diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 8721a03ad71..88f2603e6e9 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -822,16 +822,6 @@ namespace ts { return react; } - export function createReactSpread(reactNamespace: string, segments: Expression[], parentElement: JsxOpeningLikeElement) { - return createCall( - createPropertyAccess( - createReactNamespace(reactNamespace, parentElement), - "__spread" - ), - segments - ); - } - export function createReactCreateElement(reactNamespace: string, tagName: Expression, props: Expression, children: Expression[], parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression { const argumentsList = [tagName]; if (props) { @@ -868,6 +858,13 @@ namespace ts { ); } + export function createAssignHelper(attributesSegments: Expression[]) { + return createCall( + createIdentifier("__assign"), + attributesSegments + ); + } + export function createParamHelper(expression: Expression, parameterOffset: number) { return createCall( createIdentifier("__param"), diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts index 17dabf60665..557eddabe85 100644 --- a/src/compiler/printer.ts +++ b/src/compiler/printer.ts @@ -26,6 +26,19 @@ var __extends = (this && this.__extends) || function (d, b) { d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); };`; + // Emit output for the __assign helper function. + // This is typically used for JSX spread attributes, + // and can be used for object literal spread properties. + 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) { @@ -173,6 +186,7 @@ const _super = (function (geti, seti) { let currentText: string; let currentFileIdentifiers: Map; let extendsEmitted: boolean; + let assignEmitted: boolean; let decorateEmitted: boolean; let paramEmitted: boolean; let awaiterEmitted: boolean; @@ -232,6 +246,7 @@ const _super = (function (geti, seti) { currentSourceFile = undefined; currentText = undefined; extendsEmitted = false; + assignEmitted = false; decorateEmitted = false; paramEmitted = false; awaiterEmitted = false; @@ -2023,6 +2038,11 @@ const _super = (function (geti, seti) { helpersEmitted = 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) { diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 7dfe84b0b11..6a90fd0ecaf 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -100,9 +100,9 @@ namespace ts { } // Either emit one big object literal (no spread attribs), or - // a call to React.__spread + // a call to the __assign helper. objectProperties = singleOrUndefined(segments) - || createReactSpread(compilerOptions.reactNamespace, segments, node); + || createAssignHelper(segments); } const element = createReactCreateElement( diff --git a/tests/baselines/reference/reactNamespaceJSXEmit.js b/tests/baselines/reference/reactNamespaceJSXEmit.js index b39c1c1633a..3a21504bb80 100644 --- a/tests/baselines/reference/reactNamespaceJSXEmit.js +++ b/tests/baselines/reference/reactNamespaceJSXEmit.js @@ -21,8 +21,8 @@ var __assign = (this && this.__assign) || Object.assign || function(t) { } return t; }; -myReactLib.createElement("foo", {data: true}); -myReactLib.createElement(Bar, {x: x}); +myReactLib.createElement("foo", { data: true }); +myReactLib.createElement(Bar, { x: x }); myReactLib.createElement("x-component", null); myReactLib.createElement(Bar, __assign({}, x)); myReactLib.createElement(Bar, __assign({}, x, { y: 2 })); diff --git a/tests/baselines/reference/tsxExternalModuleEmit2.js b/tests/baselines/reference/tsxExternalModuleEmit2.js index 384e04a8e71..6c01a48af78 100644 --- a/tests/baselines/reference/tsxExternalModuleEmit2.js +++ b/tests/baselines/reference/tsxExternalModuleEmit2.js @@ -27,7 +27,7 @@ var __assign = (this && this.__assign) || Object.assign || function(t) { } return t; }; -var mod_1 = require('mod'); +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