Bloomberg computed property name fix (#43197)

* Fix property name bindings for class expr in loops

* Fix block-scope capturing with prop initializers

Co-authored-by: Joey Watts <joey.watts.96@gmail.com>
This commit is contained in:
Nathan Shively-Sanders
2021-03-11 10:32:42 -08:00
committed by GitHub
co-authored by Joey Watts
parent 998ecd9c06
commit b2d1f537f1
31 changed files with 587 additions and 41 deletions
+38 -17
View File
@@ -23775,14 +23775,20 @@ namespace ts {
return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType;
}
function isInsideFunction(node: Node, threshold: Node): boolean {
return !!findAncestor(node, n => n === threshold ? "quit" : isFunctionLike(n));
function isInsideFunctionOrInstancePropertyInitializer(node: Node, threshold: Node): boolean {
return !!findAncestor(node, n => n === threshold ? "quit" : isFunctionLike(n) || (
n.parent && isPropertyDeclaration(n.parent) && !hasStaticModifier(n.parent) && n.parent.initializer === n
));
}
function getPartOfForStatementContainingNode(node: Node, container: ForStatement) {
return findAncestor(node, n => n === container ? "quit" : n === container.initializer || n === container.condition || n === container.incrementor || n === container.statement);
}
function getEnclosingIterationStatement(node: Node): Node | undefined {
return findAncestor(node, n => (!n || nodeStartsNewLexicalEnvironment(n)) ? "quit" : isIterationStatement(n, /*lookInLabeledStatements*/ false));
}
function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void {
if (languageVersion >= ScriptTarget.ES2015 ||
(symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 ||
@@ -23798,20 +23804,11 @@ namespace ts {
// if there is an iteration statement in between declaration and boundary (is binding/class declared inside iteration statement)
const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
const usedInFunction = isInsideFunction(node.parent, container);
let current = container;
const isCaptured = isInsideFunctionOrInstancePropertyInitializer(node, container);
let containedInIterationStatement = false;
while (current && !nodeStartsNewLexicalEnvironment(current)) {
if (isIterationStatement(current, /*lookInLabeledStatements*/ false)) {
containedInIterationStatement = true;
break;
}
current = current.parent;
}
if (containedInIterationStatement) {
if (usedInFunction) {
const enclosingIterationStatement = getEnclosingIterationStatement(container);
if (enclosingIterationStatement) {
if (isCaptured) {
// mark iteration statement as containing block-scoped binding captured in some function
let capturesBlockScopeBindingInLoopBody = true;
if (isForStatement(container)) {
@@ -23832,7 +23829,7 @@ namespace ts {
}
}
if (capturesBlockScopeBindingInLoopBody) {
getNodeLinks(current).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
}
}
@@ -23849,7 +23846,7 @@ namespace ts {
getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
}
if (usedInFunction) {
if (isCaptured) {
getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.CapturedBlockScopedBinding;
}
}
@@ -25529,6 +25526,20 @@ namespace ts {
const links = getNodeLinks(node.expression);
if (!links.resolvedType) {
links.resolvedType = checkExpression(node.expression);
// The computed property name of a non-static class field within a loop must be stored in a block-scoped binding.
// (It needs to be bound at class evaluation time.)
if (isPropertyDeclaration(node.parent) && !hasStaticModifier(node.parent) && isClassExpression(node.parent.parent)) {
const container = getEnclosingBlockScopeContainer(node.parent.parent);
const enclosingIterationStatement = getEnclosingIterationStatement(container);
if (enclosingIterationStatement) {
// The computed field name will use a block scoped binding which can be unique for each iteration of the loop.
getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
// The generated variable which stores the computed field name must be block-scoped.
getNodeLinks(node).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
// The generated variable which stores the class must be block-scoped.
getNodeLinks(node.parent.parent).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 ||
@@ -32617,6 +32628,16 @@ namespace ts {
for (let lexicalScope = getEnclosingBlockScopeContainer(node); !!lexicalScope; lexicalScope = getEnclosingBlockScopeContainer(lexicalScope)) {
getNodeLinks(lexicalScope).flags |= NodeCheckFlags.ContainsClassWithPrivateIdentifiers;
}
// If this is a private field in a class expression inside the body of a loop,
// then we must use a block-scoped binding to store the WeakMap.
if (isClassExpression(node.parent)) {
const enclosingIterationStatement = getEnclosingIterationStatement(node.parent);
if (enclosingIterationStatement) {
getNodeLinks(node.name).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
}
}
}
}
+49
View File
@@ -159,6 +159,9 @@ namespace ts {
let lexicalEnvironmentFlagsStack: LexicalEnvironmentFlags[] = [];
let lexicalEnvironmentStackOffset = 0;
let lexicalEnvironmentSuspended = false;
let blockScopedVariableDeclarationsStack: Identifier[][] = [];
let blockScopeStackOffset = 0;
let blockScopedVariableDeclarations: Identifier[];
let emitHelpers: EmitHelper[] | undefined;
let onSubstituteNode: TransformationContext["onSubstituteNode"] = noEmitSubstitution;
let onEmitNode: TransformationContext["onEmitNode"] = noEmitNotification;
@@ -182,6 +185,9 @@ namespace ts {
hoistVariableDeclaration,
hoistFunctionDeclaration,
addInitializationStatement,
startBlockScope,
endBlockScope,
addBlockScopedVariable,
requestEmitHelper,
readEmitHelpers,
enableSubstitution,
@@ -473,6 +479,46 @@ namespace ts {
return lexicalEnvironmentFlags;
}
/**
* Starts a block scope. Any existing block hoisted variables are pushed onto the stack and the related storage variables are reset.
*/
function startBlockScope() {
Debug.assert(state > TransformationState.Uninitialized, "Cannot start a block scope during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot start a block scope after transformation has completed.");
blockScopedVariableDeclarationsStack[blockScopeStackOffset] = blockScopedVariableDeclarations;
blockScopeStackOffset++;
blockScopedVariableDeclarations = undefined!;
}
/**
* Ends a block scope. The previous set of block hoisted variables are restored. Any hoisted declarations are returned.
*/
function endBlockScope() {
Debug.assert(state > TransformationState.Uninitialized, "Cannot end a block scope during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot end a block scope after transformation has completed.");
const statements: Statement[] | undefined = some(blockScopedVariableDeclarations) ?
[
factory.createVariableStatement(
/*modifiers*/ undefined,
factory.createVariableDeclarationList(
blockScopedVariableDeclarations.map(identifier => factory.createVariableDeclaration(identifier)),
NodeFlags.Let
)
)
] : undefined;
blockScopeStackOffset--;
blockScopedVariableDeclarations = blockScopedVariableDeclarationsStack[blockScopeStackOffset];
if (blockScopeStackOffset === 0) {
blockScopedVariableDeclarationsStack = [];
}
return statements;
}
function addBlockScopedVariable(name: Identifier): void {
Debug.assert(blockScopeStackOffset > 0, "Cannot add a block scoped variable outside of an iteration body.");
(blockScopedVariableDeclarations || (blockScopedVariableDeclarations = [])).push(name);
}
function requestEmitHelper(helper: EmitHelper): void {
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed.");
@@ -539,5 +585,8 @@ namespace ts {
startLexicalEnvironment: noop,
suspendLexicalEnvironment: noop,
addDiagnostic: noop,
startBlockScope: noop,
endBlockScope: returnUndefined,
addBlockScopedVariable: noop
};
}
+19 -7
View File
@@ -36,7 +36,8 @@ namespace ts {
factory,
hoistVariableDeclaration,
endLexicalEnvironment,
resumeLexicalEnvironment
resumeLexicalEnvironment,
addBlockScopedVariable
} = context;
const resolver = context.getEmitResolver();
const compilerOptions = context.getCompilerOptions();
@@ -310,7 +311,7 @@ namespace ts {
visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.condition, visitor, isExpression),
visitPostfixUnaryExpression(node.incrementor, /*valueIsDiscarded*/ true),
visitNode(node.statement, visitor, isStatement)
visitIterationBody(node.statement, visitor, context)
);
}
return visitEachChild(node, visitor, context);
@@ -540,8 +541,10 @@ namespace ts {
}
else {
const expressions: Expression[] = [];
const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference;
const temp = factory.createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference);
const classCheckFlags = resolver.getNodeCheckFlags(node);
const isClassWithConstructorReference = classCheckFlags & NodeCheckFlags.ClassWithConstructorReference;
const requiresBlockScopedVar = classCheckFlags & NodeCheckFlags.BlockScopedBindingInLoop;
const temp = factory.createTempVariable(requiresBlockScopedVar ? addBlockScopedVariable : hoistVariableDeclaration, !!isClassWithConstructorReference);
if (isClassWithConstructorReference) {
// record an alias as the class name is not in scope for statics.
enableSubstitutionForClassAliases();
@@ -869,7 +872,6 @@ namespace ts {
return undefined;
}
/**
* If the name is a computed property, this function transforms it, then either returns an expression which caches the
* value of the result or the expression itself if the value is either unused or safe to inline into multiple locations
@@ -883,7 +885,12 @@ namespace ts {
const alreadyTransformed = isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left);
if (!alreadyTransformed && !inlinable && shouldHoist) {
const generatedName = factory.getGeneratedNameForNode(name);
hoistVariableDeclaration(generatedName);
if (resolver.getNodeCheckFlags(name) & NodeCheckFlags.BlockScopedBindingInLoop) {
addBlockScopedVariable(generatedName);
}
else {
hoistVariableDeclaration(generatedName);
}
return factory.createAssignment(generatedName, expression);
}
return (inlinable || isIdentifier(innerExpression)) ? undefined : expression;
@@ -910,7 +917,12 @@ namespace ts {
function addPrivateIdentifierToEnvironment(name: PrivateIdentifier) {
const text = getTextOfPropertyName(name) as string;
const weakMapName = factory.createUniqueName("_" + text.substring(1), GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes);
hoistVariableDeclaration(weakMapName);
if (resolver.getNodeCheckFlags(name) & NodeCheckFlags.BlockScopedBindingInLoop) {
addBlockScopedVariable(weakMapName);
}
else {
hoistVariableDeclaration(weakMapName);
}
getPrivateIdentifierEnvironment().set(name.escapedText, { placement: PrivateIdentifierPlacement.InstanceField, weakMapName });
getPendingExpressions().push(
factory.createAssignment(
+3 -3
View File
@@ -225,7 +225,7 @@ namespace ts {
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)!
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, factory.liftToBlock)
visitIterationBody(node.statement, asyncBodyVisitor, context)
);
}
@@ -237,7 +237,7 @@ namespace ts {
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)!
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, factory.liftToBlock)
visitIterationBody(node.statement, asyncBodyVisitor, context)
);
}
@@ -250,7 +250,7 @@ namespace ts {
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, factory.liftToBlock)
visitIterationBody(node.statement, asyncBodyVisitor, context)
);
}
+2 -2
View File
@@ -575,7 +575,7 @@ namespace ts {
visitNode(node.initializer, visitorWithUnusedExpressionResult, isForInitializer),
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitorWithUnusedExpressionResult, isExpression),
visitNode(node.statement, visitor, isStatement)
visitIterationBody(node.statement, visitor, context)
);
}
@@ -648,7 +648,7 @@ namespace ts {
let bodyLocation: TextRange | undefined;
let statementsLocation: TextRange | undefined;
const statements: Statement[] = [visitNode(binding, visitor, isStatement)];
const statement = visitNode(node.statement, visitor, isStatement);
const statement = visitIterationBody(node.statement, visitor, context);
if (isBlock(statement)) {
addRange(statements, statement.statements);
bodyLocation = statement;
+1 -1
View File
@@ -1502,7 +1502,7 @@ namespace ts {
: undefined,
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitor, isExpression),
visitNode(node.statement, visitor, isStatement, factory.liftToBlock)
visitIterationBody(node.statement, visitor, context)
);
}
else {
+5 -5
View File
@@ -1231,7 +1231,7 @@ namespace ts {
node.initializer && visitForInitializer(node.initializer),
visitNode(node.condition, destructuringAndImportCallVisitor, isExpression),
visitNode(node.incrementor, destructuringAndImportCallVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement)
visitIterationBody(node.statement, nestedElementVisitor, context)
);
enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer;
@@ -1251,7 +1251,7 @@ namespace ts {
node,
visitForInitializer(node.initializer),
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock)
visitIterationBody(node.statement, nestedElementVisitor, context)
);
enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer;
@@ -1272,7 +1272,7 @@ namespace ts {
node.awaitModifier,
visitForInitializer(node.initializer),
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock)
visitIterationBody(node.statement, nestedElementVisitor, context)
);
enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer;
@@ -1320,7 +1320,7 @@ namespace ts {
function visitDoStatement(node: DoStatement): VisitResult<Statement> {
return factory.updateDoStatement(
node,
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock),
visitIterationBody(node.statement, nestedElementVisitor, context),
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression)
);
}
@@ -1334,7 +1334,7 @@ namespace ts {
return factory.updateWhileStatement(
node,
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock)
visitIterationBody(node.statement, nestedElementVisitor, context)
);
}
+6
View File
@@ -7520,6 +7520,12 @@ namespace ts {
/** Hoists a variable declaration to the containing scope. */
hoistVariableDeclaration(node: Identifier): void;
/*@internal*/ startBlockScope(): void;
/*@internal*/ endBlockScope(): Statement[] | undefined;
/*@internal*/ addBlockScopedVariable(node: Identifier): void;
/** Adds an initialization statement to the top of the lexical environment. */
/* @internal */
addInitializationStatement(node: Statement): void;
+23 -5
View File
@@ -311,6 +311,24 @@ namespace ts {
return updated;
}
/**
* Visits an iteration body, adding any block-scoped variables required by the transformation.
*/
export function visitIterationBody(body: Statement, visitor: Visitor, context: TransformationContext): Statement {
context.startBlockScope();
const updated = visitNode(body, visitor, isStatement, context.factory.liftToBlock);
const declarations = context.endBlockScope();
if (some(declarations)) {
if (isBlock(updated)) {
declarations.push(...updated.statements);
return context.factory.updateBlock(updated, declarations);
}
declarations.push(updated);
return context.factory.createBlock(declarations);
}
return updated;
}
/**
* Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
*
@@ -872,14 +890,14 @@ namespace ts {
case SyntaxKind.DoStatement:
Debug.type<DoStatement>(node);
return factory.updateDoStatement(node,
nodeVisitor(node.statement, visitor, isStatement, factory.liftToBlock),
visitIterationBody(node.statement, visitor, context),
nodeVisitor(node.expression, visitor, isExpression));
case SyntaxKind.WhileStatement:
Debug.type<WhileStatement>(node);
return factory.updateWhileStatement(node,
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.statement, visitor, isStatement, factory.liftToBlock));
visitIterationBody(node.statement, visitor, context));
case SyntaxKind.ForStatement:
Debug.type<ForStatement>(node);
@@ -887,14 +905,14 @@ namespace ts {
nodeVisitor(node.initializer, visitor, isForInitializer),
nodeVisitor(node.condition, visitor, isExpression),
nodeVisitor(node.incrementor, visitor, isExpression),
nodeVisitor(node.statement, visitor, isStatement, factory.liftToBlock));
visitIterationBody(node.statement, visitor, context));
case SyntaxKind.ForInStatement:
Debug.type<ForInStatement>(node);
return factory.updateForInStatement(node,
nodeVisitor(node.initializer, visitor, isForInitializer),
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.statement, visitor, isStatement, factory.liftToBlock));
visitIterationBody(node.statement, visitor, context));
case SyntaxKind.ForOfStatement:
Debug.type<ForOfStatement>(node);
@@ -902,7 +920,7 @@ namespace ts {
nodeVisitor(node.awaitModifier, tokenVisitor, isAwaitKeyword),
nodeVisitor(node.initializer, visitor, isForInitializer),
nodeVisitor(node.expression, visitor, isExpression),
nodeVisitor(node.statement, visitor, isStatement, factory.liftToBlock));
visitIterationBody(node.statement, visitor, context));
case SyntaxKind.ContinueStatement:
Debug.type<ContinueStatement>(node);
+4
View File
@@ -4782,6 +4782,10 @@ declare namespace ts {
* environment and merging hoisted declarations upon completion.
*/
function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody;
/**
* Visits an iteration body, adding any block-scoped variables required by the transformation.
*/
function visitIterationBody(body: Statement, visitor: Visitor, context: TransformationContext): Statement;
/**
* Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
*
+4
View File
@@ -4782,6 +4782,10 @@ declare namespace ts {
* environment and merging hoisted declarations upon completion.
*/
function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody;
/**
* Visits an iteration body, adding any block-scoped variables required by the transformation.
*/
function visitIterationBody(body: Statement, visitor: Visitor, context: TransformationContext): Statement;
/**
* Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
*
@@ -0,0 +1,24 @@
//// [classDeclarationLoop.ts]
const arr = [];
for (let i = 0; i < 10; ++i) {
class C {
prop = i;
}
arr.push(C);
}
//// [classDeclarationLoop.js]
var arr = [];
var _loop_1 = function (i) {
var C = /** @class */ (function () {
function C() {
this.prop = i;
}
return C;
}());
arr.push(C);
};
for (var i = 0; i < 10; ++i) {
_loop_1(i);
}
@@ -0,0 +1,23 @@
=== tests/cases/conformance/classes/classDeclarations/classDeclarationLoop.ts ===
const arr = [];
>arr : Symbol(arr, Decl(classDeclarationLoop.ts, 0, 5))
for (let i = 0; i < 10; ++i) {
>i : Symbol(i, Decl(classDeclarationLoop.ts, 1, 8))
>i : Symbol(i, Decl(classDeclarationLoop.ts, 1, 8))
>i : Symbol(i, Decl(classDeclarationLoop.ts, 1, 8))
class C {
>C : Symbol(C, Decl(classDeclarationLoop.ts, 1, 30))
prop = i;
>prop : Symbol(C.prop, Decl(classDeclarationLoop.ts, 2, 13))
>i : Symbol(i, Decl(classDeclarationLoop.ts, 1, 8))
}
arr.push(C);
>arr.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(classDeclarationLoop.ts, 0, 5))
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>C : Symbol(C, Decl(classDeclarationLoop.ts, 1, 30))
}
@@ -0,0 +1,29 @@
=== tests/cases/conformance/classes/classDeclarations/classDeclarationLoop.ts ===
const arr = [];
>arr : any[]
>[] : undefined[]
for (let i = 0; i < 10; ++i) {
>i : number
>0 : 0
>i < 10 : boolean
>i : number
>10 : 10
>++i : number
>i : number
class C {
>C : C
prop = i;
>prop : number
>i : number
}
arr.push(C);
>arr.push(C) : number
>arr.push : (...items: any[]) => number
>arr : any[]
>push : (...items: any[]) => number
>C : typeof C
}
@@ -0,0 +1,22 @@
//// [classExpressionLoop.ts]
let arr = [];
for (let i = 0; i < 10; ++i) {
arr.push(class C {
prop = i;
});
}
//// [classExpressionLoop.js]
var arr = [];
var _loop_1 = function (i) {
arr.push(/** @class */ (function () {
function C() {
this.prop = i;
}
return C;
}()));
};
for (var i = 0; i < 10; ++i) {
_loop_1(i);
}
@@ -0,0 +1,22 @@
=== tests/cases/conformance/classes/classExpressions/classExpressionLoop.ts ===
let arr = [];
>arr : Symbol(arr, Decl(classExpressionLoop.ts, 0, 3))
for (let i = 0; i < 10; ++i) {
>i : Symbol(i, Decl(classExpressionLoop.ts, 1, 8))
>i : Symbol(i, Decl(classExpressionLoop.ts, 1, 8))
>i : Symbol(i, Decl(classExpressionLoop.ts, 1, 8))
arr.push(class C {
>arr.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(classExpressionLoop.ts, 0, 3))
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>C : Symbol(C, Decl(classExpressionLoop.ts, 2, 13))
prop = i;
>prop : Symbol(C.prop, Decl(classExpressionLoop.ts, 2, 22))
>i : Symbol(i, Decl(classExpressionLoop.ts, 1, 8))
});
}
@@ -0,0 +1,29 @@
=== tests/cases/conformance/classes/classExpressions/classExpressionLoop.ts ===
let arr = [];
>arr : any[]
>[] : undefined[]
for (let i = 0; i < 10; ++i) {
>i : number
>0 : 0
>i < 10 : boolean
>i : number
>10 : 10
>++i : number
>i : number
arr.push(class C {
>arr.push(class C { prop = i; }) : number
>arr.push : (...items: any[]) => number
>arr : any[]
>push : (...items: any[]) => number
>class C { prop = i; } : typeof C
>C : typeof C
prop = i;
>prop : number
>i : number
});
}
@@ -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() {
}
@@ -0,0 +1,25 @@
//// [computedPropertyNames52.js]
const array = [];
for (let i = 0; i < 10; ++i) {
array.push(class C {
[i] = () => C;
static [i] = 100;
})
}
//// [computedPropertyNames52-emit.js]
var _a;
const array = [];
for (let i = 0; i < 10; ++i) {
let _b, _c;
array.push((_c = class C {
constructor() {
this[_b] = () => C;
}
},
_b = i,
_a = i,
_c[_a] = 100,
_c));
}
@@ -0,0 +1,27 @@
=== tests/cases/conformance/es6/computedProperties/computedPropertyNames52.js ===
const array = [];
>array : Symbol(array, Decl(computedPropertyNames52.js, 0, 5))
for (let i = 0; i < 10; ++i) {
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
array.push(class C {
>array.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>array : Symbol(array, Decl(computedPropertyNames52.js, 0, 5))
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>C : Symbol(C, Decl(computedPropertyNames52.js, 2, 15))
[i] = () => C;
>[i] : Symbol(C[i], Decl(computedPropertyNames52.js, 2, 24))
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
>C : Symbol(C, Decl(computedPropertyNames52.js, 2, 15))
static [i] = 100;
>[i] : Symbol(C[i], Decl(computedPropertyNames52.js, 3, 22))
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
})
}
@@ -0,0 +1,36 @@
=== tests/cases/conformance/es6/computedProperties/computedPropertyNames52.js ===
const array = [];
>array : any[]
>[] : undefined[]
for (let i = 0; i < 10; ++i) {
>i : number
>0 : 0
>i < 10 : boolean
>i : number
>10 : 10
>++i : number
>i : number
array.push(class C {
>array.push(class C { [i] = () => C; static [i] = 100; }) : number
>array.push : (...items: any[]) => number
>array : any[]
>push : (...items: any[]) => number
>class C { [i] = () => C; static [i] = 100; } : typeof C
>C : typeof C
[i] = () => C;
>[i] : () => typeof C
>i : number
>() => C : () => typeof C
>C : typeof C
static [i] = 100;
>[i] : number
>i : number
>100 : 100
})
}
@@ -0,0 +1,29 @@
//// [computedPropertyNames52.js]
const array = [];
for (let i = 0; i < 10; ++i) {
array.push(class C {
[i] = () => C;
static [i] = 100;
})
}
//// [computedPropertyNames52-emit.js]
var _a;
var array = [];
var _loop_1 = function (i) {
var _b = void 0, _c = void 0;
array.push((_c = /** @class */ (function () {
function C() {
this[_b] = function () { return C; };
}
return C;
}()),
_b = i,
_a = i,
_c[_a] = 100,
_c));
};
for (var i = 0; i < 10; ++i) {
_loop_1(i);
}
@@ -0,0 +1,27 @@
=== tests/cases/conformance/es6/computedProperties/computedPropertyNames52.js ===
const array = [];
>array : Symbol(array, Decl(computedPropertyNames52.js, 0, 5))
for (let i = 0; i < 10; ++i) {
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
array.push(class C {
>array.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>array : Symbol(array, Decl(computedPropertyNames52.js, 0, 5))
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>C : Symbol(C, Decl(computedPropertyNames52.js, 2, 15))
[i] = () => C;
>[i] : Symbol(C[i], Decl(computedPropertyNames52.js, 2, 24))
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
>C : Symbol(C, Decl(computedPropertyNames52.js, 2, 15))
static [i] = 100;
>[i] : Symbol(C[i], Decl(computedPropertyNames52.js, 3, 22))
>i : Symbol(i, Decl(computedPropertyNames52.js, 1, 8))
})
}
@@ -0,0 +1,36 @@
=== tests/cases/conformance/es6/computedProperties/computedPropertyNames52.js ===
const array = [];
>array : any[]
>[] : undefined[]
for (let i = 0; i < 10; ++i) {
>i : number
>0 : 0
>i < 10 : boolean
>i : number
>10 : 10
>++i : number
>i : number
array.push(class C {
>array.push(class C { [i] = () => C; static [i] = 100; }) : number
>array.push : (...items: any[]) => number
>array : any[]
>push : (...items: any[]) => number
>class C { [i] = () => C; static [i] = 100; } : typeof C
>C : typeof C
[i] = () => C;
>[i] : () => typeof C
>i : number
>() => C : () => typeof C
>C : typeof C
static [i] = 100;
>[i] : number
>i : number
>100 : 100
})
}
@@ -0,0 +1,22 @@
//// [privateNameClassExpressionLoop.ts]
const array = [];
for (let i = 0; i < 10; ++i) {
array.push(class C {
#myField = "hello";
});
}
//// [privateNameClassExpressionLoop.js]
var _a;
const array = [];
for (let i = 0; i < 10; ++i) {
let _myField;
array.push((_a = class C {
constructor() {
_myField.set(this, "hello");
}
},
_myField = new WeakMap(),
_a));
}
@@ -0,0 +1,21 @@
=== tests/cases/conformance/classes/members/privateNames/privateNameClassExpressionLoop.ts ===
const array = [];
>array : Symbol(array, Decl(privateNameClassExpressionLoop.ts, 0, 5))
for (let i = 0; i < 10; ++i) {
>i : Symbol(i, Decl(privateNameClassExpressionLoop.ts, 1, 8))
>i : Symbol(i, Decl(privateNameClassExpressionLoop.ts, 1, 8))
>i : Symbol(i, Decl(privateNameClassExpressionLoop.ts, 1, 8))
array.push(class C {
>array.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>array : Symbol(array, Decl(privateNameClassExpressionLoop.ts, 0, 5))
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>C : Symbol(C, Decl(privateNameClassExpressionLoop.ts, 2, 15))
#myField = "hello";
>#myField : Symbol(C.#myField, Decl(privateNameClassExpressionLoop.ts, 2, 24))
});
}
@@ -0,0 +1,29 @@
=== tests/cases/conformance/classes/members/privateNames/privateNameClassExpressionLoop.ts ===
const array = [];
>array : any[]
>[] : undefined[]
for (let i = 0; i < 10; ++i) {
>i : number
>0 : 0
>i < 10 : boolean
>i : number
>10 : 10
>++i : number
>i : number
array.push(class C {
>array.push(class C { #myField = "hello"; }) : number
>array.push : (...items: any[]) => number
>array : any[]
>push : (...items: any[]) => number
>class C { #myField = "hello"; } : typeof C
>C : typeof C
#myField = "hello";
>#myField : string
>"hello" : "hello"
});
}
@@ -0,0 +1,7 @@
const arr = [];
for (let i = 0; i < 10; ++i) {
class C {
prop = i;
}
arr.push(C);
}
@@ -0,0 +1,6 @@
let arr = [];
for (let i = 0; i < 10; ++i) {
arr.push(class C {
prop = i;
});
}
@@ -0,0 +1,7 @@
// @target: es2015
const array = [];
for (let i = 0; i < 10; ++i) {
array.push(class C {
#myField = "hello";
});
}
@@ -0,0 +1,11 @@
// @filename: computedPropertyNames52.js
// @out: computedPropertyNames52-emit.js
// @allowJs: true
// @target: es5, es2015
const array = [];
for (let i = 0; i < 10; ++i) {
array.push(class C {
[i] = () => C;
static [i] = 100;
})
}