From 29d667dd1f13640b0be7fa1dec82fe35c9909bbe Mon Sep 17 00:00:00 2001 From: Joseph Watts Date: Fri, 26 Oct 2018 11:28:24 -0400 Subject: [PATCH 1/4] Fix microsoft/TypeScript#27864 Signed-off-by: Joseph Watts --- src/compiler/checker.ts | 17 +++++++++++++++++ src/compiler/transformer.ts | 14 ++++++++++++-- src/compiler/transformers/esnext.ts | 15 +++++++++++++++ src/compiler/types.ts | 7 ++++++- 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 909ec5e82b21b..9ac68cbaec7d9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17487,6 +17487,23 @@ namespace ts { const links = getNodeLinks(node.expression); if (!links.resolvedType) { links.resolvedType = checkExpression(node.expression); + + if (languageVersion < ScriptTarget.ESNext && isPropertyDeclaration(node.parent) && isClassLike(node.parent.parent)) { + const container = getEnclosingBlockScopeContainer(node); + let current = container; + let containedInIterationStatement = false; + while (current && !nodeStartsNewLexicalEnvironment(current)) { + if (isIterationStatement(current, /*lookInLabeledStatements*/ false)) { + containedInIterationStatement = true; + break; + } + current = current.parent; + } + if (containedInIterationStatement) { + getNodeLinks(current).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; + } + links.flags |= NodeCheckFlags.BlockScopedBindingInLoop; + } // This will allow types number, string, symbol or any. It will also allow enums, the unknown // type, and any union of these types (like string | number). if (links.resolvedType.flags & TypeFlags.Nullable || diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index b78202e0c3d58..e3bf3d8c68421 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -84,6 +84,8 @@ namespace ts { let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[]; let lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = []; let lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = []; + let lexicalEnvironmentScopingStack: LexicalEnvironmentScoping[] = []; + let lexicalEnvironmentScoping: LexicalEnvironmentScoping; let lexicalEnvironmentStackOffset = 0; let lexicalEnvironmentSuspended = false; let emitHelpers: EmitHelper[] | undefined; @@ -258,7 +260,7 @@ namespace ts { * Starts a new lexical environment. Any existing hoisted variable or function declarations * are pushed onto a stack, and the related storage variables are reset. */ - function startLexicalEnvironment(): void { + function startLexicalEnvironment(scoping: LexicalEnvironmentScoping = LexicalEnvironmentScoping.Function): void { Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); @@ -267,11 +269,13 @@ namespace ts { // stack size variable. This allows us to reuse existing array slots we've // already allocated between transformations to avoid allocation and GC overhead during // transformation. + lexicalEnvironmentScopingStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentScoping; lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentVariableDeclarations; lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFunctionDeclarations; lexicalEnvironmentStackOffset++; lexicalEnvironmentVariableDeclarations = undefined!; lexicalEnvironmentFunctionDeclarations = undefined!; + lexicalEnvironmentScoping = scoping; } /** Suspends the current lexical environment, usually after visiting a parameter list. */ @@ -308,7 +312,10 @@ namespace ts { if (lexicalEnvironmentVariableDeclarations) { const statement = createVariableStatement( /*modifiers*/ undefined, - createVariableDeclarationList(lexicalEnvironmentVariableDeclarations) + createVariableDeclarationList( + lexicalEnvironmentVariableDeclarations, + lexicalEnvironmentScoping === LexicalEnvironmentScoping.Block ? NodeFlags.Let : undefined + ) ); if (!statements) { @@ -324,9 +331,11 @@ namespace ts { lexicalEnvironmentStackOffset--; lexicalEnvironmentVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset]; lexicalEnvironmentFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset]; + lexicalEnvironmentScoping = lexicalEnvironmentScopingStack[lexicalEnvironmentStackOffset]; if (lexicalEnvironmentStackOffset === 0) { lexicalEnvironmentVariableDeclarationsStack = []; lexicalEnvironmentFunctionDeclarationsStack = []; + lexicalEnvironmentScopingStack = []; } return statements; } @@ -358,6 +367,7 @@ namespace ts { lexicalEnvironmentVariableDeclarationsStack = undefined!; lexicalEnvironmentFunctionDeclarations = undefined!; lexicalEnvironmentFunctionDeclarationsStack = undefined!; + lexicalEnvironmentScopingStack = undefined!; onSubstituteNode = undefined!; onEmitNode = undefined!; emitHelpers = undefined; diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 73a55f8aa041e..b6a99e63a45fd 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -12,6 +12,7 @@ namespace ts { export function transformESNext(context: TransformationContext) { const { + startLexicalEnvironment, resumeLexicalEnvironment, endLexicalEnvironment, hoistVariableDeclaration @@ -84,6 +85,8 @@ namespace ts { return node; } switch (node.kind) { + case SyntaxKind.Block: + return visitBlock(node as Block); case SyntaxKind.AwaitExpression: return visitAwaitExpression(node as AwaitExpression); case SyntaxKind.YieldExpression: @@ -503,6 +506,18 @@ namespace ts { } } + function visitBlock(node: Block): Block { + startLexicalEnvironment(LexicalEnvironmentScoping.Block); + node = visitEachChild(node, visitor, context); + const declarations = endLexicalEnvironment(); + if (some(declarations)) { + return updateBlock( + node, + mergeLexicalEnvironment(node.statements, declarations) + ); + } + return node; + } function visitAwaitExpression(node: AwaitExpression): Expression { if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 378ce8b9cbc84..d7dd0dabcce06 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5229,6 +5229,11 @@ namespace ts { writeFile: WriteFileCallback; } + export const enum LexicalEnvironmentScoping { + Function, + Block + }; + export interface TransformationContext { /*@internal*/ getEmitResolver(): EmitResolver; /*@internal*/ getEmitHost(): EmitHost; @@ -5237,7 +5242,7 @@ namespace ts { getCompilerOptions(): CompilerOptions; /** Starts a new lexical environment. */ - startLexicalEnvironment(): void; + startLexicalEnvironment(scoping?: LexicalEnvironmentScoping): void; /** Suspends the current lexical environment, usually after visiting a parameter list. */ suspendLexicalEnvironment(): void; From cf947c557f454aa96a9c15f4f5cdee0bbc2b7785 Mon Sep 17 00:00:00 2001 From: Max Heiber Date: Sat, 27 Oct 2018 11:46:22 -0400 Subject: [PATCH 2/4] Tests for computed field scope fix Signed-off-by: Max Heiber --- src/testRunner/tsconfig.json | 1 + .../unittests/evaluation/computedFieldLoop.ts | 30 ++++++++++++ .../reference/api/tsserverlibrary.d.ts | 6 ++- tests/baselines/reference/api/typescript.d.ts | 6 ++- .../baselines/reference/classBlockScoping.js | 2 +- .../classExpressionWithStaticProperties3.js | 2 +- ...classExpressionWithStaticPropertiesES63.js | 2 +- .../computedPropertyNames52_ES5.errors.txt | 17 +++++++ .../reference/computedPropertyNames52_ES5.js | 33 +++++++++++++ .../computedPropertyNames52_ES5.symbols | 36 ++++++++++++++ .../computedPropertyNames52_ES5.types | 47 +++++++++++++++++++ .../computedPropertyNames52_ES6.errors.txt | 17 +++++++ .../reference/computedPropertyNames52_ES6.js | 28 +++++++++++ .../computedPropertyNames52_ES6.symbols | 36 ++++++++++++++ .../computedPropertyNames52_ES6.types | 47 +++++++++++++++++++ .../reference/emitter.forAwait.es2015.js | 6 +-- .../reference/emitter.forAwait.es2017.js | 6 +-- .../computedPropertyNames52_ES5.ts | 12 +++++ .../computedPropertyNames52_ES6.ts | 12 +++++ 19 files changed, 335 insertions(+), 11 deletions(-) create mode 100644 src/testRunner/unittests/evaluation/computedFieldLoop.ts create mode 100644 tests/baselines/reference/computedPropertyNames52_ES5.errors.txt create mode 100644 tests/baselines/reference/computedPropertyNames52_ES5.js create mode 100644 tests/baselines/reference/computedPropertyNames52_ES5.symbols create mode 100644 tests/baselines/reference/computedPropertyNames52_ES5.types create mode 100644 tests/baselines/reference/computedPropertyNames52_ES6.errors.txt create mode 100644 tests/baselines/reference/computedPropertyNames52_ES6.js create mode 100644 tests/baselines/reference/computedPropertyNames52_ES6.symbols create mode 100644 tests/baselines/reference/computedPropertyNames52_ES6.types create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES5.ts create mode 100644 tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES6.ts diff --git a/src/testRunner/tsconfig.json b/src/testRunner/tsconfig.json index 42edf83996495..2aab69438c6a3 100644 --- a/src/testRunner/tsconfig.json +++ b/src/testRunner/tsconfig.json @@ -88,6 +88,7 @@ "unittests/versionCache.ts", "unittests/evaluation/asyncArrow.ts", "unittests/evaluation/asyncGenerator.ts", + "unittests/evaluation/computedFieldLoop.ts", "unittests/evaluation/forAwaitOf.ts", "unittests/services/colorization.ts", "unittests/services/documentRegistry.ts", diff --git a/src/testRunner/unittests/evaluation/computedFieldLoop.ts b/src/testRunner/unittests/evaluation/computedFieldLoop.ts new file mode 100644 index 0000000000000..3c63ed607b739 --- /dev/null +++ b/src/testRunner/unittests/evaluation/computedFieldLoop.ts @@ -0,0 +1,30 @@ +describe("computed scope is correct for a computed field defined in a loop", () => { + it("return (es5)", async () => { + const result = evaluator.evaluateTypeScript(` + const classes = []; + for (let i = 0; i <= 10; ++i) { + classes.push( + class A { + [i] = "my property"; + } + ); + } + export const output = classes.map(Object.keys) + `); + + result.main(); + assert.deepEqual(result.output, [ + ['1'], + ['2'], + ['3'], + ['4'], + ['5'], + ['6'], + ['7'], + ['8'], + ['9'], + ['10'], + ['bananananananan'] + ]); + }); +}); \ No newline at end of file diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ebb179af202a1..e2ef954dcfed6 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2757,11 +2757,15 @@ declare namespace ts { MappedTypeParameter = 3, Unspecified = 4 } + enum LexicalEnvironmentScoping { + Function = 0, + Block = 1 + } interface TransformationContext { /** Gets the compiler options supplied to the transformer. */ getCompilerOptions(): CompilerOptions; /** Starts a new lexical environment. */ - startLexicalEnvironment(): void; + startLexicalEnvironment(scoping?: LexicalEnvironmentScoping): void; /** Suspends the current lexical environment, usually after visiting a parameter list. */ suspendLexicalEnvironment(): void; /** Resumes a suspended lexical environment, usually before visiting a function body. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 7d00bfb714bdc..f26df2ab114a6 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2757,11 +2757,15 @@ declare namespace ts { MappedTypeParameter = 3, Unspecified = 4 } + enum LexicalEnvironmentScoping { + Function = 0, + Block = 1 + } interface TransformationContext { /** Gets the compiler options supplied to the transformer. */ getCompilerOptions(): CompilerOptions; /** Starts a new lexical environment. */ - startLexicalEnvironment(): void; + startLexicalEnvironment(scoping?: LexicalEnvironmentScoping): void; /** Suspends the current lexical environment, usually after visiting a parameter list. */ suspendLexicalEnvironment(): void; /** Resumes a suspended lexical environment, usually before visiting a function body. */ diff --git a/tests/baselines/reference/classBlockScoping.js b/tests/baselines/reference/classBlockScoping.js index ee3d9163b5e99..b2846a9cc1c89 100644 --- a/tests/baselines/reference/classBlockScoping.js +++ b/tests/baselines/reference/classBlockScoping.js @@ -35,9 +35,9 @@ function f(b: boolean) { //// [classBlockScoping.js] function f(b) { - var _a; var Foo; if (b) { + var _a = void 0; Foo = (_a = /** @class */ (function () { function Foo() { } diff --git a/tests/baselines/reference/classExpressionWithStaticProperties3.js b/tests/baselines/reference/classExpressionWithStaticProperties3.js index d71f02f22cb0b..120651d43c431 100644 --- a/tests/baselines/reference/classExpressionWithStaticProperties3.js +++ b/tests/baselines/reference/classExpressionWithStaticProperties3.js @@ -10,9 +10,9 @@ for (let i = 0; i < 3; i++) { arr.forEach(C => console.log(C.y())); //// [classExpressionWithStaticProperties3.js] -var _a; var arr = []; var _loop_1 = function (i) { + var _a = void 0; arr.push((_a = /** @class */ (function () { function C() { } diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES63.js b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.js index 8ff0f242f1951..b94e3aab7109e 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES63.js +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.js @@ -10,9 +10,9 @@ for (let i = 0; i < 3; i++) { arr.forEach(C => console.log(C.y())); //// [classExpressionWithStaticPropertiesES63.js] -var _a; const arr = []; for (let i = 0; i < 3; i++) { + let _a; arr.push((_a = class C { }, _a.x = i, diff --git a/tests/baselines/reference/computedPropertyNames52_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames52_ES5.errors.txt new file mode 100644 index 0000000000000..98ef7af30bfcc --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames52_ES5.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES5.ts(5,13): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES5.ts (1 errors) ==== + const classes = []; + for (let i = 0; i <= 10; ++i) { + classes.push( + class A { + [i] = "my property"; + ~~~ +!!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. + } + ); + } + for (const clazz of classes) { + console.log(Object.getOwnPropertyNames(new clazz())); + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames52_ES5.js b/tests/baselines/reference/computedPropertyNames52_ES5.js new file mode 100644 index 0000000000000..463c40ed1263d --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames52_ES5.js @@ -0,0 +1,33 @@ +//// [computedPropertyNames52_ES5.ts] +const classes = []; +for (let i = 0; i <= 10; ++i) { + classes.push( + class A { + [i] = "my property"; + } + ); +} +for (const clazz of classes) { + console.log(Object.getOwnPropertyNames(new clazz())); +} + +//// [computedPropertyNames52_ES5.js] +var classes = []; +var _loop_1 = function (i) { + var _a = void 0, _b = void 0; + classes.push((_b = /** @class */ (function () { + function A() { + this[_a] = "my property"; + } + return A; + }()), + _a = i, + _b)); +}; +for (var i = 0; i <= 10; ++i) { + _loop_1(i); +} +for (var _i = 0, classes_1 = classes; _i < classes_1.length; _i++) { + var clazz = classes_1[_i]; + console.log(Object.getOwnPropertyNames(new clazz())); +} diff --git a/tests/baselines/reference/computedPropertyNames52_ES5.symbols b/tests/baselines/reference/computedPropertyNames52_ES5.symbols new file mode 100644 index 0000000000000..ede524071ec31 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames52_ES5.symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES5.ts === +const classes = []; +>classes : Symbol(classes, Decl(computedPropertyNames52_ES5.ts, 0, 5)) + +for (let i = 0; i <= 10; ++i) { +>i : Symbol(i, Decl(computedPropertyNames52_ES5.ts, 1, 8)) +>i : Symbol(i, Decl(computedPropertyNames52_ES5.ts, 1, 8)) +>i : Symbol(i, Decl(computedPropertyNames52_ES5.ts, 1, 8)) + + classes.push( +>classes.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>classes : Symbol(classes, Decl(computedPropertyNames52_ES5.ts, 0, 5)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + class A { +>A : Symbol(A, Decl(computedPropertyNames52_ES5.ts, 2, 17)) + + [i] = "my property"; +>[i] : Symbol(A[i], Decl(computedPropertyNames52_ES5.ts, 3, 17)) +>i : Symbol(i, Decl(computedPropertyNames52_ES5.ts, 1, 8)) + } + ); +} +for (const clazz of classes) { +>clazz : Symbol(clazz, Decl(computedPropertyNames52_ES5.ts, 8, 10)) +>classes : Symbol(classes, Decl(computedPropertyNames52_ES5.ts, 0, 5)) + + console.log(Object.getOwnPropertyNames(new clazz())); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>Object.getOwnPropertyNames : Symbol(ObjectConstructor.getOwnPropertyNames, Decl(lib.es5.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>getOwnPropertyNames : Symbol(ObjectConstructor.getOwnPropertyNames, Decl(lib.es5.d.ts, --, --)) +>clazz : Symbol(clazz, Decl(computedPropertyNames52_ES5.ts, 8, 10)) +} diff --git a/tests/baselines/reference/computedPropertyNames52_ES5.types b/tests/baselines/reference/computedPropertyNames52_ES5.types new file mode 100644 index 0000000000000..c0aa1ece400fe --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames52_ES5.types @@ -0,0 +1,47 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES5.ts === +const classes = []; +>classes : any[] +>[] : undefined[] + +for (let i = 0; i <= 10; ++i) { +>i : number +>0 : 0 +>i <= 10 : boolean +>i : number +>10 : 10 +>++i : number +>i : number + + classes.push( +>classes.push( class A { [i] = "my property"; } ) : number +>classes.push : (...items: any[]) => number +>classes : any[] +>push : (...items: any[]) => number + + class A { +>class A { [i] = "my property"; } : typeof A +>A : typeof A + + [i] = "my property"; +>[i] : string +>i : number +>"my property" : "my property" + } + ); +} +for (const clazz of classes) { +>clazz : any +>classes : any[] + + console.log(Object.getOwnPropertyNames(new clazz())); +>console.log(Object.getOwnPropertyNames(new clazz())) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>Object.getOwnPropertyNames(new clazz()) : string[] +>Object.getOwnPropertyNames : (o: any) => string[] +>Object : ObjectConstructor +>getOwnPropertyNames : (o: any) => string[] +>new clazz() : any +>clazz : any +} diff --git a/tests/baselines/reference/computedPropertyNames52_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames52_ES6.errors.txt new file mode 100644 index 0000000000000..b48d170acda21 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames52_ES6.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES6.ts(5,13): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES6.ts (1 errors) ==== + const classes = []; + for (let i = 0; i <= 10; ++i) { + classes.push( + class A { + [i] = "my property"; + ~~~ +!!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type. + } + ); + } + for (const clazz of classes) { + console.log(Object.getOwnPropertyNames(new clazz())); + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames52_ES6.js b/tests/baselines/reference/computedPropertyNames52_ES6.js new file mode 100644 index 0000000000000..58a0d484486a8 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames52_ES6.js @@ -0,0 +1,28 @@ +//// [computedPropertyNames52_ES6.ts] +const classes = []; +for (let i = 0; i <= 10; ++i) { + classes.push( + class A { + [i] = "my property"; + } + ); +} +for (const clazz of classes) { + console.log(Object.getOwnPropertyNames(new clazz())); +} + +//// [computedPropertyNames52_ES6.js] +const classes = []; +for (let i = 0; i <= 10; ++i) { + let _a, _b; + classes.push((_b = class A { + constructor() { + this[_a] = "my property"; + } + }, + _a = i, + _b)); +} +for (const clazz of classes) { + console.log(Object.getOwnPropertyNames(new clazz())); +} diff --git a/tests/baselines/reference/computedPropertyNames52_ES6.symbols b/tests/baselines/reference/computedPropertyNames52_ES6.symbols new file mode 100644 index 0000000000000..a7b8f869ce078 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames52_ES6.symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES6.ts === +const classes = []; +>classes : Symbol(classes, Decl(computedPropertyNames52_ES6.ts, 0, 5)) + +for (let i = 0; i <= 10; ++i) { +>i : Symbol(i, Decl(computedPropertyNames52_ES6.ts, 1, 8)) +>i : Symbol(i, Decl(computedPropertyNames52_ES6.ts, 1, 8)) +>i : Symbol(i, Decl(computedPropertyNames52_ES6.ts, 1, 8)) + + classes.push( +>classes.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>classes : Symbol(classes, Decl(computedPropertyNames52_ES6.ts, 0, 5)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + class A { +>A : Symbol(A, Decl(computedPropertyNames52_ES6.ts, 2, 17)) + + [i] = "my property"; +>[i] : Symbol(A[i], Decl(computedPropertyNames52_ES6.ts, 3, 17)) +>i : Symbol(i, Decl(computedPropertyNames52_ES6.ts, 1, 8)) + } + ); +} +for (const clazz of classes) { +>clazz : Symbol(clazz, Decl(computedPropertyNames52_ES6.ts, 8, 10)) +>classes : Symbol(classes, Decl(computedPropertyNames52_ES6.ts, 0, 5)) + + console.log(Object.getOwnPropertyNames(new clazz())); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>Object.getOwnPropertyNames : Symbol(ObjectConstructor.getOwnPropertyNames, Decl(lib.es5.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>getOwnPropertyNames : Symbol(ObjectConstructor.getOwnPropertyNames, Decl(lib.es5.d.ts, --, --)) +>clazz : Symbol(clazz, Decl(computedPropertyNames52_ES6.ts, 8, 10)) +} diff --git a/tests/baselines/reference/computedPropertyNames52_ES6.types b/tests/baselines/reference/computedPropertyNames52_ES6.types new file mode 100644 index 0000000000000..cbbaa7e71d7e6 --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames52_ES6.types @@ -0,0 +1,47 @@ +=== tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES6.ts === +const classes = []; +>classes : any[] +>[] : undefined[] + +for (let i = 0; i <= 10; ++i) { +>i : number +>0 : 0 +>i <= 10 : boolean +>i : number +>10 : 10 +>++i : number +>i : number + + classes.push( +>classes.push( class A { [i] = "my property"; } ) : number +>classes.push : (...items: any[]) => number +>classes : any[] +>push : (...items: any[]) => number + + class A { +>class A { [i] = "my property"; } : typeof A +>A : typeof A + + [i] = "my property"; +>[i] : string +>i : number +>"my property" : "my property" + } + ); +} +for (const clazz of classes) { +>clazz : any +>classes : any[] + + console.log(Object.getOwnPropertyNames(new clazz())); +>console.log(Object.getOwnPropertyNames(new clazz())) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>Object.getOwnPropertyNames(new clazz()) : string[] +>Object.getOwnPropertyNames : (o: any) => string[] +>Object : ObjectConstructor +>getOwnPropertyNames : (o: any) => string[] +>new clazz() : any +>clazz : any +} diff --git a/tests/baselines/reference/emitter.forAwait.es2015.js b/tests/baselines/reference/emitter.forAwait.es2015.js index 6260870471b13..87c8036d65ece 100644 --- a/tests/baselines/reference/emitter.forAwait.es2015.js +++ b/tests/baselines/reference/emitter.forAwait.es2015.js @@ -59,7 +59,7 @@ var __asyncValues = (this && this.__asyncValues) || function (o) { }; function f1() { return __awaiter(this, void 0, void 0, function* () { - var e_1, _a; + let e_1, _a; let y; try { for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), !y_1_1.done;) { @@ -93,7 +93,7 @@ var __asyncValues = (this && this.__asyncValues) || function (o) { }; function f2() { return __awaiter(this, void 0, void 0, function* () { - var e_1, _a; + let e_1, _a; let x, y; try { for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), !y_1_1.done;) { @@ -204,7 +204,7 @@ var __asyncValues = (this && this.__asyncValues) || function (o) { // https://github.com/Microsoft/TypeScript/issues/21363 function f5() { return __awaiter(this, void 0, void 0, function* () { - var e_1, _a; + let e_1, _a; let y; try { outer: for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = yield y_1.next(), !y_1_1.done;) { diff --git a/tests/baselines/reference/emitter.forAwait.es2017.js b/tests/baselines/reference/emitter.forAwait.es2017.js index dd0e8aede2bb8..daf6e54526ddb 100644 --- a/tests/baselines/reference/emitter.forAwait.es2017.js +++ b/tests/baselines/reference/emitter.forAwait.es2017.js @@ -50,7 +50,7 @@ var __asyncValues = (this && this.__asyncValues) || function (o) { function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; async function f1() { - var e_1, _a; + let e_1, _a; let y; try { for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), !y_1_1.done;) { @@ -74,7 +74,7 @@ var __asyncValues = (this && this.__asyncValues) || function (o) { function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; async function f2() { - var e_1, _a; + let e_1, _a; let x, y; try { for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), !y_1_1.done;) { @@ -175,7 +175,7 @@ var __asyncValues = (this && this.__asyncValues) || function (o) { }; // https://github.com/Microsoft/TypeScript/issues/21363 async function f5() { - var e_1, _a; + let e_1, _a; let y; try { outer: for (var y_1 = __asyncValues(y), y_1_1; y_1_1 = await y_1.next(), !y_1_1.done;) { diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES5.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES5.ts new file mode 100644 index 0000000000000..297a0e826dfc2 --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES5.ts @@ -0,0 +1,12 @@ +//@target: es5 +const classes = []; +for (let i = 0; i <= 10; ++i) { + classes.push( + class A { + [i] = "my property"; + } + ); +} +for (const clazz of classes) { + console.log(Object.getOwnPropertyNames(new clazz())); +} \ No newline at end of file diff --git a/tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES6.ts b/tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES6.ts new file mode 100644 index 0000000000000..48ed1c391ce9b --- /dev/null +++ b/tests/cases/conformance/es6/computedProperties/computedPropertyNames52_ES6.ts @@ -0,0 +1,12 @@ +//@target: es6 +const classes = []; +for (let i = 0; i <= 10; ++i) { + classes.push( + class A { + [i] = "my property"; + } + ); +} +for (const clazz of classes) { + console.log(Object.getOwnPropertyNames(new clazz())); +} \ No newline at end of file From bdd5ad16f936ce184ed065b443333a0592afc6ef Mon Sep 17 00:00:00 2001 From: Max Heiber Date: Sat, 27 Oct 2018 15:42:39 -0400 Subject: [PATCH 3/4] Remove evaluation test for computed field emit I couldn't get the evaluator.evaluateTypeScript function to do codegen when there is a syntax error, even with the `noEmitOnError: false` compiler option. Signed-off-by: Max Heiber --- src/testRunner/tsconfig.json | 1 - .../unittests/evaluation/computedFieldLoop.ts | 30 ------------------- 2 files changed, 31 deletions(-) delete mode 100644 src/testRunner/unittests/evaluation/computedFieldLoop.ts diff --git a/src/testRunner/tsconfig.json b/src/testRunner/tsconfig.json index 2aab69438c6a3..42edf83996495 100644 --- a/src/testRunner/tsconfig.json +++ b/src/testRunner/tsconfig.json @@ -88,7 +88,6 @@ "unittests/versionCache.ts", "unittests/evaluation/asyncArrow.ts", "unittests/evaluation/asyncGenerator.ts", - "unittests/evaluation/computedFieldLoop.ts", "unittests/evaluation/forAwaitOf.ts", "unittests/services/colorization.ts", "unittests/services/documentRegistry.ts", diff --git a/src/testRunner/unittests/evaluation/computedFieldLoop.ts b/src/testRunner/unittests/evaluation/computedFieldLoop.ts deleted file mode 100644 index 3c63ed607b739..0000000000000 --- a/src/testRunner/unittests/evaluation/computedFieldLoop.ts +++ /dev/null @@ -1,30 +0,0 @@ -describe("computed scope is correct for a computed field defined in a loop", () => { - it("return (es5)", async () => { - const result = evaluator.evaluateTypeScript(` - const classes = []; - for (let i = 0; i <= 10; ++i) { - classes.push( - class A { - [i] = "my property"; - } - ); - } - export const output = classes.map(Object.keys) - `); - - result.main(); - assert.deepEqual(result.output, [ - ['1'], - ['2'], - ['3'], - ['4'], - ['5'], - ['6'], - ['7'], - ['8'], - ['9'], - ['10'], - ['bananananananan'] - ]); - }); -}); \ No newline at end of file From a58f29bc72e06c336a7b73aae8e994ab74ac38d1 Mon Sep 17 00:00:00 2001 From: Joseph Watts Date: Tue, 20 Nov 2018 20:34:38 -0500 Subject: [PATCH 4/4] Fix linter error Signed-off-by: Joseph Watts --- src/compiler/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d7dd0dabcce06..0f9e806bc7413 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5232,7 +5232,7 @@ namespace ts { export const enum LexicalEnvironmentScoping { Function, Block - }; + } export interface TransformationContext { /*@internal*/ getEmitResolver(): EmitResolver;