Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ namespace ts {
let hasAsyncFunctions: boolean;
let hasDecorators: boolean;
let hasParameterDecorators: boolean;
let hasJsxSpreadAttribute: boolean;

// If this file is an external module, then it is automatically in strict-mode according to
// ES6. If it is not an external module, then we'll determine if it is in strict mode or
Expand Down Expand Up @@ -161,6 +162,7 @@ namespace ts {
hasAsyncFunctions = false;
hasDecorators = false;
hasParameterDecorators = false;
hasJsxSpreadAttribute = false;
}

return bindSourceFile;
Expand Down Expand Up @@ -498,6 +500,9 @@ namespace ts {
if (hasAsyncFunctions) {
flags |= NodeFlags.HasAsyncFunctions;
}
if (hasJsxSpreadAttribute) {
flags |= NodeFlags.HasJsxSpreadAttribute;
}
}

node.flags = flags;
Expand Down Expand Up @@ -1289,6 +1294,10 @@ namespace ts {
case SyntaxKind.EnumMember:
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes);

case SyntaxKind.JsxSpreadAttribute:
hasJsxSpreadAttribute = true;
return;

case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
Expand Down
24 changes: 20 additions & 4 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,16 @@ var __extends = (this && this.__extends) || function (d, b) {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};`;

const assignHelper = `
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};`;

// emit output for the __decorate helper function
const decorateHelper = `
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
Expand Down Expand Up @@ -540,6 +550,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
let convertedLoopState: ConvertedLoopState;

