From 0adc76bd2b255d2f07ec5bc5bda285e53385b9b4 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 14 Nov 2016 08:52:16 -0800 Subject: [PATCH 1/2] Test object spread+async emit & nested spread emit --- tests/baselines/reference/objectRest2.js | 42 +++++++++++++++++ tests/baselines/reference/objectRest2.symbols | 34 ++++++++++++++ tests/baselines/reference/objectRest2.types | 45 +++++++++++++++++++ tests/baselines/reference/objectSpread.js | 2 +- .../conformance/types/rest/objectRest2.ts | 15 +++++++ 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/objectRest2.js create mode 100644 tests/baselines/reference/objectRest2.symbols create mode 100644 tests/baselines/reference/objectRest2.types create mode 100644 tests/cases/conformance/types/rest/objectRest2.ts diff --git a/tests/baselines/reference/objectRest2.js b/tests/baselines/reference/objectRest2.js new file mode 100644 index 00000000000..e21c8c79853 --- /dev/null +++ b/tests/baselines/reference/objectRest2.js @@ -0,0 +1,42 @@ +//// [objectRest2.ts] +// test for #12203 +declare function connectionFromArray(objects: number, args: any): {}; +function rootConnection(name: string) { + return { + resolve: async (context, args) => { + const { objects } = await { objects: 12 }; + return { + ...connectionFromArray(objects, args) + }; + } + }; +} +rootConnection('test'); + + +//// [objectRest2.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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments)).next()); + }); +}; +function rootConnection(name) { + return { + resolve: (context, args) => __awaiter(this, void 0, void 0, function* () { + const { objects } = yield { objects: 12 }; + return __assign({}, connectionFromArray(objects, args)); + }) + }; +} +rootConnection('test'); diff --git a/tests/baselines/reference/objectRest2.symbols b/tests/baselines/reference/objectRest2.symbols new file mode 100644 index 00000000000..42532f5d183 --- /dev/null +++ b/tests/baselines/reference/objectRest2.symbols @@ -0,0 +1,34 @@ +=== tests/cases/conformance/types/rest/objectRest2.ts === +// test for #12203 +declare function connectionFromArray(objects: number, args: any): {}; +>connectionFromArray : Symbol(connectionFromArray, Decl(objectRest2.ts, 0, 0)) +>objects : Symbol(objects, Decl(objectRest2.ts, 1, 37)) +>args : Symbol(args, Decl(objectRest2.ts, 1, 53)) + +function rootConnection(name: string) { +>rootConnection : Symbol(rootConnection, Decl(objectRest2.ts, 1, 69)) +>name : Symbol(name, Decl(objectRest2.ts, 2, 24)) + + return { + resolve: async (context, args) => { +>resolve : Symbol(resolve, Decl(objectRest2.ts, 3, 10)) +>context : Symbol(context, Decl(objectRest2.ts, 4, 20)) +>args : Symbol(args, Decl(objectRest2.ts, 4, 28)) + + const { objects } = await { objects: 12 }; +>objects : Symbol(objects, Decl(objectRest2.ts, 5, 15)) +>objects : Symbol(objects, Decl(objectRest2.ts, 5, 35)) + + return { + ...connectionFromArray(objects, args) +>connectionFromArray : Symbol(connectionFromArray, Decl(objectRest2.ts, 0, 0)) +>objects : Symbol(objects, Decl(objectRest2.ts, 5, 15)) +>args : Symbol(args, Decl(objectRest2.ts, 4, 28)) + + }; + } + }; +} +rootConnection('test'); +>rootConnection : Symbol(rootConnection, Decl(objectRest2.ts, 1, 69)) + diff --git a/tests/baselines/reference/objectRest2.types b/tests/baselines/reference/objectRest2.types new file mode 100644 index 00000000000..8e89a3cb573 --- /dev/null +++ b/tests/baselines/reference/objectRest2.types @@ -0,0 +1,45 @@ +=== tests/cases/conformance/types/rest/objectRest2.ts === +// test for #12203 +declare function connectionFromArray(objects: number, args: any): {}; +>connectionFromArray : (objects: number, args: any) => {} +>objects : number +>args : any + +function rootConnection(name: string) { +>rootConnection : (name: string) => { resolve: (context: any, args: any) => Promise<{}>; } +>name : string + + return { +>{ resolve: async (context, args) => { const { objects } = await { objects: 12 }; return { ...connectionFromArray(objects, args) }; } } : { resolve: (context: any, args: any) => Promise<{}>; } + + resolve: async (context, args) => { +>resolve : (context: any, args: any) => Promise<{}> +>async (context, args) => { const { objects } = await { objects: 12 }; return { ...connectionFromArray(objects, args) }; } : (context: any, args: any) => Promise<{}> +>context : any +>args : any + + const { objects } = await { objects: 12 }; +>objects : number +>await { objects: 12 } : { objects: number; } +>{ objects: 12 } : { objects: number; } +>objects : number +>12 : 12 + + return { +>{ ...connectionFromArray(objects, args) } : {} + + ...connectionFromArray(objects, args) +>connectionFromArray(objects, args) : {} +>connectionFromArray : (objects: number, args: any) => {} +>objects : number +>args : any + + }; + } + }; +} +rootConnection('test'); +>rootConnection('test') : { resolve: (context: any, args: any) => Promise<{}>; } +>rootConnection : (name: string) => { resolve: (context: any, args: any) => Promise<{}>; } +>'test' : "test" + diff --git a/tests/baselines/reference/objectSpread.js b/tests/baselines/reference/objectSpread.js index d1de48c5cab..4305e17ab31 100644 --- a/tests/baselines/reference/objectSpread.js +++ b/tests/baselines/reference/objectSpread.js @@ -105,7 +105,7 @@ var combinedMid = __assign({}, o, { b: 'ok' }, o2); var combinedAfter = __assign({}, o, o2, { b: 'ok' }); var combinedNested = __assign({}, __assign({ a: 4 }, { b: false, c: 'overriden' }), { d: 'actually new' }, { a: 5, d: 'maybe new' }); var combinedNestedChangeType = __assign({}, __assign({ a: 1 }, { b: false, c: 'overriden' }), { c: -1 }); -var propertyNested = __assign({ a: __assign({}, o) }); +var propertyNested = { a: __assign({}, o) }; // accessors don't copy the descriptor // (which means that readonly getters become read/write properties) var op = { get a() { return 6; } }; diff --git a/tests/cases/conformance/types/rest/objectRest2.ts b/tests/cases/conformance/types/rest/objectRest2.ts new file mode 100644 index 00000000000..4a38123f1ac --- /dev/null +++ b/tests/cases/conformance/types/rest/objectRest2.ts @@ -0,0 +1,15 @@ +// @lib: es2015 +// @target: es2015 +// test for #12203 +declare function connectionFromArray(objects: number, args: any): {}; +function rootConnection(name: string) { + return { + resolve: async (context, args) => { + const { objects } = await { objects: 12 }; + return { + ...connectionFromArray(objects, args) + }; + } + }; +} +rootConnection('test'); From fab1416dd26339a7338d009faeb025d37ef0c91b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 14 Nov 2016 08:58:29 -0800 Subject: [PATCH 2/2] Fixes for object spread emit 1. Retain function modifiers. They were previously dropped. 2. Do not emit __assign for object literals with no spreads, just visit children. 3. call aggregateTransformFlags after creating an __assign call. --- src/compiler/transformers/esnext.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 1fad209bdb3..eaaa1e416cd 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -92,11 +92,15 @@ namespace ts { // { a, ...o, b } => __assign({a}, o, {b}); // If the first element is a spread element, then the first argument to __assign is {}: // { ...o, a, b, ...o2 } => __assign({}, o, {a, b}, o2) - const objects = chunkObjectLiteralElements(node.properties); - if (objects.length && objects[0].kind !== SyntaxKind.ObjectLiteralExpression) { - objects.unshift(createObjectLiteral()); + if (forEach(node.properties, p => p.kind === SyntaxKind.SpreadAssignment)) { + const objects = chunkObjectLiteralElements(node.properties); + if (objects.length && objects[0].kind !== SyntaxKind.ObjectLiteralExpression) { + objects.unshift(createObjectLiteral()); + } + + return aggregateTransformFlags(createCall(createIdentifier("__assign"), undefined, objects)); } - return createCall(createIdentifier("__assign"), undefined, objects); + return visitEachChild(node, visitor, context); } /** @@ -235,7 +239,7 @@ namespace ts { visitEachChild(node.body, visitor, context); const func = setOriginalNode( createArrowFunction( - /*modifiers*/ undefined, + node.modifiers, /*typeParameters*/ undefined, visitNodes(node.parameters, visitor, isParameter), /*type*/ undefined, @@ -256,7 +260,7 @@ namespace ts { visitEachChild(node.body, visitor, context); return setOriginalNode( createFunctionExpression( - /*modifiers*/ undefined, + node.modifiers, node.asteriskToken, name, /*typeParameters*/ undefined,