From e9f984d3cedc689f89c33bcf5c2524ab3055b0cd Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 7 Apr 2016 18:30:26 -0700 Subject: [PATCH] Use an emit helper for JSX Spread Attributes. --- src/compiler/binder.ts | 9 +++++++++ src/compiler/emitter.ts | 23 +++++++++++++++++++---- src/compiler/types.ts | 6 +++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 98bc54e88c3..642eb28ae3d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -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 @@ -161,6 +162,7 @@ namespace ts { hasAsyncFunctions = false; hasDecorators = false; hasParameterDecorators = false; + hasJsxSpreadAttribute = false; } return bindSourceFile; @@ -498,6 +500,9 @@ namespace ts { if (hasAsyncFunctions) { flags |= NodeFlags.HasAsyncFunctions; } + if (hasJsxSpreadAttribute) { + flags |= NodeFlags.HasJsxSpreadAttribute; + } } node.flags = flags; @@ -1289,6 +1294,10 @@ namespace ts { case SyntaxKind.EnumMember: return bindPropertyOrMethodOrAccessor(node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes); + case SyntaxKind.JsxSpreadAttribute: + hasJsxSpreadAttribute = true; + return; + case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 212d9f05510..1d72dcdb683 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -345,6 +345,15 @@ 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 i = 1, n = arguments.length; i < n; i++) { + var s = arguments[i]; + if (s != null) for (var p in s) if (s.hasOwnProperty(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) { @@ -540,6 +549,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; @@ -623,6 +633,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; @@ -1259,11 +1270,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++) { @@ -7610,11 +7620,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) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 2692354258f..374f2c9ff62 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -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 @@ -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,