diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 46cab8f92f001..0879a3a9ee426 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1673,6 +1673,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge return false; } + function getClassExpressionInPropertyAccessInStaticPropertyDeclaration(node: Identifier) { + if (languageVersion >= ScriptTarget.ES6) { + let parent = node.parent; + if (parent.kind === SyntaxKind.PropertyAccessExpression && (parent).expression === node) { + parent = parent.parent; + while (parent && parent.kind !== SyntaxKind.PropertyDeclaration) { + parent = parent.parent; + } + return parent && parent.kind === SyntaxKind.PropertyDeclaration && (parent.flags & NodeFlags.Static) !== 0 && + parent.parent.kind === SyntaxKind.ClassExpression ? parent.parent : undefined; + } + } + return undefined; + } + function emitIdentifier(node: Identifier) { if (convertedLoopState) { if (node.text == "arguments" && resolver.isArgumentsLocalBinding(node)) { @@ -1687,6 +1702,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge write(node.text); } else if (isExpressionIdentifier(node)) { + const classExpression = getClassExpressionInPropertyAccessInStaticPropertyDeclaration(node); + if (classExpression) { + const declaration = resolver.getReferencedValueDeclaration(node); + if (declaration === classExpression) { + write(getGeneratedNameForNode(declaration.name)); + return; + } + } emitExpressionIdentifier(node); } else if (isNameOfNestedBlockScopedRedeclarationOrCapturedBinding(node)) { @@ -5086,13 +5109,13 @@ const _super = (function (geti, seti) { } } - function emitPropertyDeclaration(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver?: Identifier, isExpression?: boolean) { + function emitPropertyDeclaration(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver?: string, isExpression?: boolean) { writeLine(); emitLeadingComments(property); emitStart(property); emitStart(property.name); if (receiver) { - emit(receiver); + write(receiver); } else { if (property.flags & NodeFlags.Static) { @@ -5511,13 +5534,16 @@ const _super = (function (geti, seti) { // of it have been initialized by the time it is used. const staticProperties = getInitializedProperties(node, /*isStatic*/ true); const isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression; - let tempVariable: Identifier; + let generatedName: string; if (isClassExpressionWithStaticProperties) { - tempVariable = createAndRecordTempVariable(TempFlags.Auto); + generatedName = getGeneratedNameForNode(node.name); + const synthesizedNode = createSynthesizedNode(SyntaxKind.Identifier); + synthesizedNode.text = generatedName; + recordTempDeclaration(synthesizedNode); write("("); increaseIndent(); - emit(tempVariable); + emit(synthesizedNode); write(" = "); } @@ -5571,11 +5597,11 @@ const _super = (function (geti, seti) { for (const property of staticProperties) { write(","); writeLine(); - emitPropertyDeclaration(node, property, /*receiver*/ tempVariable, /*isExpression*/ true); + emitPropertyDeclaration(node, property, /*receiver*/ generatedName, /*isExpression*/ true); } write(","); writeLine(); - emit(tempVariable); + write(generatedName); decreaseIndent(); write(")"); } diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES61.js b/tests/baselines/reference/classExpressionWithStaticPropertiesES61.js index 43f5e7415c4da..7ddacb7040504 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES61.js +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES61.js @@ -1,10 +1,15 @@ //// [classExpressionWithStaticPropertiesES61.ts] -var v = class C { static a = 1; static b = 2 }; +var v = class C { + static a = 1; + static b = 2; + static c = C.a + 3; +}; //// [classExpressionWithStaticPropertiesES61.js] -var v = (_a = class C { +var v = (C_1 = class C { }, - _a.a = 1, - _a.b = 2, - _a); -var _a; + C_1.a = 1, + C_1.b = 2, + C_1.c = C_1.a + 3, + C_1); +var C_1; diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES61.symbols b/tests/baselines/reference/classExpressionWithStaticPropertiesES61.symbols index c5f53e19bffb1..1101c0bab2fc4 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES61.symbols +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES61.symbols @@ -1,7 +1,18 @@ === tests/cases/compiler/classExpressionWithStaticPropertiesES61.ts === -var v = class C { static a = 1; static b = 2 }; +var v = class C { >v : Symbol(v, Decl(classExpressionWithStaticPropertiesES61.ts, 0, 3)) +>C : Symbol(C, Decl(classExpressionWithStaticPropertiesES61.ts, 0, 7)) + + static a = 1; +>a : Symbol(C.a, Decl(classExpressionWithStaticPropertiesES61.ts, 0, 17)) + + static b = 2; +>b : Symbol(C.b, Decl(classExpressionWithStaticPropertiesES61.ts, 1, 17)) + + static c = C.a + 3; +>c : Symbol(C.c, Decl(classExpressionWithStaticPropertiesES61.ts, 2, 17)) +>C.a : Symbol(C.a, Decl(classExpressionWithStaticPropertiesES61.ts, 0, 17)) >C : Symbol(C, Decl(classExpressionWithStaticPropertiesES61.ts, 0, 7)) >a : Symbol(C.a, Decl(classExpressionWithStaticPropertiesES61.ts, 0, 17)) ->b : Symbol(C.b, Decl(classExpressionWithStaticPropertiesES61.ts, 0, 31)) +}; diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES61.types b/tests/baselines/reference/classExpressionWithStaticPropertiesES61.types index 02c385b7525df..0ba6ada4131f2 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES61.types +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES61.types @@ -1,10 +1,23 @@ === tests/cases/compiler/classExpressionWithStaticPropertiesES61.ts === -var v = class C { static a = 1; static b = 2 }; +var v = class C { >v : typeof C ->class C { static a = 1; static b = 2 } : typeof C +>class C { static a = 1; static b = 2; static c = C.a + 3;} : typeof C >C : typeof C + + static a = 1; >a : number >1 : number + + static b = 2; >b : number >2 : number + static c = C.a + 3; +>c : number +>C.a + 3 : number +>C.a : number +>C : typeof C +>a : number +>3 : number + +}; diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES62.js b/tests/baselines/reference/classExpressionWithStaticPropertiesES62.js index 1efa56ecaa23d..0a4b7645ecc29 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES62.js +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES62.js @@ -1,9 +1,20 @@ //// [classExpressionWithStaticPropertiesES62.ts] -var v = class C { static a = 1; static b }; +var v = class C { + static a = 1; + static b + static c = { + x: "hi" + } + static d = C.c.x + " world"; + }; //// [classExpressionWithStaticPropertiesES62.js] -var v = (_a = class C { +var v = (C_1 = class C { }, - _a.a = 1, - _a); -var _a; + C_1.a = 1, + C_1.c = { + x: "hi" + }, + C_1.d = C_1.c.x + " world", + C_1); +var C_1; diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES62.symbols b/tests/baselines/reference/classExpressionWithStaticPropertiesES62.symbols index be57a289f533b..697be499595c9 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES62.symbols +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES62.symbols @@ -1,7 +1,26 @@ === tests/cases/compiler/classExpressionWithStaticPropertiesES62.ts === -var v = class C { static a = 1; static b }; +var v = class C { >v : Symbol(v, Decl(classExpressionWithStaticPropertiesES62.ts, 0, 3)) >C : Symbol(C, Decl(classExpressionWithStaticPropertiesES62.ts, 0, 7)) + + static a = 1; >a : Symbol(C.a, Decl(classExpressionWithStaticPropertiesES62.ts, 0, 17)) ->b : Symbol(C.b, Decl(classExpressionWithStaticPropertiesES62.ts, 0, 31)) + static b +>b : Symbol(C.b, Decl(classExpressionWithStaticPropertiesES62.ts, 1, 17)) + + static c = { +>c : Symbol(C.c, Decl(classExpressionWithStaticPropertiesES62.ts, 2, 12)) + + x: "hi" +>x : Symbol(x, Decl(classExpressionWithStaticPropertiesES62.ts, 3, 16)) + } + static d = C.c.x + " world"; +>d : Symbol(C.d, Decl(classExpressionWithStaticPropertiesES62.ts, 5, 5)) +>C.c.x : Symbol(x, Decl(classExpressionWithStaticPropertiesES62.ts, 3, 16)) +>C.c : Symbol(C.c, Decl(classExpressionWithStaticPropertiesES62.ts, 2, 12)) +>C : Symbol(C, Decl(classExpressionWithStaticPropertiesES62.ts, 0, 7)) +>c : Symbol(C.c, Decl(classExpressionWithStaticPropertiesES62.ts, 2, 12)) +>x : Symbol(x, Decl(classExpressionWithStaticPropertiesES62.ts, 3, 16)) + + }; diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES62.types b/tests/baselines/reference/classExpressionWithStaticPropertiesES62.types index e8ded1422f1e4..97d6940a3fc61 100644 --- a/tests/baselines/reference/classExpressionWithStaticPropertiesES62.types +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES62.types @@ -1,9 +1,32 @@ === tests/cases/compiler/classExpressionWithStaticPropertiesES62.ts === -var v = class C { static a = 1; static b }; +var v = class C { >v : typeof C ->class C { static a = 1; static b } : typeof C +>class C { static a = 1; static b static c = { x: "hi" } static d = C.c.x + " world"; } : typeof C >C : typeof C + + static a = 1; >a : number >1 : number + + static b >b : any + static c = { +>c : { x: string; } +>{ x: "hi" } : { x: string; } + + x: "hi" +>x : string +>"hi" : string + } + static d = C.c.x + " world"; +>d : string +>C.c.x + " world" : string +>C.c.x : string +>C.c : { x: string; } +>C : typeof C +>c : { x: string; } +>x : string +>" world" : string + + }; diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES63.js b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.js new file mode 100644 index 0000000000000..539557357624c --- /dev/null +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.js @@ -0,0 +1,23 @@ +//// [classExpressionWithStaticPropertiesES63.ts] + +declare var console: any; +const arr: {y(): number}[] = []; +for (let i = 0; i < 3; i++) { + arr.push(class C { + static x = i; + static y = () => C.x * 2; + }); +} +arr.forEach(C => console.log(C.y())); + +//// [classExpressionWithStaticPropertiesES63.js] +const arr = []; +for (let i = 0; i < 3; i++) { + arr.push((C_1 = class C { + }, + C_1.x = i, + C_1.y = () => C_1.x * 2, + C_1)); +} +arr.forEach(C => console.log(C.y())); +var C_1; diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES63.symbols b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.symbols new file mode 100644 index 0000000000000..f1a7fa807f56b --- /dev/null +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.symbols @@ -0,0 +1,42 @@ +=== tests/cases/compiler/classExpressionWithStaticPropertiesES63.ts === + +declare var console: any; +>console : Symbol(console, Decl(classExpressionWithStaticPropertiesES63.ts, 1, 11)) + +const arr: {y(): number}[] = []; +>arr : Symbol(arr, Decl(classExpressionWithStaticPropertiesES63.ts, 2, 5)) +>y : Symbol(y, Decl(classExpressionWithStaticPropertiesES63.ts, 2, 12)) + +for (let i = 0; i < 3; i++) { +>i : Symbol(i, Decl(classExpressionWithStaticPropertiesES63.ts, 3, 8)) +>i : Symbol(i, Decl(classExpressionWithStaticPropertiesES63.ts, 3, 8)) +>i : Symbol(i, Decl(classExpressionWithStaticPropertiesES63.ts, 3, 8)) + + arr.push(class C { +>arr.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(classExpressionWithStaticPropertiesES63.ts, 2, 5)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>C : Symbol(C, Decl(classExpressionWithStaticPropertiesES63.ts, 4, 13)) + + static x = i; +>x : Symbol(C.x, Decl(classExpressionWithStaticPropertiesES63.ts, 4, 22)) +>i : Symbol(i, Decl(classExpressionWithStaticPropertiesES63.ts, 3, 8)) + + static y = () => C.x * 2; +>y : Symbol(C.y, Decl(classExpressionWithStaticPropertiesES63.ts, 5, 21)) +>C.x : Symbol(C.x, Decl(classExpressionWithStaticPropertiesES63.ts, 4, 22)) +>C : Symbol(C, Decl(classExpressionWithStaticPropertiesES63.ts, 4, 13)) +>x : Symbol(C.x, Decl(classExpressionWithStaticPropertiesES63.ts, 4, 22)) + + }); +} +arr.forEach(C => console.log(C.y())); +>arr.forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(classExpressionWithStaticPropertiesES63.ts, 2, 5)) +>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) +>C : Symbol(C, Decl(classExpressionWithStaticPropertiesES63.ts, 9, 12)) +>console : Symbol(console, Decl(classExpressionWithStaticPropertiesES63.ts, 1, 11)) +>C.y : Symbol(y, Decl(classExpressionWithStaticPropertiesES63.ts, 2, 12)) +>C : Symbol(C, Decl(classExpressionWithStaticPropertiesES63.ts, 9, 12)) +>y : Symbol(y, Decl(classExpressionWithStaticPropertiesES63.ts, 2, 12)) + diff --git a/tests/baselines/reference/classExpressionWithStaticPropertiesES63.types b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.types new file mode 100644 index 0000000000000..92f14f3f65f50 --- /dev/null +++ b/tests/baselines/reference/classExpressionWithStaticPropertiesES63.types @@ -0,0 +1,58 @@ +=== tests/cases/compiler/classExpressionWithStaticPropertiesES63.ts === + +declare var console: any; +>console : any + +const arr: {y(): number}[] = []; +>arr : { y(): number; }[] +>y : () => number +>[] : undefined[] + +for (let i = 0; i < 3; i++) { +>i : number +>0 : number +>i < 3 : boolean +>i : number +>3 : number +>i++ : number +>i : number + + arr.push(class C { +>arr.push(class C { static x = i; static y = () => C.x * 2; }) : number +>arr.push : (...items: { y(): number; }[]) => number +>arr : { y(): number; }[] +>push : (...items: { y(): number; }[]) => number +>class C { static x = i; static y = () => C.x * 2; } : typeof C +>C : typeof C + + static x = i; +>x : number +>i : number + + static y = () => C.x * 2; +>y : () => number +>() => C.x * 2 : () => number +>C.x * 2 : number +>C.x : number +>C : typeof C +>x : number +>2 : number + + }); +} +arr.forEach(C => console.log(C.y())); +>arr.forEach(C => console.log(C.y())) : void +>arr.forEach : (callbackfn: (value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg?: any) => void +>arr : { y(): number; }[] +>forEach : (callbackfn: (value: { y(): number; }, index: number, array: { y(): number; }[]) => void, thisArg?: any) => void +>C => console.log(C.y()) : (C: { y(): number; }) => any +>C : { y(): number; } +>console.log(C.y()) : any +>console.log : any +>console : any +>log : any +>C.y() : number +>C.y : () => number +>C : { y(): number; } +>y : () => number + diff --git a/tests/cases/compiler/classExpressionWithStaticPropertiesES61.ts b/tests/cases/compiler/classExpressionWithStaticPropertiesES61.ts index 8df07b9569a03..3f9fc43835e1e 100644 --- a/tests/cases/compiler/classExpressionWithStaticPropertiesES61.ts +++ b/tests/cases/compiler/classExpressionWithStaticPropertiesES61.ts @@ -1,2 +1,6 @@ //@target: es6 -var v = class C { static a = 1; static b = 2 }; \ No newline at end of file +var v = class C { + static a = 1; + static b = 2; + static c = C.a + 3; +}; \ No newline at end of file diff --git a/tests/cases/compiler/classExpressionWithStaticPropertiesES62.ts b/tests/cases/compiler/classExpressionWithStaticPropertiesES62.ts index ee0430eb793ab..afb87b10de96a 100644 --- a/tests/cases/compiler/classExpressionWithStaticPropertiesES62.ts +++ b/tests/cases/compiler/classExpressionWithStaticPropertiesES62.ts @@ -1,2 +1,9 @@ //@target: es6 -var v = class C { static a = 1; static b }; \ No newline at end of file +var v = class C { + static a = 1; + static b + static c = { + x: "hi" + } + static d = C.c.x + " world"; + }; \ No newline at end of file diff --git a/tests/cases/compiler/classExpressionWithStaticPropertiesES63.ts b/tests/cases/compiler/classExpressionWithStaticPropertiesES63.ts new file mode 100644 index 0000000000000..939a344f9bb05 --- /dev/null +++ b/tests/cases/compiler/classExpressionWithStaticPropertiesES63.ts @@ -0,0 +1,11 @@ +//@target: es6 + +declare var console: any; +const arr: {y(): number}[] = []; +for (let i = 0; i < 3; i++) { + arr.push(class C { + static x = i; + static y = () => C.x * 2; + }); +} +arr.forEach(C => console.log(C.y())); \ No newline at end of file