Skip to content

Commit a7bf690

Browse files
Merge pull request #7952 from Microsoft/objectAssignPoly
Use an emit helper (or Object.assign) for JsxSpreadAttributes
2 parents 58efc2e + 73dbe41 commit a7bf690

File tree

9 files changed

+89
-15
lines changed

9 files changed

+89
-15
lines changed

src/compiler/binder.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ namespace ts {
122122
let hasAsyncFunctions: boolean;
123123
let hasDecorators: boolean;
124124
let hasParameterDecorators: boolean;
125+
let hasJsxSpreadAttribute: boolean;
125126

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

166168
return bindSourceFile;
@@ -498,6 +500,9 @@ namespace ts {
498500
if (hasAsyncFunctions) {
499501
flags |= NodeFlags.HasAsyncFunctions;
500502
}
503+
if (hasJsxSpreadAttribute) {
504+
flags |= NodeFlags.HasJsxSpreadAttribute;
505+
}
501506
}
502507

503508
node.flags = flags;
@@ -1298,6 +1303,10 @@ namespace ts {
12981303
case SyntaxKind.EnumMember:
12991304
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes);
13001305

1306+
case SyntaxKind.JsxSpreadAttribute:
1307+
hasJsxSpreadAttribute = true;
1308+
return;
1309+
13011310
case SyntaxKind.CallSignature:
13021311
case SyntaxKind.ConstructSignature:
13031312
case SyntaxKind.IndexSignature:

src/compiler/emitter.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,16 @@ var __extends = (this && this.__extends) || function (d, b) {
345345
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
346346
};`;
347347

348+
const assignHelper = `
349+
var __assign = (this && this.__assign) || Object.assign || function(t) {
350+
for (var s, i = 1, n = arguments.length; i < n; i++) {
351+
s = arguments[i];
352+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
353+
t[p] = s[p];
354+
}
355+
return t;
356+
};`;
357+
348358
// emit output for the __decorate helper function
349359
const decorateHelper = `
350360
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
@@ -542,6 +552,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
542552
let convertedLoopState: ConvertedLoopState;
543553

544554
let extendsEmitted: boolean;
555+
let assignEmitted: boolean;
545556
let decorateEmitted: boolean;
546557
let paramEmitted: boolean;
547558
let awaiterEmitted: boolean;
@@ -625,6 +636,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
625636
decorateEmitted = false;
626637
paramEmitted = false;
627638
awaiterEmitted = false;
639+
assignEmitted = false;
628640
tempFlags = 0;
629641
tempVariables = undefined;
630642
tempParameters = undefined;
@@ -1261,11 +1273,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
12611273
}
12621274
else {
12631275
// Either emit one big object literal (no spread attribs), or
1264-
// a call to React.__spread
1276+
// a call to the __assign helper
12651277
const attrs = openingNode.attributes;
12661278
if (forEach(attrs, attr => attr.kind === SyntaxKind.JsxSpreadAttribute)) {
1267-
emitExpressionIdentifier(syntheticReactRef);
1268-
write(".__spread(");
1279+
write("__assign(");
12691280

12701281
let haveOpenedObjectLiteral = false;
12711282
for (let i = 0; i < attrs.length; i++) {
@@ -7704,11 +7715,16 @@ const _super = (function (geti, seti) {
77047715
if (!compilerOptions.noEmitHelpers) {
77057716
// Only Emit __extends function when target ES5.
77067717
// For target ES6 and above, we can emit classDeclaration as is.
7707-
if ((languageVersion < ScriptTarget.ES6) && (!extendsEmitted && node.flags & NodeFlags.HasClassExtends)) {
7718+
if (languageVersion < ScriptTarget.ES6 && !extendsEmitted && node.flags & NodeFlags.HasClassExtends) {
77087719
writeLines(extendsHelper);
77097720
extendsEmitted = true;
77107721
}
77117722

7723+
if (compilerOptions.jsx !== JsxEmit.Preserve && !assignEmitted && (node.flags & NodeFlags.HasJsxSpreadAttribute)) {
7724+
writeLines(assignHelper);
7725+
assignEmitted = true;
7726+
}
7727+
77127728
if (!decorateEmitted && node.flags & NodeFlags.HasDecorators) {
77137729
writeLines(decorateHelper);
77147730
if (compilerOptions.emitDecoratorMetadata) {

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ namespace ts {
405405
JavaScriptFile = 1 << 27, // If node was parsed in a JavaScript
406406
ThisNodeOrAnySubNodesHasError = 1 << 28, // If this node or any of its children had an error
407407
HasAggregatedChildData = 1 << 29, // If we've computed data from children and cached it in this node
408+
HasJsxSpreadAttribute = 1 << 30,
408409

409410
Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async,
410411
AccessibilityModifier = Public | Private | Protected,

tests/baselines/reference/reactNamespaceJSXEmit.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,16 @@ declare var x: any;
1313

1414

1515
//// [reactNamespaceJSXEmit.js]
16+
var __assign = (this && this.__assign) || Object.assign || function(t) {
17+
for (var s, i = 1, n = arguments.length; i < n; i++) {
18+
s = arguments[i];
19+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
20+
t[p] = s[p];
21+
}
22+
return t;
23+
};
1624
myReactLib.createElement("foo", {data: true});
1725
myReactLib.createElement(Bar, {x: x});
1826
myReactLib.createElement("x-component", null);
19-
myReactLib.createElement(Bar, myReactLib.__spread({}, x));
20-
myReactLib.createElement(Bar, myReactLib.__spread({}, x, {y: 2}));
27+
myReactLib.createElement(Bar, __assign({}, x));
28+
myReactLib.createElement(Bar, __assign({}, x, {y: 2}));

tests/baselines/reference/tsxExternalModuleEmit2.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,16 @@ declare var Foo, React;
1919

2020
//// [app.js]
2121
"use strict";
22+
var __assign = (this && this.__assign) || Object.assign || function(t) {
23+
for (var s, i = 1, n = arguments.length; i < n; i++) {
24+
s = arguments[i];
25+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
26+
t[p] = s[p];
27+
}
28+
return t;
29+
};
2230
var mod_1 = require('mod');
2331
// Should see mod_1['default'] in emit here
2432
React.createElement(Foo, {handler: mod_1["default"]});
2533
// Should see mod_1['default'] in emit here
26-
React.createElement(Foo, React.__spread({}, mod_1["default"]));
34+
React.createElement(Foo, __assign({}, mod_1["default"]));

tests/baselines/reference/tsxReactEmit2.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,17 @@ var spreads5 = <div x={p2} {...p1} y={p3}>{p2}</div>;
1616

1717

1818
//// [file.js]
19+
var __assign = (this && this.__assign) || Object.assign || function(t) {
20+
for (var s, i = 1, n = arguments.length; i < n; i++) {
21+
s = arguments[i];
22+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
23+
t[p] = s[p];
24+
}
25+
return t;
26+
};
1927
var p1, p2, p3;
20-
var spreads1 = React.createElement("div", React.__spread({}, p1), p2);
21-
var spreads2 = React.createElement("div", React.__spread({}, p1), p2);
22-
var spreads3 = React.createElement("div", React.__spread({x: p3}, p1), p2);
23-
var spreads4 = React.createElement("div", React.__spread({}, p1, {x: p3}), p2);
24-
var spreads5 = React.createElement("div", React.__spread({x: p2}, p1, {y: p3}), p2);
28+
var spreads1 = React.createElement("div", __assign({}, p1), p2);
29+
var spreads2 = React.createElement("div", __assign({}, p1), p2);
30+
var spreads3 = React.createElement("div", __assign({x: p3}, p1), p2);
31+
var spreads4 = React.createElement("div", __assign({}, p1, {x: p3}), p2);
32+
var spreads5 = React.createElement("div", __assign({x: p2}, p1, {y: p3}), p2);

tests/baselines/reference/tsxReactEmit4.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@ var openClosed1 = <div>
1818
var spread1 = <div {...p} x={0} />;
1919

2020
//// [file.js]
21+
var __assign = (this && this.__assign) || Object.assign || function(t) {
22+
for (var s, i = 1, n = arguments.length; i < n; i++) {
23+
s = arguments[i];
24+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
25+
t[p] = s[p];
26+
}
27+
return t;
28+
};
2129
var p;
2230
var openClosed1 = React.createElement("div", null, blah);
2331
// Should emit React.__spread({}, p, {x: 0})
24-
var spread1 = React.createElement("div", React.__spread({}, p, {x: 0}));
32+
var spread1 = React.createElement("div", __assign({}, p, {x: 0}));

tests/baselines/reference/tsxReactEmit5.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,16 @@ var spread1 = <div x='' {...foo} y='' />;
2323
//// [file.js]
2424
//// [react-consumer.js]
2525
"use strict";
26+
var __assign = (this && this.__assign) || Object.assign || function(t) {
27+
for (var s, i = 1, n = arguments.length; i < n; i++) {
28+
s = arguments[i];
29+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
30+
t[p] = s[p];
31+
}
32+
return t;
33+
};
2634
var test_1 = require("./test");
2735
// Should emit test_1.React.createElement
2836
// and React.__spread
2937
var foo;
30-
var spread1 = test_1.React.createElement("div", test_1.React.__spread({x: ''}, foo, {y: ''}));
38+
var spread1 = test_1.React.createElement("div", __assign({x: ''}, foo, {y: ''}));

tests/baselines/reference/tsxReactEmit6.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ namespace M {
2828

2929
//// [file.js]
3030
//// [react-consumer.js]
31+
var __assign = (this && this.__assign) || Object.assign || function(t) {
32+
for (var s, i = 1, n = arguments.length; i < n; i++) {
33+
s = arguments[i];
34+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
35+
t[p] = s[p];
36+
}
37+
return t;
38+
};
3139
var M;
3240
(function (M) {
3341
})(M || (M = {}));
@@ -36,7 +44,7 @@ var M;
3644
// Should emit M.React.createElement
3745
// and M.React.__spread
3846
var foo;
39-
var spread1 = M.React.createElement("div", M.React.__spread({x: ''}, foo, {y: ''}));
47+
var spread1 = M.React.createElement("div", __assign({x: ''}, foo, {y: ''}));
4048
// Quotes
4149
var x = M.React.createElement("div", null, "This \"quote\" thing");
4250
})(M || (M = {}));

0 commit comments

Comments
 (0)