let extendsEmitted: boolean;
let assignEmitted: boolean;
let decorateEmitted: boolean;
let paramEmitted: boolean;
let awaiterEmitted: boolean;
Expand Down Expand Up @@ -623,6 +634,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
decorateEmitted = false;
paramEmitted = false;
awaiterEmitted = false;
assignEmitted = false;
tempFlags = 0;
tempVariables = undefined;
tempParameters = undefined;
Expand Down Expand Up @@ -1259,11 +1271,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
else {
// Either emit one big object literal (no spread attribs), or
// a call to React.__spread
// a call to the __assign helper
const attrs = openingNode.attributes;
if (forEach(attrs, attr => attr.kind === SyntaxKind.JsxSpreadAttribute)) {
emitExpressionIdentifier(syntheticReactRef);
write(".__spread(");
write("__assign(");

let haveOpenedObjectLiteral = false;
for (let i = 0; i < attrs.length; i++) {
Expand Down Expand Up @@ -7610,11 +7621,16 @@ const _super = (function (geti, seti) {
if (!compilerOptions.noEmitHelpers) {
// Only Emit __extends function when target ES5.
// For target ES6 and above, we can emit classDeclaration as is.
if ((languageVersion < ScriptTarget.ES6) && (!extendsEmitted && node.flags & NodeFlags.HasClassExtends)) {
if (languageVersion < ScriptTarget.ES6 && !extendsEmitted && node.flags & NodeFlags.HasClassExtends) {
writeLines(extendsHelper);
extendsEmitted = true;
}

if (compilerOptions.jsx !== JsxEmit.Preserve && !assignEmitted && (node.flags & NodeFlags.HasJsxSpreadAttribute)) {
writeLines(assignHelper);
assignEmitted = true;
}

if (!decorateEmitted && node.flags & NodeFlags.HasDecorators) {
writeLines(decorateHelper);
if (compilerOptions.emitDecoratorMetadata) {
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ namespace ts {
FirstNode = QualifiedName,
}

export const enum NodeFlags {
export const enum NodeFlags {
None = 0,
Export = 1 << 1, // Declarations
Ambient = 1 << 2, // Declarations
Expand Down Expand Up @@ -397,6 +397,10 @@ namespace ts {
HasParamDecorators = 1 << 24, // If the file has parameter decorators (initialized by binding)
HasAsyncFunctions = 1 << 25, // If the file has async functions (initialized by binding)

// This was picked out from the 'master' branch.
// To keep the flags consistent, we're skipping a few ahead.
HasJsxSpreadAttribute = 1 << 30,

Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async,
AccessibilityModifier = Public | Private | Protected,
BlockScoped = Let | Const,
Expand Down
12 changes: 10 additions & 2 deletions tests/baselines/reference/reactNamespaceJSXEmit.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@ declare var x: any;


//// [reactNamespaceJSXEmit.js]
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
myReactLib.createElement("foo", {data: true});
myReactLib.createElement(Bar, {x: x});
myReactLib.createElement("x-component", null);
myReactLib.createElement(Bar, myReactLib.__spread({}, x));
myReactLib.createElement(Bar, myReactLib.__spread({}, x, {y: 2}));
myReactLib.createElement(Bar, __assign({}, x));
myReactLib.createElement(Bar, __assign({}, x, {y: 2}));
10 changes: 9 additions & 1 deletion tests/baselines/reference/tsxExternalModuleEmit2.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,16 @@ declare var Foo, React;

//// [app.js]
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var mod_1 = require('mod');
// Should see mod_1['default'] in emit here
React.createElement(Foo, {handler: mod_1["default"]});
// Should see mod_1['default'] in emit here
React.createElement(Foo, React.__spread({}, mod_1["default"]));
React.createElement(Foo, __assign({}, mod_1["default"]));
18 changes: 13 additions & 5 deletions tests/baselines/reference/tsxReactEmit2.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ var spreads5 = <div x={p2} {...p1} y={p3}>{p2}</div>;


//// [file.js]
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var p1, p2, p3;
var spreads1 = React.createElement("div", React.__spread({}, p1), p2);
var spreads2 = React.createElement("div", React.__spread({}, p1), p2);
var spreads3 = React.createElement("div", React.__spread({x: p3}, p1), p2);
var spreads4 = React.createElement("div", React.__spread({}, p1, {x: p3}), p2);
var spreads5 = React.createElement("div", React.__spread({x: p2}, p1, {y: p3}), p2);
var spreads1 = React.createElement("div", __assign({}, p1), p2);
var spreads2 = React.createElement("div", __assign({}, p1), p2);
var spreads3 = React.createElement("div", __assign({x: p3}, p1), p2);
var spreads4 = React.createElement("div", __assign({}, p1, {x: p3}), p2);
var spreads5 = React.createElement("div", __assign({x: p2}, p1, {y: p3}), p2);
10 changes: 9 additions & 1 deletion tests/baselines/reference/tsxReactEmit4.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@ var openClosed1 = <div>
var spread1 = <div {...p} x={0} />;

//// [file.js]
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var p;
var openClosed1 = React.createElement("div", null, blah);
// Should emit React.__spread({}, p, {x: 0})
var spread1 = React.createElement("div", React.__spread({}, p, {x: 0}));
var spread1 = React.createElement("div", __assign({}, p, {x: 0}));
10 changes: 9 additions & 1 deletion tests/baselines/reference/tsxReactEmit5.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@ var spread1 = <div x='' {...foo} y='' />;
//// [file.js]
//// [react-consumer.js]
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var test_1 = require("./test");
// Should emit test_1.React.createElement
// and React.__spread
var foo;
var spread1 = test_1.React.createElement("div", test_1.React.__spread({x: ''}, foo, {y: ''}));
var spread1 = test_1.React.createElement("div", __assign({x: ''}, foo, {y: ''}));
10 changes: 9 additions & 1 deletion tests/baselines/reference/tsxReactEmit6.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ namespace M {

//// [file.js]
//// [react-consumer.js]
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var M;
(function (M) {
})(M || (M = {}));
Expand All @@ -36,7 +44,7 @@ var M;
// Should emit M.React.createElement
// and M.React.__spread
var foo;
var spread1 = M.React.createElement("div", M.React.__spread({x: ''}, foo, {y: ''}));
var spread1 = M.React.createElement("div", __assign({x: ''}, foo, {y: ''}));
// Quotes
var x = M.React.createElement("div", null, "This \"quote\" thing");
})(M || (M = {}));