diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index b5adef0c6dd33..6964705e9432e 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -1,5 +1,6 @@ import { __String, + AccessorDeclaration, addRange, append, appendIfUnique, @@ -1180,6 +1181,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode mergeLexicalEnvironment, replaceModifiers, replaceDecoratorsAndModifiers, + replacePropertyName, }; forEach(nodeFactoryPatchers, fn => fn(factory)); @@ -7149,6 +7151,26 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode Debug.assertNever(node); } + function replacePropertyName(node: T, name: T["name"]): T; + function replacePropertyName(node: AccessorDeclaration | MethodDeclaration | MethodSignature | PropertyDeclaration | PropertySignature | PropertyAssignment, name: PropertyName) { + switch (node.kind) { + case SyntaxKind.GetAccessor: + return updateGetAccessorDeclaration(node, node.modifiers, name, node.parameters, node.type, node.body); + case SyntaxKind.SetAccessor: + return updateSetAccessorDeclaration(node, node.modifiers, name, node.parameters, node.body); + case SyntaxKind.MethodDeclaration: + return updateMethodDeclaration(node, node.modifiers, node.asteriskToken, name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body); + case SyntaxKind.MethodSignature: + return updateMethodSignature(node, node.modifiers, name, node.questionToken, node.typeParameters, node.parameters, node.type); + case SyntaxKind.PropertyDeclaration: + return updatePropertyDeclaration(node, node.modifiers, name, node.questionToken ?? node.exclamationToken, node.type, node.initializer); + case SyntaxKind.PropertySignature: + return updatePropertySignature(node, node.modifiers, name, node.questionToken, node.type); + case SyntaxKind.PropertyAssignment: + return updatePropertyAssignment(node, name, node.initializer); + } + } + function asNodeArray(array: readonly T[]): NodeArray; function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined; function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined { diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 3cb50067125d5..e715a2dd815e4 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -9,6 +9,7 @@ import { arrayIsEqualTo, ArrayLiteralExpression, ArrowFunction, + AssignmentExpression, BinaryExpression, BindingElement, BindingPattern, @@ -39,18 +40,19 @@ import { elementAt, EmitFlags, EmitHint, + EqualsToken, every, Expression, ExpressionStatement, ExpressionWithTypeArguments, filter, - findSuperStatementIndexPath, first, firstOrUndefined, flatten, flattenDestructuringAssignment, flattenDestructuringBinding, FlattenLevel, + forEachChild, ForInStatement, ForOfStatement, ForStatement, @@ -58,6 +60,7 @@ import { FunctionDeclaration, FunctionExpression, FunctionLikeDeclaration, + GeneratedIdentifier, GeneratedIdentifierFlags, getAllAccessorDeclarations, getClassExtendsHeritageElement, @@ -104,6 +107,7 @@ import { isForStatement, isFunctionExpression, isFunctionLike, + isGeneratedIdentifier, isHoistedFunction, isHoistedVariableStatement, isIdentifier, @@ -113,26 +117,24 @@ import { isIterationStatement, isLabeledStatement, isModifier, - isNumericLiteral, isObjectLiteralElementLike, - isObjectLiteralExpression, isOmittedExpression, isPackedArrayLiteral, isPrivateIdentifier, - isPropertyAssignment, + isPropertyAccessExpression, isPropertyDeclaration, isPropertyName, isReturnStatement, isSpreadElement, isStatement, isStatic, + isSuperCall, isSuperProperty, isSwitchStatement, isTryStatement, isVariableDeclaration, isVariableDeclarationList, isVariableStatement, - isVoidExpression, isWithStatement, IterationStatement, LabeledStatement, @@ -154,6 +156,7 @@ import { NodeCheckFlags, NodeFlags, nodeIsSynthesized, + nullTransformationContext, NumericLiteral, ObjectLiteralElementLike, ObjectLiteralExpression, @@ -162,7 +165,9 @@ import { PrimaryExpression, ProcessLevel, processTaggedTemplateExpression, + PropertyAccessExpression, PropertyAssignment, + PropertyDeclaration, rangeEndIsOnSameLineAsRangeStart, ReturnStatement, SemicolonClassElement, @@ -187,11 +192,13 @@ import { startOnNewLine, Statement, StringLiteral, + SuperExpression, SwitchStatement, SyntaxKind, TaggedTemplateExpression, TemplateExpression, TextRange, + ThisExpression, TokenFlags, TransformationContext, TransformFlags, @@ -381,7 +388,7 @@ const enum HierarchyFacts { IterationContainer = 1 << 10, // Enclosed in an outer IterationStatement ForStatement = 1 << 11, // Enclosing block-scoped container is a ForStatement ForInOrForOfStatement = 1 << 12, // Enclosing block-scoped container is a ForInStatement or ForOfStatement - ConstructorWithCapturedSuper = 1 << 13, // Enclosed in a constructor that captures 'this' for use with 'super' + ConstructorWithSuperCall = 1 << 13, // Enclosed in a constructor that captures 'this' for use with 'super' StaticInitializer = 1 << 14, // Enclosed in a static initializer // NOTE: do not add more ancestor flags without also updating AncestorFactsMask below. @@ -404,14 +411,14 @@ const enum HierarchyFacts { // Functions, methods, and accessors are both new lexical scopes and new block scopes. FunctionIncludes = Function | TopLevel, - FunctionExcludes = BlockScopeExcludes & ~TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis | NonStaticClassElement | ConstructorWithCapturedSuper | IterationContainer | StaticInitializer, + FunctionExcludes = BlockScopeExcludes & ~TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis | NonStaticClassElement | ConstructorWithSuperCall | IterationContainer | StaticInitializer, AsyncFunctionBodyIncludes = FunctionIncludes | AsyncFunctionBody, AsyncFunctionBodyExcludes = FunctionExcludes & ~NonStaticClassElement, // Arrow functions are lexically scoped to their container, but are new block scopes. ArrowFunctionIncludes = ArrowFunction | TopLevel, - ArrowFunctionExcludes = BlockScopeExcludes & ~TopLevel | ConstructorWithCapturedSuper, + ArrowFunctionExcludes = BlockScopeExcludes & ~TopLevel | ConstructorWithSuperCall, // Constructors are both new lexical scopes and new block scopes. Constructors are also // always considered non-static members of a class. @@ -448,7 +455,8 @@ const enum HierarchyFacts { // NewTarget = 1 << 15, // Contains a 'new.target' meta-property - CapturedLexicalThis = 1 << 16, // Contains a lexical `this` reference captured by an arrow function. + LexicalThis = 1 << 16, // Contains a lexical `this` reference + CapturedLexicalThis = 1 << 17, // Contains a lexical `this` reference captured by an arrow function. // // Subtree masks @@ -457,7 +465,7 @@ const enum HierarchyFacts { SubtreeFactsMask = ~AncestorFactsMask, ArrowFunctionSubtreeExcludes = None, - FunctionSubtreeExcludes = NewTarget | CapturedLexicalThis, + FunctionSubtreeExcludes = NewTarget | LexicalThis | CapturedLexicalThis, } // dprint-ignore @@ -561,7 +569,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } function isReturnVoidStatementInConstructorWithCapturedSuper(node: Node): boolean { - return (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper) !== 0 + return (hierarchyFacts & HierarchyFacts.ConstructorWithSuperCall) !== 0 && node.kind === SyntaxKind.ReturnStatement && !(node as ReturnStatement).expression; } @@ -585,7 +593,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile function shouldVisitNode(node: Node): boolean { return (node.transformFlags & TransformFlags.ContainsES2015) !== 0 || convertedLoopState !== undefined - || (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && isOrMayContainReturnCompletion(node)) + || (hierarchyFacts & HierarchyFacts.ConstructorWithSuperCall && isOrMayContainReturnCompletion(node)) || (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatement(node)) || (getInternalEmitFlags(node) & InternalEmitFlags.TypeScriptClassWrapper) !== 0; } @@ -617,7 +625,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile function callExpressionVisitor(node: Node): VisitResult { if (node.kind === SyntaxKind.SuperKeyword) { - return visitSuperKeyword(/*isExpressionOfCall*/ true); + return visitSuperKeyword(node as SuperExpression, /*isExpressionOfCall*/ true); } return visitor(node); } @@ -741,7 +749,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return visitSpreadElement(node as SpreadElement); case SyntaxKind.SuperKeyword: - return visitSuperKeyword(/*isExpressionOfCall*/ false); + return visitSuperKeyword(node as SuperExpression, /*isExpressionOfCall*/ false); case SyntaxKind.ThisKeyword: return visitThisKeyword(node); @@ -811,7 +819,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } function returnCapturedThis(node: Node): ReturnStatement { - return setOriginalNode(factory.createReturnStatement(factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)), node); + return setOriginalNode(factory.createReturnStatement(createCapturedThis()), node); + } + + function createCapturedThis() { + return factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel) as CapturedThis; } function visitReturnStatement(node: ReturnStatement): Statement { @@ -840,6 +852,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile } function visitThisKeyword(node: Node): Node { + hierarchyFacts |= HierarchyFacts.LexicalThis; if (hierarchyFacts & HierarchyFacts.ArrowFunction && !(hierarchyFacts & HierarchyFacts.StaticInitializer)) { hierarchyFacts |= HierarchyFacts.CapturedLexicalThis; } @@ -1035,7 +1048,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - extendsClauseElement ? [factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel))] : [], + extendsClauseElement ? [factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined, createSyntheticSuper())] : [], /*type*/ undefined, transformClassBody(node, extendsClauseElement), ); @@ -1196,192 +1209,39 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return block; } - function transformConstructorBodyWorker( - prologueOut: Statement[], - statementsOut: Statement[], - statementsIn: NodeArray, - statementOffset: number, - superPath: readonly number[], - superPathDepth: number, - constructor: ConstructorDeclaration & { body: FunctionBody; }, - isDerivedClass: boolean, - hasSynthesizedSuper: boolean, - isFirstStatement: boolean, - ): boolean { - let mayReplaceThis = false; - - const superStatementIndex = superPathDepth < superPath.length ? superPath[superPathDepth] : -1; - const leadingStatementsEnd = superStatementIndex >= 0 ? superStatementIndex : statementsIn.length; - - // find the index of the first statement material to evaluation - if (isFirstStatement && superStatementIndex >= 0) { - let firstMaterialIndex = statementOffset; - while (isFirstStatement && firstMaterialIndex < superStatementIndex) { - const statement = constructor.body.statements[firstMaterialIndex]; - if (!isUninitializedVariableStatement(statement) && !isUsingDeclarationStateVariableStatement(statement)) break; - firstMaterialIndex++; - } + function isUninitializedVariableStatement(node: Statement) { + return isVariableStatement(node) && every(node.declarationList.declarations, decl => isIdentifier(decl.name) && !decl.initializer); + } - isFirstStatement = superStatementIndex === firstMaterialIndex; + function containsSuperCall(node: Node): boolean { + if (isSuperCall(node)) { + return true; } - - // visit everything prior to the statement containing `super()`. - addRange(statementsOut, visitNodes(statementsIn, visitor, isStatement, statementOffset, leadingStatementsEnd - statementOffset)); - - const superStatement = superStatementIndex >= 0 ? statementsIn[superStatementIndex] : undefined; - if (superStatement && isTryStatement(superStatement)) { - const tryBlockStatements: Statement[] = []; - - mayReplaceThis = transformConstructorBodyWorker( - prologueOut, - tryBlockStatements, - superStatement.tryBlock.statements, - /*statementOffset*/ 0, - superPath, - superPathDepth + 1, - constructor, - isDerivedClass, - hasSynthesizedSuper, - isFirstStatement, - ); - - const tryBlockStatementsArray = factory.createNodeArray(tryBlockStatements); - setTextRange(tryBlockStatementsArray, superStatement.tryBlock.statements); - - statementsOut.push(factory.updateTryStatement( - superStatement, - factory.updateBlock(superStatement.tryBlock, tryBlockStatements), - visitNode(superStatement.catchClause, visitor, isCatchClause), - visitNode(superStatement.finallyBlock, visitor, isBlock), - )); + if (!(node.transformFlags & TransformFlags.ContainsLexicalSuper)) { + return false; } - else { - const superCall = superStatement && getSuperCallFromStatement(superStatement); - let superCallExpression: Expression | undefined; - if (hasSynthesizedSuper) { - superCallExpression = createDefaultSuperCallOrThis(); - hierarchyFacts |= HierarchyFacts.ConstructorWithCapturedSuper; - } - else if (superCall) { - superCallExpression = visitSuperCallInBody(superCall); - hierarchyFacts |= HierarchyFacts.ConstructorWithCapturedSuper; - } - - if (isDerivedClass || superCallExpression) { - if ( - superCallExpression && - superStatementIndex === statementsIn.length - 1 && - !(constructor.body.transformFlags & TransformFlags.ContainsLexicalThis) - ) { - // If the subclass constructor does *not* contain `this` and *ends* with a `super()` call, we will use the - // following representation: - // - // ``` - // // es2015 (source) - // class C extends Base { - // constructor() { - // super("foo"); - // } - // } - // - // // es5 (transformed) - // var C = (function (_super) { - // function C() { - // return _super.call(this, "foo") || this; - // } - // return C; - // })(Base); - // ``` - - const superCall = cast(cast(superCallExpression, isBinaryExpression).left, isCallExpression); - const returnStatement = factory.createReturnStatement(superCallExpression); - setCommentRange(returnStatement, getCommentRange(superCall)); - setEmitFlags(superCall, EmitFlags.NoComments); - statementsOut.push(returnStatement); - return false; - } - else { - // Otherwise, we will use the following transformed representation for calls to `super()` in a constructor: - // - // ``` - // // es2015 (source) - // class C extends Base { - // constructor() { - // super("foo"); - // this.x = 1; - // } - // } - // - // // es5 (transformed) - // var C = (function (_super) { - // function C() { - // var _this = _super.call(this, "foo") || this; - // _this.x = 1; - // return _this; - // } - // return C; - // })(Base); - // ``` - - // If the super() call is the first statement, we can directly create and assign its result to `_this` - if (isFirstStatement) { - insertCaptureThisForNode(statementsOut, constructor, superCallExpression || createActualThis()); - } - // Since the `super()` call isn't the first statement, it's split across 1-2 statements: - // * A prologue `var _this = this;`, in case the constructor accesses this before super() - // * If it exists, a reassignment to that `_this` of the super() call - else { - insertCaptureThisForNode(prologueOut, constructor, createActualThis()); - if (superCallExpression) { - addSuperThisCaptureThisForNode(statementsOut, superCallExpression); - } - } + switch (node.kind) { + // stop at function boundaries + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.ClassStaticBlockDeclaration: + return false; - mayReplaceThis = true; + // only step into computed property names for class and object literal elements + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.PropertyDeclaration: { + const named = node as AccessorDeclaration | MethodDeclaration | PropertyDeclaration; + if (isComputedPropertyName(named.name)) { + return !!forEachChild(named.name, containsSuperCall); } - } - else { - // If a class is not derived from a base class or does not have a call to `super()`, `this` is only - // captured when necessitated by an arrow function capturing the lexical `this`: - // - // ``` - // // es2015 - // class C {} - // - // // es5 - // var C = (function () { - // function C() { - // } - // return C; - // })(); - // ``` - insertCaptureThisForNodeIfNeeded(prologueOut, constructor); + return false; } } - - // visit everything following the statement containing `super()`. - if (superStatementIndex >= 0) { - addRange(statementsOut, visitNodes(statementsIn, visitor, isStatement, superStatementIndex + 1)); - } - - return mayReplaceThis; - } - - function isUninitializedVariableStatement(node: Statement) { - return isVariableStatement(node) && every(node.declarationList.declarations, decl => isIdentifier(decl.name) && !decl.initializer); - } - - function isUsingDeclarationStateVariableStatement(node: Statement) { - if (!isVariableStatement(node) || node.declarationList.declarations.length !== 1) return false; - const varDecl = node.declarationList.declarations[0]; - if (!isIdentifier(varDecl.name) || !varDecl.initializer) return false; - const initializer = varDecl.initializer; - if (!isObjectLiteralExpression(initializer) || initializer.properties.length !== 3) return false; - const [stackProp, errorProp, hasErrorProp] = initializer.properties; - if (!isPropertyAssignment(stackProp) || !isIdentifier(stackProp.name) || idText(stackProp.name) !== "stack" || !isArrayLiteralExpression(stackProp.initializer)) return false; - if (!isPropertyAssignment(errorProp) || !isIdentifier(errorProp.name) || idText(errorProp.name) !== "error" || !isVoidExpression(errorProp.initializer) || !isNumericLiteral(errorProp.initializer.expression)) return false; - if (!isPropertyAssignment(hasErrorProp) || !isIdentifier(hasErrorProp.name) || idText(hasErrorProp.name) !== "hasError" || hasErrorProp.initializer.kind !== SyntaxKind.FalseKeyword) return false; - return true; + return !!forEachChild(node, containsSuperCall); } /** @@ -1423,32 +1283,29 @@ export function transformES2015(context: TransformationContext): (x: SourceFile // In derived classes, there may be code before the necessary super() call // We'll remove pre-super statements to be tacked on after the rest of the body const standardPrologueEnd = factory.copyStandardPrologue(constructor.body.statements, prologue, /*statementOffset*/ 0); - const superStatementIndices = findSuperStatementIndexPath(constructor.body.statements, standardPrologueEnd); - if (hasSynthesizedSuper || superStatementIndices.length > 0) { - hierarchyFacts |= HierarchyFacts.ConstructorWithCapturedSuper; - } - - const mayReplaceThis = transformConstructorBodyWorker( - prologue, - statements, - constructor.body.statements, - standardPrologueEnd, - superStatementIndices, - /*superPathDepth*/ 0, - constructor, - isDerivedClass, - hasSynthesizedSuper, - /*isFirstStatement*/ true, // NOTE: this will be recalculated inside of transformConstructorBodyWorker - ); + if (hasSynthesizedSuper || containsSuperCall(constructor.body)) { + hierarchyFacts |= HierarchyFacts.ConstructorWithSuperCall; + } + + addRange(statements, visitNodes(constructor.body.statements, visitor, isStatement, standardPrologueEnd)); + + const mayReplaceThis = isDerivedClass || hierarchyFacts & HierarchyFacts.ConstructorWithSuperCall; // Add parameter defaults at the beginning of the output, with prologue statements addDefaultValueAssignmentsIfNeeded(prologue, constructor); addRestParameterIfNeeded(prologue, constructor, hasSynthesizedSuper); insertCaptureNewTargetIfNeeded(prologue, constructor); + if (mayReplaceThis) { + insertCaptureThisForNode(prologue, constructor, createActualThis()); + } + else { + insertCaptureThisForNodeIfNeeded(prologue, constructor); + } + factory.mergeLexicalEnvironment(prologue, endLexicalEnvironment()); if (mayReplaceThis && !isSufficientlyCoveredByReturnStatements(constructor.body)) { - statements.push(factory.createReturnStatement(factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel))); + statements.push(factory.createReturnStatement(createCapturedThis())); } const body = factory.createBlock( @@ -1465,6 +1322,469 @@ export function transformES2015(context: TransformationContext): (x: SourceFile ); setTextRange(body, constructor.body); + return simplifyConstructor(body, constructor.body, hasSynthesizedSuper); + } + + type CapturedThis = GeneratedIdentifier & { readonly escapedText: __String & "__this"; }; + type SyntheticSuper = GeneratedIdentifier & { readonly escapedText: __String & "__super"; }; + type ThisCapturingVariableDeclaration = VariableDeclaration & { readonly name: CapturedThis; readonly initializer: Expression; }; + type ThisCapturingVariableStatement = VariableStatement & { readonly declarationList: { readonly declarations: { 0: ThisCapturingVariableDeclaration; }; }; }; + type ThisCapturingAssignmentExpression = AssignmentExpression & { readonly left: CapturedThis; }; + type TransformedSuperCall = CallExpression & { readonly expression: PropertyAccessExpression & { readonly expression: SyntheticSuper; }; }; + type TransformedSuperCallWithFallback = BinaryExpression & { readonly left: TransformedSuperCall; readonly right: ThisExpression; }; + type ImplicitSuperCall = BinaryExpression & { readonly left: BinaryExpression; readonly right: TransformedSuperCall; }; + type ImplicitSuperCallWithFallback = BinaryExpression & { readonly left: ImplicitSuperCall; readonly right: ThisExpression; }; + type ThisCapturingTransformedSuperCallWithFallback = ThisCapturingAssignmentExpression & { readonly right: TransformedSuperCallWithFallback; }; + type ThisCapturingImplicitSuperCallWithFallback = ThisCapturingAssignmentExpression & { readonly right: ImplicitSuperCallWithFallback; }; + type TransformedSuperCallLike = + | TransformedSuperCall + | TransformedSuperCallWithFallback + | ThisCapturingTransformedSuperCallWithFallback + | ImplicitSuperCall + | ImplicitSuperCallWithFallback + | ThisCapturingImplicitSuperCallWithFallback; + + /** Tests whether `node` is a generated identifier whose base text is `_this` */ + function isCapturedThis(node: Node): node is CapturedThis { + return isGeneratedIdentifier(node) && idText(node) === "_this"; + } + + /** Tests whether `node` is a generated identifier whose base text is `_super` */ + function isSyntheticSuper(node: Node): node is SyntheticSuper { + return isGeneratedIdentifier(node) && + idText(node) === "_super"; + } + + /** Tests whether `node` is VariableStatement like `var _this = ...;` */ + function isThisCapturingVariableStatement(node: Node): node is ThisCapturingVariableStatement { + return isVariableStatement(node) && node.declarationList.declarations.length === 1 && + isThisCapturingVariableDeclaration(node.declarationList.declarations[0]); + } + + /** Tests whether `node` is a VariableDeclaration like in `var _this = ...` */ + function isThisCapturingVariableDeclaration(node: Node): node is ThisCapturingVariableDeclaration { + return isVariableDeclaration(node) && isCapturedThis(node.name) && !!node.initializer; + } + + /** Tests whether `node` is an AssignmentExpression like `_this = ...` */ + function isThisCapturingAssignment(node: Node): node is ThisCapturingAssignmentExpression { + return isAssignmentExpression(node, /*excludeCompoundAssignment*/ true) && isCapturedThis(node.left); + } + + /** Tests whether `node` is a call like `_super.call(this, ...)` or `_super.apply(this, ...)` */ + function isTransformedSuperCall(node: Node): node is TransformedSuperCall { + return isCallExpression(node) && + isPropertyAccessExpression(node.expression) && + isSyntheticSuper(node.expression.expression) && + isIdentifier(node.expression.name) && + (idText(node.expression.name) === "call" || idText(node.expression.name) === "apply") && + node.arguments.length >= 1 && + node.arguments[0].kind === SyntaxKind.ThisKeyword; + } + + /** Tests whether `node` is an expression like `_super.call(this) || this` */ + function isTransformedSuperCallWithFallback(node: Node): node is TransformedSuperCallWithFallback { + return isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.BarBarToken && + node.right.kind === SyntaxKind.ThisKeyword && + isTransformedSuperCall(node.left); + } + + /** Tests whether `node` is a call like `_super !== null && _super.apply(this, arguments)` */ + function isImplicitSuperCall(node: Node): node is ImplicitSuperCall { + return isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken && + isBinaryExpression(node.left) && node.left.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken && + isSyntheticSuper(node.left.left) && + node.left.right.kind === SyntaxKind.NullKeyword && + isTransformedSuperCall(node.right) && + idText(node.right.expression.name) === "apply"; + } + + /** Tests whether `node` is an expression like `_super !== null && _super.apply(this, arguments) || this` */ + function isImplicitSuperCallWithFallback(node: Node): node is ImplicitSuperCallWithFallback { + return isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.BarBarToken && + node.right.kind === SyntaxKind.ThisKeyword && + isImplicitSuperCall(node.left); + } + + /** Tests whether `node` is an expression like `_this = _super.call(this) || this` */ + function isThisCapturingTransformedSuperCallWithFallback(node: Node): node is ThisCapturingTransformedSuperCallWithFallback { + return isThisCapturingAssignment(node) && isTransformedSuperCallWithFallback(node.right); + } + + /** Tests whether `node` is an expression like `_this = _super.call(this) || this` */ + function isThisCapturingImplicitSuperCallWithFallback(node: Node): node is ThisCapturingImplicitSuperCallWithFallback { + return isThisCapturingAssignment(node) && isImplicitSuperCallWithFallback(node.right); + } + + function isTransformedSuperCallLike(node: Node): node is TransformedSuperCallLike { + return isTransformedSuperCall(node) || + isTransformedSuperCallWithFallback(node) || + isThisCapturingTransformedSuperCallWithFallback(node) || + isImplicitSuperCall(node) || + isImplicitSuperCallWithFallback(node) || + isThisCapturingImplicitSuperCallWithFallback(node); + } + + /** + * Simplifies a constructor by inlining `_this = _super.call(this) || this;` into a `var _this = this;` statement + * that precedes it when they appear at the top level of the constructor body. No nested transformation is performed + * as it is assumed that `body` has already been transformed prior to invoking this function. + */ + function simplifyConstructorInlineSuperInThisCaptureVariable(body: Block) { + // given: + // + // var C = (function (_super) { + // function C() { + // var _this = this; + // _this = _super.call(this) || this; + // _this.x = 1; + // return _this; + // } + // return C; + // })(Base); + // + // simplifies to: + // + // var C = (function (_super) { + // function C() { + // var _this = _super.call(this) || this; + // _this.x = 1; + // return _this; + // } + // return C; + // })(Base); + // + + for (let i = 0; i < body.statements.length - 1; i++) { + const statement = body.statements[i]; + // walk forward until we find `var _this = ...;` + if (!isThisCapturingVariableStatement(statement)) { + continue; + } + + // Only perform inlining for `var _this = this;` + const varDecl = statement.declarationList.declarations[0]; + if (varDecl.initializer.kind !== SyntaxKind.ThisKeyword) { + continue; + } + + // It's possible that temporary variables may have been injected between `var _this` and `_this = ...`, + // so we'll track any intervening statements to stitch them back in to the result. + const thisCaptureStatementIndex = i; + let superCallIndex = i + 1; + while (superCallIndex < body.statements.length) { + const statement = body.statements[superCallIndex]; + // stop on the next `_this = _super.call(...) || this` statement + if (isExpressionStatement(statement)) { + if (isTransformedSuperCallLike(skipOuterExpressions(statement.expression))) { + break; + } + } + + // skip over hoisted temporary variables + if (isUninitializedVariableStatement(statement)) { + superCallIndex++; + continue; + } + + // if there are any other statements following `var _this = ...` then we cannot simplify. + return body; + } + + const following = body.statements[superCallIndex] as ExpressionStatement; + + // If the expression that follows is `_this = ...`, strip off the assignment to `_this` since that will + // be handled by the variable initializer. + let expression = following.expression; + if (isThisCapturingAssignment(expression)) { + expression = expression.right; + } + + const newVarDecl = factory.updateVariableDeclaration( + varDecl, + varDecl.name, + /*exclamationToken*/ undefined, + /*type*/ undefined, + expression, + ); + + const newDeclList = factory.updateVariableDeclarationList(statement.declarationList, [newVarDecl]); + const newVarStatement = factory.createVariableStatement(statement.modifiers, newDeclList); + setOriginalNode(newVarStatement, following); + setTextRange(newVarStatement, following); + const newStatements = factory.createNodeArray([ + ...body.statements.slice(0, thisCaptureStatementIndex), // copy statements preceding to `var _this` + ...body.statements.slice(thisCaptureStatementIndex + 1, superCallIndex), // copy intervening temp variables + newVarStatement, + ...body.statements.slice(superCallIndex + 1), // copy statements following `super.call(this, ...)` + ]); + setTextRange(newStatements, body.statements); + return factory.updateBlock(body, newStatements); + } + + return body; + } + + /** + * Simplifies a constructor by inlining `_this = _super.call(this) || this;` into a `return _this;` statement + * that follows it when they appear at the top level of the constructor body. No nested transformation is performed + * as it is assumed that `body` has already been transformed prior to invoking this function. + */ + function simplifyConstructorInlineSuperReturn(body: Block, original: Block) { + // given: + // + // var C = (function (_super) { + // function C() { + // ... + // _this = _super.call(this) || this; + // return _this; + // } + // return C; + // })(Base); + // + // simplifies to: + // + // var C = (function (_super) { + // function C() { + // ... + // return _super.call(this) || this; + // } + // return C; + // })(Base); + // + + // bail if there is a non-top-level `super()` in the original body + for (const statement of original.statements) { + if (statement.transformFlags & TransformFlags.ContainsLexicalSuper && !getSuperCallFromStatement(statement)) { + return body; + } + } + + // If the original node contained a lexical `this` that must be preserved, or if we recorded a captured `this` + // or `super`, then we cannot simplify `var _this = ...;`, but may still be able to inline standalone `_this = ...` + // assignment statements. + const canElideThisCapturingVariable = !(original.transformFlags & TransformFlags.ContainsLexicalThis) && + !(hierarchyFacts & HierarchyFacts.LexicalThis) && + !(hierarchyFacts & HierarchyFacts.CapturedLexicalThis); + + // find the return statement and the preceding transformed `super()` call + for (let i = body.statements.length - 1; i > 0; i--) { + // walk backwards until we find a `return _this;` + const statement = body.statements[i]; + if (isReturnStatement(statement) && statement.expression && isCapturedThis(statement.expression)) { + const preceding = body.statements[i - 1]; + let expression: Expression | undefined; + if ( + isExpressionStatement(preceding) && + isThisCapturingTransformedSuperCallWithFallback(skipOuterExpressions(preceding.expression)) + ) { + // The preceding statement is `_this = _super.call(this, ...) || this`, so we'll inline the + // expression. + expression = preceding.expression; + } + else if (canElideThisCapturingVariable && isThisCapturingVariableStatement(preceding)) { + const varDecl = preceding.declarationList.declarations[0]; + if (isTransformedSuperCallLike(skipOuterExpressions(varDecl.initializer))) { + // The preceding statement is `var _this = _super.call(this, ...) || this`, so we'll inline the + // initializer as a `_this` assignment, though it may be removed in a later pass. + expression = factory.createAssignment( + createCapturedThis(), + varDecl.initializer, + ); + } + } + + if (!expression) { + break; + } + + const newReturnStatement = factory.createReturnStatement(expression); + setOriginalNode(newReturnStatement, preceding); + setTextRange(newReturnStatement, preceding); + const newStatements = factory.createNodeArray([ + ...body.statements.slice(0, i - 1), // copy all statements preceding `_super.call(this, ...)` + newReturnStatement, + ...body.statements.slice(i + 1), // copy all statements following `return _this;` + ]); + setTextRange(newStatements, body.statements); + return factory.updateBlock(body, newStatements); + } + } + + return body; + } + + /** Elides `var _this =` and `_this =` within the current function scope. */ + function elideUnusedThisCaptureWorker(node: Node): VisitResult { + if (isThisCapturingVariableStatement(node)) { + const varDecl = node.declarationList.declarations[0]; + if (varDecl.initializer.kind === SyntaxKind.ThisKeyword) { + return undefined; // elide `var _this = this;` + } + } + else if (isThisCapturingAssignment(node)) { + return factory.createPartiallyEmittedExpression(node.right, node); // elide `_this =` + } + + switch (node.kind) { + // stop at function boundaries + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.ClassStaticBlockDeclaration: + return node; + + // only step into computed property names for class and object literal elements + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.PropertyDeclaration: { + const named = node as AccessorDeclaration | MethodDeclaration | PropertyDeclaration; + if (isComputedPropertyName(named.name)) { + return factory.replacePropertyName(named, visitEachChild(named.name, elideUnusedThisCaptureWorker, nullTransformationContext)); + } + return node; + } + } + return visitEachChild(node, elideUnusedThisCaptureWorker, nullTransformationContext); + } + + /** + * Simplifies a constructor by eliding `var _this = this;` and `_this = ...` when `this` capturing is no longer + * necessary after other simplifications have been performed. No nested transformation is performed as it is assumed + * that `body` has already been transformed prior to invoking this function. It is also assumed that this function is + * only invoked after some other simplification has successfully replaced `body`. + */ + function simplifyConstructorElideUnusedThisCapture(body: Block, original: Block) { + // given: + // + // var C = (function (_super) { + // function C() { + // var _this = this; + // return _super.call(this) || this; + // } + // return C; + // })(Base); + // + // becomes: + // + // var C = (function (_super) { + // function C() { + // return _super.call(this) || this; + // } + // return C; + // })(Base); + // + + // If the original node contained a lexical `this` that must be preserved, or if we recorded a captured `this`, + // then there is nothing we can simplify. + if ( + original.transformFlags & TransformFlags.ContainsLexicalThis || + hierarchyFacts & HierarchyFacts.LexicalThis || + hierarchyFacts & HierarchyFacts.CapturedLexicalThis + ) { + return body; + } + + // bail if there is a non-top-level `super()` in the original body + for (const statement of original.statements) { + if (statement.transformFlags & TransformFlags.ContainsLexicalSuper && !getSuperCallFromStatement(statement)) { + return body; + } + } + + return factory.updateBlock(body, visitNodes(body.statements, elideUnusedThisCaptureWorker, isStatement)); + } + + /** Injects `_super !== null &&` preceding any instance of a synthetic `_super.apply(this, arguments)` */ + function injectSuperPresenceCheckWorker(node: Node): VisitResult { + if ( + isTransformedSuperCall(node) && node.arguments.length === 2 && + isIdentifier(node.arguments[1]) && idText(node.arguments[1]) === "arguments" + ) { + return factory.createLogicalAnd( + factory.createStrictInequality( + createSyntheticSuper(), + factory.createNull(), + ), + node, + ); + } + + switch (node.kind) { + // stop at function boundaries + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.ClassStaticBlockDeclaration: + return node; + + // only step into computed property names for class and object literal elements + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.PropertyDeclaration: { + const named = node as AccessorDeclaration | MethodDeclaration | PropertyDeclaration; + if (isComputedPropertyName(named.name)) { + return factory.replacePropertyName(named, visitEachChild(named.name, injectSuperPresenceCheckWorker, nullTransformationContext)); + } + return node; + } + } + return visitEachChild(node, injectSuperPresenceCheckWorker, nullTransformationContext); + } + + /** + * A slight non-simplification of a constructor, this injects a `_super !== null` test prior to a synthetic + * `_super.call(this)` expression to support the synthetic super call we introduce for subclasses with an + * implicit constructor, in the event the derviced class in the `extends` clause evaluates to `null`. No nested + * transformation is performed as it is assumed that `body` has already been transformed prior to invoking this + * function. It is also assumed that this function is only invoked for a constructor containing a synthetic + * implicit `super()` call. + */ + function complicateConstructorInjectSuperPresenceCheck(body: Block) { + // given: + // + // var C = (function (_super) { + // function C() { + // return _super.call(this) || this; + // } + // return C; + // })(Base); + // + // becomes: + // + // var C = (function (_super) { + // function C() { + // return _super !== null && _super.call(this) || this; + // } + // return C; + // })(Base); + // + + return factory.updateBlock(body, visitNodes(body.statements, injectSuperPresenceCheckWorker, isStatement)); + } + + /** + * Simplifies a derived constructor by performing inlining tasks related to this-capturing and transformed + * `super()` calls. + * @param body The constructor body. + * @param original The original constructor body. + * @param hasSynthesizedSuper A value indicating whether the body may contain a synthetic implicit `super()` call. + */ + function simplifyConstructor(body: Block, original: Block, hasSynthesizedSuper: boolean) { + const inputBody = body; + body = simplifyConstructorInlineSuperInThisCaptureVariable(body); + body = simplifyConstructorInlineSuperReturn(body, original); + if (body !== inputBody) { + // Only perform `var _this = this` elision if some other simplification succeeded. + body = simplifyConstructorElideUnusedThisCapture(body, original); + } + if (hasSynthesizedSuper) { + body = complicateConstructorInjectSuperPresenceCheck(body); + } return body; } @@ -1505,11 +1825,11 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return factory.createLogicalOr( factory.createLogicalAnd( factory.createStrictInequality( - factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + createSyntheticSuper(), factory.createNull(), ), factory.createFunctionApplyCall( - factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + createSyntheticSuper(), createActualThis(), factory.createIdentifier("arguments"), ), @@ -1836,32 +2156,13 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return false; } - /** - * Assigns the `this` in a constructor to the result of its `super()` call. - * - * @param statements Statements in the constructor body. - * @param superExpression Existing `super()` call for the constructor. - */ - function addSuperThisCaptureThisForNode(statements: Statement[], superExpression: Expression): void { - enableSubstitutionsForCapturedThis(); - const assignSuperExpression = factory.createExpressionStatement( - factory.createBinaryExpression( - factory.createThis(), - SyntaxKind.EqualsToken, - superExpression, - ), - ); - statements.push(assignSuperExpression); - setCommentRange(assignSuperExpression, getOriginalNode(superExpression).parent); - } - function insertCaptureThisForNode(statements: Statement[], node: Node, initializer: Expression | undefined): void { enableSubstitutionsForCapturedThis(); const captureThisStatement = factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList([ factory.createVariableDeclaration( - factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), + createCapturedThis(), /*exclamationToken*/ undefined, /*type*/ undefined, initializer, @@ -4219,10 +4520,6 @@ export function transformES2015(context: TransformationContext): (x: SourceFile ); } - function visitSuperCallInBody(node: CallExpression) { - return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ false); - } - function visitCallExpressionWithPotentialCapturedThisAssignment(node: CallExpression, assignToCapturedThis: boolean): CallExpression | BinaryExpression { // We are here either because SuperKeyword was used somewhere in the expression, or // because we contain a SpreadElementExpression. @@ -4284,12 +4581,16 @@ export function transformES2015(context: TransformationContext): (x: SourceFile createActualThis(), ); resultingCall = assignToCapturedThis - ? factory.createAssignment(factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), initializer) + ? factory.createAssignment(createCapturedThis(), initializer) : initializer; } return setOriginalNode(resultingCall, node); } + if (isSuperCall(node)) { + hierarchyFacts |= HierarchyFacts.CapturedLexicalThis; + } + return visitEachChild(node, visitor, context); } @@ -4520,14 +4821,21 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return setTextRange(expression, node); } + function createSyntheticSuper() { + return factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel) as SyntheticSuper; + } + /** * Visits the `super` keyword */ - function visitSuperKeyword(isExpressionOfCall: boolean): LeftHandSideExpression { - return hierarchyFacts & HierarchyFacts.NonStaticClassElement - && !isExpressionOfCall - ? factory.createPropertyAccessExpression(factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), "prototype") - : factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel); + function visitSuperKeyword(node: SuperExpression, isExpressionOfCall: boolean): LeftHandSideExpression { + const expression = hierarchyFacts & HierarchyFacts.NonStaticClassElement && !isExpressionOfCall + ? factory.createPropertyAccessExpression(setOriginalNode(createSyntheticSuper(), node), "prototype") + : createSyntheticSuper(); + setOriginalNode(expression, node); + setCommentRange(expression, node); + setSourceMapRange(expression, node); + return expression; } function visitMetaProperty(node: MetaProperty) { @@ -4712,7 +5020,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis && hierarchyFacts & HierarchyFacts.CapturesThis ) { - return setTextRange(factory.createUniqueName("_this", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel), node); + return setTextRange(createCapturedThis(), node); } return node; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f8cde0c9787da..e0e9be8dc3ba3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -9080,6 +9080,10 @@ export interface NodeFactory { * Updates a node that may contain decorators or modifiers, replacing only the decorators and modifiers of the node. */ replaceDecoratorsAndModifiers(node: T, modifiers: readonly ModifierLike[] | undefined): T; + /** + * Updates a node that contains a property name, replacing only the name of the node. + */ + replacePropertyName(node: T, name: T["name"]): T; } /** @internal */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 42d824b69c91a..a0da94069a0e8 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -8394,6 +8394,10 @@ declare namespace ts { * Updates a node that may contain decorators or modifiers, replacing only the decorators and modifiers of the node. */ replaceDecoratorsAndModifiers(node: T, modifiers: readonly ModifierLike[] | undefined): T; + /** + * Updates a node that contains a property name, replacing only the name of the node. + */ + replacePropertyName(node: T, name: T["name"]): T; } interface CoreTransformationContext { readonly factory: NodeFactory; diff --git a/tests/baselines/reference/callWithSpread.js b/tests/baselines/reference/callWithSpread.js index 02e5799197780..6bf603161d25c 100644 --- a/tests/baselines/reference/callWithSpread.js +++ b/tests/baselines/reference/callWithSpread.js @@ -136,8 +136,7 @@ var D = /** @class */ (function (_super) { __extends(D, _super); function D() { var _this = _super.call(this, 1, 2) || this; - _this = _super.apply(this, __spreadArray([1, 2], a, false)) || this; - return _this; + return _super.apply(this, __spreadArray([1, 2], a, false)) || this; } D.prototype.foo = function () { _super.prototype.foo.call(this, 1, 2); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.js index 3289e9fc6b35b..78dcd037c53d5 100644 --- a/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.js +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing6.js @@ -42,8 +42,7 @@ var Super = /** @class */ (function (_super) { function Super() { var _this = this; (function () { return _this; }); // No Error - _this = _super.call(this) || this; - return _this; + return _this = _super.call(this) || this; } return Super; }(Base)); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.js index 94dc2366fae10..6ea9f8f789244 100644 --- a/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.js +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing7.js @@ -35,7 +35,7 @@ var Base = /** @class */ (function () { var Super = /** @class */ (function (_super) { __extends(Super, _super); function Super() { - var _this = _super.call(this, (function () { return _this; })) || this; + var _this = _super.call(this, (function () { return _this; })) || this; // No error return _this; } return Super; diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.js b/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.js index c89ffd4cfb615..08a0f865e8b1a 100644 --- a/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.js +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing8.js @@ -42,8 +42,7 @@ var Super = /** @class */ (function (_super) { function Super() { var _this = this; var that = _this; - _this = _super.call(this) || this; - return _this; + return _this = _super.call(this) || this; } return Super; }(Base)); diff --git a/tests/baselines/reference/classUpdateTests.js b/tests/baselines/reference/classUpdateTests.js index 683a2d96a3017..6e25d0c15a258 100644 --- a/tests/baselines/reference/classUpdateTests.js +++ b/tests/baselines/reference/classUpdateTests.js @@ -208,7 +208,7 @@ var I = /** @class */ (function (_super) { var J = /** @class */ (function (_super) { __extends(J, _super); function J(p1) { - var _this = _super.call(this) || this; + var _this = _super.call(this) || this; // NO ERROR _this.p1 = p1; return _this; } @@ -228,7 +228,7 @@ var K = /** @class */ (function (_super) { var L = /** @class */ (function (_super) { __extends(L, _super); function L(p1) { - var _this = _super.call(this) || this; + var _this = _super.call(this) || this; // NO ERROR _this.p1 = p1; return _this; } diff --git a/tests/baselines/reference/derivedClassConstructorWithExplicitReturns01.js.map b/tests/baselines/reference/derivedClassConstructorWithExplicitReturns01.js.map index 867cf6af4908b..591d33250101c 100644 --- a/tests/baselines/reference/derivedClassConstructorWithExplicitReturns01.js.map +++ b/tests/baselines/reference/derivedClassConstructorWithExplicitReturns01.js.map @@ -1,3 +1,3 @@ //// [derivedClassConstructorWithExplicitReturns01.js.map] -{"version":3,"file":"derivedClassConstructorWithExplicitReturns01.js","sourceRoot":"","sources":["derivedClassConstructorWithExplicitReturns01.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;IAKI,WAAY,KAAa;QAJzB,UAAK,GAAG,EAAE,CAAC;QAKP,OAAO;YACH,KAAK,EAAE,KAAK;YACZ,GAAG;gBACC,OAAO,8BAA8B,CAAC;YAC1C,CAAC;SACJ,CAAA;IACL,CAAC;IATD,eAAG,GAAH,cAAQ,OAAO,uBAAuB,CAAC,CAAC,CAAC;IAU7C,QAAC;AAAD,CAAC,AAbD,IAaC;AAED;IAAgB,qBAAC;IAGb,WAAY,CAAO;QAAP,kBAAA,EAAA,OAAO;QAAnB,YACI,kBAAM,CAAC,CAAC,SAYX;QAfD,WAAK,GAAG,cAAM,OAAA,KAAI,EAAJ,CAAI,CAAC;QAKf,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC;YACtB,UAAU,CAAA;YACV,OAAO;gBACH,KAAK,EAAE,CAAC;gBACR,KAAK,EAAE,cAAM,OAAA,KAAI,EAAJ,CAAI;gBACjB,GAAG,gBAAK,OAAO,cAAc,CAAA,CAAC,CAAC;aAClC,CAAC;QACN,CAAC;;YAEG,OAAO,IAAI,CAAC;IACpB,CAAC;IACL,QAAC;AAAD,CAAC,AAjBD,CAAgB,CAAC,GAiBhB"} -//// https://sokra.github.io/source-map-visualization#base64,dmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkgew0KICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHsNCiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fA0KICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fA0KICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTsNCiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7DQogICAgfTsNCiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHsNCiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSAiZnVuY3Rpb24iICYmIGIgIT09IG51bGwpDQogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDbGFzcyBleHRlbmRzIHZhbHVlICIgKyBTdHJpbmcoYikgKyAiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGwiKTsNCiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTsNCiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9DQogICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTsNCiAgICB9Ow0KfSkoKTsNCnZhciBDID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkgew0KICAgIGZ1bmN0aW9uIEModmFsdWUpIHsNCiAgICAgICAgdGhpcy5jUHJvcCA9IDEwOw0KICAgICAgICByZXR1cm4gew0KICAgICAgICAgICAgY1Byb3A6IHZhbHVlLA0KICAgICAgICAgICAgZm9vOiBmdW5jdGlvbiAoKSB7DQogICAgICAgICAgICAgICAgcmV0dXJuICJ3ZWxsIHRoaXMgbG9va3Mga2luZGEgQy1pc2guIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfTsNCiAgICB9DQogICAgQy5wcm90b3R5cGUuZm9vID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gInRoaXMgbmV2ZXIgZ2V0cyB1c2VkLiI7IH07DQogICAgcmV0dXJuIEM7DQp9KCkpOw0KdmFyIEQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7DQogICAgX19leHRlbmRzKEQsIF9zdXBlcik7DQogICAgZnVuY3Rpb24gRChhKSB7DQogICAgICAgIGlmIChhID09PSB2b2lkIDApIHsgYSA9IDEwMDsgfQ0KICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBhKSB8fCB0aGlzOw0KICAgICAgICBfdGhpcy5kUHJvcCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzOyB9Ow0KICAgICAgICBpZiAoTWF0aC5yYW5kb20oKSA8IDAuNSkgew0KICAgICAgICAgICAgIllvdSB3aW4hIjsNCiAgICAgICAgICAgIHJldHVybiB7DQogICAgICAgICAgICAgICAgY1Byb3A6IDEsDQogICAgICAgICAgICAgICAgZFByb3A6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzOyB9LA0KICAgICAgICAgICAgICAgIGZvbzogZnVuY3Rpb24gKCkgeyByZXR1cm4gIllvdSB3aW4hISEhISI7IH0NCiAgICAgICAgICAgIH07DQogICAgICAgIH0NCiAgICAgICAgZWxzZQ0KICAgICAgICAgICAgcmV0dXJuIG51bGw7DQogICAgfQ0KICAgIHJldHVybiBEOw0KfShDKSk7DQovLyMgc291cmNlTWFwcGluZ1VSTD1kZXJpdmVkQ2xhc3NDb25zdHJ1Y3RvcldpdGhFeHBsaWNpdFJldHVybnMwMS5qcy5tYXA=,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVyaXZlZENsYXNzQ29uc3RydWN0b3JXaXRoRXhwbGljaXRSZXR1cm5zMDEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkZXJpdmVkQ2xhc3NDb25zdHJ1Y3RvcldpdGhFeHBsaWNpdFJldHVybnMwMS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQTtJQUtJLFdBQVksS0FBYTtRQUp6QixVQUFLLEdBQUcsRUFBRSxDQUFDO1FBS1AsT0FBTztZQUNILEtBQUssRUFBRSxLQUFLO1lBQ1osR0FBRztnQkFDQyxPQUFPLDhCQUE4QixDQUFDO1lBQzFDLENBQUM7U0FDSixDQUFBO0lBQ0wsQ0FBQztJQVRELGVBQUcsR0FBSCxjQUFRLE9BQU8sdUJBQXVCLENBQUMsQ0FBQyxDQUFDO0lBVTdDLFFBQUM7QUFBRCxDQUFDLEFBYkQsSUFhQztBQUVEO0lBQWdCLHFCQUFDO0lBR2IsV0FBWSxDQUFPO1FBQVAsa0JBQUEsRUFBQSxPQUFPO1FBQW5CLFlBQ0ksa0JBQU0sQ0FBQyxDQUFDLFNBWVg7UUFmRCxXQUFLLEdBQUcsY0FBTSxPQUFBLEtBQUksRUFBSixDQUFJLENBQUM7UUFLZixJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLEVBQUUsQ0FBQztZQUN0QixVQUFVLENBQUE7WUFDVixPQUFPO2dCQUNILEtBQUssRUFBRSxDQUFDO2dCQUNSLEtBQUssRUFBRSxjQUFNLE9BQUEsS0FBSSxFQUFKLENBQUk7Z0JBQ2pCLEdBQUcsZ0JBQUssT0FBTyxjQUFjLENBQUEsQ0FBQyxDQUFDO2FBQ2xDLENBQUM7UUFDTixDQUFDOztZQUVHLE9BQU8sSUFBSSxDQUFDO0lBQ3BCLENBQUM7SUFDTCxRQUFDO0FBQUQsQ0FBQyxBQWpCRCxDQUFnQixDQUFDLEdBaUJoQiJ9,Y2xhc3MgQyB7CiAgICBjUHJvcCA9IDEwOwoKICAgIGZvbygpIHsgcmV0dXJuICJ0aGlzIG5ldmVyIGdldHMgdXNlZC4iOyB9CgogICAgY29uc3RydWN0b3IodmFsdWU6IG51bWJlcikgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIGNQcm9wOiB2YWx1ZSwKICAgICAgICAgICAgZm9vKCkgewogICAgICAgICAgICAgICAgcmV0dXJuICJ3ZWxsIHRoaXMgbG9va3Mga2luZGEgQy1pc2guIjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKY2xhc3MgRCBleHRlbmRzIEMgewogICAgZFByb3AgPSAoKSA9PiB0aGlzOwoKICAgIGNvbnN0cnVjdG9yKGEgPSAxMDApIHsKICAgICAgICBzdXBlcihhKTsKCiAgICAgICAgaWYgKE1hdGgucmFuZG9tKCkgPCAwLjUpIHsKICAgICAgICAgICAgIllvdSB3aW4hIgogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgY1Byb3A6IDEsCiAgICAgICAgICAgICAgICBkUHJvcDogKCkgPT4gdGhpcywKICAgICAgICAgICAgICAgIGZvbygpIHsgcmV0dXJuICJZb3Ugd2luISEhISEiIH0KICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgIH0KfQ== +{"version":3,"file":"derivedClassConstructorWithExplicitReturns01.js","sourceRoot":"","sources":["derivedClassConstructorWithExplicitReturns01.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;IAKI,WAAY,KAAa;QAJzB,UAAK,GAAG,EAAE,CAAC;QAKP,OAAO;YACH,KAAK,EAAE,KAAK;YACZ,GAAG;gBACC,OAAO,8BAA8B,CAAC;YAC1C,CAAC;SACJ,CAAA;IACL,CAAC;IATD,eAAG,GAAH,cAAQ,OAAO,uBAAuB,CAAC,CAAC,CAAC;IAU7C,QAAC;AAAD,CAAC,AAbD,IAaC;AAED;IAAgB,qBAAC;IAGb,WAAY,CAAO;QAAP,kBAAA,EAAA,OAAO;QACf,YAAA,MAAK,YAAC,CAAC,CAAC,SAAC;QAHb,WAAK,GAAG,cAAM,OAAA,KAAI,EAAJ,CAAI,CAAC;QAKf,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC;YACtB,UAAU,CAAA;YACV,OAAO;gBACH,KAAK,EAAE,CAAC;gBACR,KAAK,EAAE,cAAM,OAAA,KAAI,EAAJ,CAAI;gBACjB,GAAG,gBAAK,OAAO,cAAc,CAAA,CAAC,CAAC;aAClC,CAAC;QACN,CAAC;;YAEG,OAAO,IAAI,CAAC;IACpB,CAAC;IACL,QAAC;AAAD,CAAC,AAjBD,CAAgB,CAAC,GAiBhB"} +//// https://sokra.github.io/source-map-visualization#base64,dmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkgew0KICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHsNCiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fA0KICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fA0KICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTsNCiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7DQogICAgfTsNCiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHsNCiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSAiZnVuY3Rpb24iICYmIGIgIT09IG51bGwpDQogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDbGFzcyBleHRlbmRzIHZhbHVlICIgKyBTdHJpbmcoYikgKyAiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGwiKTsNCiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTsNCiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9DQogICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTsNCiAgICB9Ow0KfSkoKTsNCnZhciBDID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkgew0KICAgIGZ1bmN0aW9uIEModmFsdWUpIHsNCiAgICAgICAgdGhpcy5jUHJvcCA9IDEwOw0KICAgICAgICByZXR1cm4gew0KICAgICAgICAgICAgY1Byb3A6IHZhbHVlLA0KICAgICAgICAgICAgZm9vOiBmdW5jdGlvbiAoKSB7DQogICAgICAgICAgICAgICAgcmV0dXJuICJ3ZWxsIHRoaXMgbG9va3Mga2luZGEgQy1pc2guIjsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfTsNCiAgICB9DQogICAgQy5wcm90b3R5cGUuZm9vID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gInRoaXMgbmV2ZXIgZ2V0cyB1c2VkLiI7IH07DQogICAgcmV0dXJuIEM7DQp9KCkpOw0KdmFyIEQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7DQogICAgX19leHRlbmRzKEQsIF9zdXBlcik7DQogICAgZnVuY3Rpb24gRChhKSB7DQogICAgICAgIGlmIChhID09PSB2b2lkIDApIHsgYSA9IDEwMDsgfQ0KICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBhKSB8fCB0aGlzOw0KICAgICAgICBfdGhpcy5kUHJvcCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzOyB9Ow0KICAgICAgICBpZiAoTWF0aC5yYW5kb20oKSA8IDAuNSkgew0KICAgICAgICAgICAgIllvdSB3aW4hIjsNCiAgICAgICAgICAgIHJldHVybiB7DQogICAgICAgICAgICAgICAgY1Byb3A6IDEsDQogICAgICAgICAgICAgICAgZFByb3A6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzOyB9LA0KICAgICAgICAgICAgICAgIGZvbzogZnVuY3Rpb24gKCkgeyByZXR1cm4gIllvdSB3aW4hISEhISI7IH0NCiAgICAgICAgICAgIH07DQogICAgICAgIH0NCiAgICAgICAgZWxzZQ0KICAgICAgICAgICAgcmV0dXJuIG51bGw7DQogICAgfQ0KICAgIHJldHVybiBEOw0KfShDKSk7DQovLyMgc291cmNlTWFwcGluZ1VSTD1kZXJpdmVkQ2xhc3NDb25zdHJ1Y3RvcldpdGhFeHBsaWNpdFJldHVybnMwMS5qcy5tYXA=,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVyaXZlZENsYXNzQ29uc3RydWN0b3JXaXRoRXhwbGljaXRSZXR1cm5zMDEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkZXJpdmVkQ2xhc3NDb25zdHJ1Y3RvcldpdGhFeHBsaWNpdFJldHVybnMwMS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQTtJQUtJLFdBQVksS0FBYTtRQUp6QixVQUFLLEdBQUcsRUFBRSxDQUFDO1FBS1AsT0FBTztZQUNILEtBQUssRUFBRSxLQUFLO1lBQ1osR0FBRztnQkFDQyxPQUFPLDhCQUE4QixDQUFDO1lBQzFDLENBQUM7U0FDSixDQUFBO0lBQ0wsQ0FBQztJQVRELGVBQUcsR0FBSCxjQUFRLE9BQU8sdUJBQXVCLENBQUMsQ0FBQyxDQUFDO0lBVTdDLFFBQUM7QUFBRCxDQUFDLEFBYkQsSUFhQztBQUVEO0lBQWdCLHFCQUFDO0lBR2IsV0FBWSxDQUFPO1FBQVAsa0JBQUEsRUFBQSxPQUFPO1FBQ2YsWUFBQSxNQUFLLFlBQUMsQ0FBQyxDQUFDLFNBQUM7UUFIYixXQUFLLEdBQUcsY0FBTSxPQUFBLEtBQUksRUFBSixDQUFJLENBQUM7UUFLZixJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxHQUFHLEVBQUUsQ0FBQztZQUN0QixVQUFVLENBQUE7WUFDVixPQUFPO2dCQUNILEtBQUssRUFBRSxDQUFDO2dCQUNSLEtBQUssRUFBRSxjQUFNLE9BQUEsS0FBSSxFQUFKLENBQUk7Z0JBQ2pCLEdBQUcsZ0JBQUssT0FBTyxjQUFjLENBQUEsQ0FBQyxDQUFDO2FBQ2xDLENBQUM7UUFDTixDQUFDOztZQUVHLE9BQU8sSUFBSSxDQUFDO0lBQ3BCLENBQUM7SUFDTCxRQUFDO0FBQUQsQ0FBQyxBQWpCRCxDQUFnQixDQUFDLEdBaUJoQiJ9,Y2xhc3MgQyB7CiAgICBjUHJvcCA9IDEwOwoKICAgIGZvbygpIHsgcmV0dXJuICJ0aGlzIG5ldmVyIGdldHMgdXNlZC4iOyB9CgogICAgY29uc3RydWN0b3IodmFsdWU6IG51bWJlcikgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIGNQcm9wOiB2YWx1ZSwKICAgICAgICAgICAgZm9vKCkgewogICAgICAgICAgICAgICAgcmV0dXJuICJ3ZWxsIHRoaXMgbG9va3Mga2luZGEgQy1pc2guIjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKY2xhc3MgRCBleHRlbmRzIEMgewogICAgZFByb3AgPSAoKSA9PiB0aGlzOwoKICAgIGNvbnN0cnVjdG9yKGEgPSAxMDApIHsKICAgICAgICBzdXBlcihhKTsKCiAgICAgICAgaWYgKE1hdGgucmFuZG9tKCkgPCAwLjUpIHsKICAgICAgICAgICAgIllvdSB3aW4hIgogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgY1Byb3A6IDEsCiAgICAgICAgICAgICAgICBkUHJvcDogKCkgPT4gdGhpcywKICAgICAgICAgICAgICAgIGZvbygpIHsgcmV0dXJuICJZb3Ugd2luISEhISEiIH0KICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgIH0KfQ== diff --git a/tests/baselines/reference/derivedClassConstructorWithExplicitReturns01.sourcemap.txt b/tests/baselines/reference/derivedClassConstructorWithExplicitReturns01.sourcemap.txt index e967981014b23..f51d0759aa4de 100644 --- a/tests/baselines/reference/derivedClassConstructorWithExplicitReturns01.sourcemap.txt +++ b/tests/baselines/reference/derivedClassConstructorWithExplicitReturns01.sourcemap.txt @@ -270,36 +270,27 @@ sourceFile:derivedClassConstructorWithExplicitReturns01.ts >>> var _this = _super.call(this, a) || this; 1->^^^^^^^^ 2 > ^^^^^^^^^^^^ -3 > ^^^^^^^^^^^^^^^^^^ -4 > ^ -5 > ^ -6 > ^^^^^^^^^ -7 > ^^^^-> -1-> -2 > constructor(a = 100) { - > -3 > super( -4 > a -5 > ) -6 > ; - > - > if (Math.random() < 0.5) { - > "You win!" - > return { - > cProp: 1, - > dProp: () => this, - > foo() { return "You win!!!!!" } - > }; - > } - > else - > return null; - > } -1->Emitted(33, 9) Source(19, 5) + SourceIndex(0) +3 > ^^^^^^ +4 > ^^^^^^^^^^^^ +5 > ^ +6 > ^ +7 > ^^^^^^^^^ +8 > ^^^^-> +1->) { + > +2 > +3 > super +4 > ( +5 > a +6 > ) +7 > ; +1->Emitted(33, 9) Source(20, 9) + SourceIndex(0) 2 >Emitted(33, 21) Source(20, 9) + SourceIndex(0) -3 >Emitted(33, 39) Source(20, 15) + SourceIndex(0) -4 >Emitted(33, 40) Source(20, 16) + SourceIndex(0) -5 >Emitted(33, 41) Source(20, 17) + SourceIndex(0) -6 >Emitted(33, 50) Source(32, 6) + SourceIndex(0) +3 >Emitted(33, 27) Source(20, 14) + SourceIndex(0) +4 >Emitted(33, 39) Source(20, 15) + SourceIndex(0) +5 >Emitted(33, 40) Source(20, 16) + SourceIndex(0) +6 >Emitted(33, 41) Source(20, 17) + SourceIndex(0) +7 >Emitted(33, 50) Source(20, 18) + SourceIndex(0) --- >>> _this.dProp = function () { return _this; }; 1->^^^^^^^^ diff --git a/tests/baselines/reference/derivedClassParameterProperties.js b/tests/baselines/reference/derivedClassParameterProperties.js index e56735c84b616..0c6bc13af140d 100644 --- a/tests/baselines/reference/derivedClassParameterProperties.js +++ b/tests/baselines/reference/derivedClassParameterProperties.js @@ -174,8 +174,7 @@ var Derived6 = /** @class */ (function (_super) { var _this = this; _this.a = 1; var b = 2; - _this = _super.call(this) || this; - return _this; + return _this = _super.call(this) || this; } return Derived6; }(Base)); diff --git a/tests/baselines/reference/derivedClassSuperCallsWithThisArg.js b/tests/baselines/reference/derivedClassSuperCallsWithThisArg.js index ba92c5001c708..f64c8a7c62a9c 100644 --- a/tests/baselines/reference/derivedClassSuperCallsWithThisArg.js +++ b/tests/baselines/reference/derivedClassSuperCallsWithThisArg.js @@ -54,7 +54,7 @@ var Base = /** @class */ (function () { var Derived = /** @class */ (function (_super) { __extends(Derived, _super); function Derived() { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // ok return _this; } return Derived; @@ -62,7 +62,7 @@ var Derived = /** @class */ (function (_super) { var Derived2 = /** @class */ (function (_super) { __extends(Derived2, _super); function Derived2(a) { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // error _this.a = a; return _this; } @@ -71,7 +71,7 @@ var Derived2 = /** @class */ (function (_super) { var Derived3 = /** @class */ (function (_super) { __extends(Derived3, _super); function Derived3(a) { - var _this = _super.call(this, function () { return _this; }) || this; + var _this = _super.call(this, function () { return _this; }) || this; // error _this.a = a; return _this; } @@ -80,7 +80,7 @@ var Derived3 = /** @class */ (function (_super) { var Derived4 = /** @class */ (function (_super) { __extends(Derived4, _super); function Derived4(a) { - var _this = _super.call(this, function () { return this; }) || this; + var _this = _super.call(this, function () { return this; }) || this; // ok _this.a = a; return _this; } diff --git a/tests/baselines/reference/derivedClassSuperProperties.js b/tests/baselines/reference/derivedClassSuperProperties.js index e87fd91b7d1ef..7a2f83b3f0108 100644 --- a/tests/baselines/reference/derivedClassSuperProperties.js +++ b/tests/baselines/reference/derivedClassSuperProperties.js @@ -638,7 +638,7 @@ var DerivedWithFunctionExpression = /** @class */ (function (_super) { var DerivedWithParenthesis = /** @class */ (function (_super) { __extends(DerivedWithParenthesis, _super); function DerivedWithParenthesis() { - var _this = _super.call(this) || this; + var _this = (_this = _super.call(this) || this); _this.prop = true; return _this; } @@ -649,7 +649,7 @@ var DerivedWithParenthesisAfterStatement = /** @class */ (function (_super) { function DerivedWithParenthesisAfterStatement() { var _this = this; _this.prop; - _this = _super.call(this) || this; + (_this = _super.call(this) || this); _this.prop = true; return _this; } @@ -658,7 +658,7 @@ var DerivedWithParenthesisAfterStatement = /** @class */ (function (_super) { var DerivedWithParenthesisBeforeStatement = /** @class */ (function (_super) { __extends(DerivedWithParenthesisBeforeStatement, _super); function DerivedWithParenthesisBeforeStatement() { - var _this = _super.call(this) || this; + var _this = (_this = _super.call(this) || this); _this.prop = true; _this.prop; return _this; diff --git a/tests/baselines/reference/derivedClassSuperStatementPosition.js b/tests/baselines/reference/derivedClassSuperStatementPosition.js index dccc2730c4c39..dcbfd4dd78bea 100644 --- a/tests/baselines/reference/derivedClassSuperStatementPosition.js +++ b/tests/baselines/reference/derivedClassSuperStatementPosition.js @@ -126,8 +126,8 @@ var DerivedBasic = /** @class */ (function (_super) { var DerivedAfterParameterDefault = /** @class */ (function (_super) { __extends(DerivedAfterParameterDefault, _super); function DerivedAfterParameterDefault(x) { - var _this = this; if (x === void 0) { x = false; } + var _this = this; _this.x1 = x; _this = _super.call(this, x) || this; _this.x2 = x; @@ -138,11 +138,11 @@ var DerivedAfterParameterDefault = /** @class */ (function (_super) { var DerivedAfterRestParameter = /** @class */ (function (_super) { __extends(DerivedAfterRestParameter, _super); function DerivedAfterRestParameter() { - var _this = this; var x = []; for (var _i = 0; _i < arguments.length; _i++) { x[_i] = arguments[_i]; } + var _this = this; _this.x1 = x; _this = _super.call(this, x) || this; _this.x2 = x; diff --git a/tests/baselines/reference/errorSuperCalls.js b/tests/baselines/reference/errorSuperCalls.js index 598d3e32848e8..be2bee7189eeb 100644 --- a/tests/baselines/reference/errorSuperCalls.js +++ b/tests/baselines/reference/errorSuperCalls.js @@ -146,8 +146,7 @@ var Derived = /** @class */ (function (_super) { //super call with type arguments function Derived() { var _this = _super.call(this) || this; - _this = _super.call(this) || this; - return _this; + return _super.call(this) || this; } return Derived; }(Base)); diff --git a/tests/baselines/reference/nestedSuperCallEmit.js b/tests/baselines/reference/nestedSuperCallEmit.js new file mode 100644 index 0000000000000..705323a4db188 --- /dev/null +++ b/tests/baselines/reference/nestedSuperCallEmit.js @@ -0,0 +1,74 @@ +//// [tests/cases/compiler/nestedSuperCallEmit.ts] //// + +//// [nestedSuperCallEmit.ts] +// https://github.com/microsoft/TypeScript/issues/55646 +abstract class Foo { + constructor(shouldThrow: boolean) { + if (shouldThrow) { + throw new Error('Please retry'); + } else { + console.log('OK'); + } + } +} + +class Bar extends Foo { + constructor() { + try { + super(true); + } catch (e: unknown) { + console.log('Error: ' + (e as Error).message); + // retry + super(false); + } + } +} + +new Bar(); + + +//// [nestedSuperCallEmit.js] +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +// https://github.com/microsoft/TypeScript/issues/55646 +var Foo = /** @class */ (function () { + function Foo(shouldThrow) { + if (shouldThrow) { + throw new Error('Please retry'); + } + else { + console.log('OK'); + } + } + return Foo; +}()); +var Bar = /** @class */ (function (_super) { + __extends(Bar, _super); + function Bar() { + var _this = this; + try { + _this = _super.call(this, true) || this; + } + catch (e) { + console.log('Error: ' + e.message); + // retry + _this = _super.call(this, false) || this; + } + return _this; + } + return Bar; +}(Foo)); +new Bar(); diff --git a/tests/baselines/reference/sourceMapValidationClassWithDefaultConstructorAndExtendsClause.js.map b/tests/baselines/reference/sourceMapValidationClassWithDefaultConstructorAndExtendsClause.js.map index 5d54d7ce50547..978d87c83e953 100644 --- a/tests/baselines/reference/sourceMapValidationClassWithDefaultConstructorAndExtendsClause.js.map +++ b/tests/baselines/reference/sourceMapValidationClassWithDefaultConstructorAndExtendsClause.js.map @@ -1,3 +1,3 @@ //// [sourceMapValidationClassWithDefaultConstructorAndExtendsClause.js.map] -{"version":3,"file":"sourceMapValidationClassWithDefaultConstructorAndExtendsClause.js","sourceRoot":"","sources":["sourceMapValidationClassWithDefaultConstructorAndExtendsClause.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;IAAA;IACA,CAAC;IAAD,sBAAC;AAAD,CAAC,AADD,IACC;AAED;IAAsB,2BAAe;IAArC;QAAA,qEAGC;QAFU,OAAC,GAAG,EAAE,CAAC;QACP,WAAK,GAAG,KAAK,CAAC;;IACzB,CAAC;IAAD,cAAC;AAAD,CAAC,AAHD,CAAsB,eAAe,GAGpC"} -//// https://sokra.github.io/source-map-visualization#base64,dmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkgew0KICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHsNCiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fA0KICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fA0KICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTsNCiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7DQogICAgfTsNCiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHsNCiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSAiZnVuY3Rpb24iICYmIGIgIT09IG51bGwpDQogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDbGFzcyBleHRlbmRzIHZhbHVlICIgKyBTdHJpbmcoYikgKyAiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGwiKTsNCiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTsNCiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9DQogICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTsNCiAgICB9Ow0KfSkoKTsNCnZhciBBYnN0cmFjdEdyZWV0ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7DQogICAgZnVuY3Rpb24gQWJzdHJhY3RHcmVldGVyKCkgew0KICAgIH0NCiAgICByZXR1cm4gQWJzdHJhY3RHcmVldGVyOw0KfSgpKTsNCnZhciBHcmVldGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikgew0KICAgIF9fZXh0ZW5kcyhHcmVldGVyLCBfc3VwZXIpOw0KICAgIGZ1bmN0aW9uIEdyZWV0ZXIoKSB7DQogICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOw0KICAgICAgICBfdGhpcy5hID0gMTA7DQogICAgICAgIF90aGlzLm5hbWVBID0gIlRlbiI7DQogICAgICAgIHJldHVybiBfdGhpczsNCiAgICB9DQogICAgcmV0dXJuIEdyZWV0ZXI7DQp9KEFic3RyYWN0R3JlZXRlcikpOw0KLy8jIHNvdXJjZU1hcHBpbmdVUkw9c291cmNlTWFwVmFsaWRhdGlvbkNsYXNzV2l0aERlZmF1bHRDb25zdHJ1Y3RvckFuZEV4dGVuZHNDbGF1c2UuanMubWFw,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic291cmNlTWFwVmFsaWRhdGlvbkNsYXNzV2l0aERlZmF1bHRDb25zdHJ1Y3RvckFuZEV4dGVuZHNDbGF1c2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzb3VyY2VNYXBWYWxpZGF0aW9uQ2xhc3NXaXRoRGVmYXVsdENvbnN0cnVjdG9yQW5kRXh0ZW5kc0NsYXVzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQTtJQUFBO0lBQ0EsQ0FBQztJQUFELHNCQUFDO0FBQUQsQ0FBQyxBQURELElBQ0M7QUFFRDtJQUFzQiwyQkFBZTtJQUFyQztRQUFBLHFFQUdDO1FBRlUsT0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNQLFdBQUssR0FBRyxLQUFLLENBQUM7O0lBQ3pCLENBQUM7SUFBRCxjQUFDO0FBQUQsQ0FBQyxBQUhELENBQXNCLGVBQWUsR0FHcEMifQ==,Y2xhc3MgQWJzdHJhY3RHcmVldGVyIHsKfQoKY2xhc3MgR3JlZXRlciBleHRlbmRzIEFic3RyYWN0R3JlZXRlciB7CiAgICBwdWJsaWMgYSA9IDEwOwogICAgcHVibGljIG5hbWVBID0gIlRlbiI7Cn0= +{"version":3,"file":"sourceMapValidationClassWithDefaultConstructorAndExtendsClause.js","sourceRoot":"","sources":["sourceMapValidationClassWithDefaultConstructorAndExtendsClause.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;IAAA;IACA,CAAC;IAAD,sBAAC;AAAD,CAAC,AADD,IACC;AAED;IAAsB,2BAAe;IAArC;;QACW,OAAC,GAAG,EAAE,CAAC;QACP,WAAK,GAAG,KAAK,CAAC;;IACzB,CAAC;IAAD,cAAC;AAAD,CAAC,AAHD,CAAsB,eAAe,GAGpC"} +//// https://sokra.github.io/source-map-visualization#base64,dmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkgew0KICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHsNCiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fA0KICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fA0KICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTsNCiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7DQogICAgfTsNCiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHsNCiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSAiZnVuY3Rpb24iICYmIGIgIT09IG51bGwpDQogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJDbGFzcyBleHRlbmRzIHZhbHVlICIgKyBTdHJpbmcoYikgKyAiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGwiKTsNCiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTsNCiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9DQogICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTsNCiAgICB9Ow0KfSkoKTsNCnZhciBBYnN0cmFjdEdyZWV0ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7DQogICAgZnVuY3Rpb24gQWJzdHJhY3RHcmVldGVyKCkgew0KICAgIH0NCiAgICByZXR1cm4gQWJzdHJhY3RHcmVldGVyOw0KfSgpKTsNCnZhciBHcmVldGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikgew0KICAgIF9fZXh0ZW5kcyhHcmVldGVyLCBfc3VwZXIpOw0KICAgIGZ1bmN0aW9uIEdyZWV0ZXIoKSB7DQogICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOw0KICAgICAgICBfdGhpcy5hID0gMTA7DQogICAgICAgIF90aGlzLm5hbWVBID0gIlRlbiI7DQogICAgICAgIHJldHVybiBfdGhpczsNCiAgICB9DQogICAgcmV0dXJuIEdyZWV0ZXI7DQp9KEFic3RyYWN0R3JlZXRlcikpOw0KLy8jIHNvdXJjZU1hcHBpbmdVUkw9c291cmNlTWFwVmFsaWRhdGlvbkNsYXNzV2l0aERlZmF1bHRDb25zdHJ1Y3RvckFuZEV4dGVuZHNDbGF1c2UuanMubWFw,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic291cmNlTWFwVmFsaWRhdGlvbkNsYXNzV2l0aERlZmF1bHRDb25zdHJ1Y3RvckFuZEV4dGVuZHNDbGF1c2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzb3VyY2VNYXBWYWxpZGF0aW9uQ2xhc3NXaXRoRGVmYXVsdENvbnN0cnVjdG9yQW5kRXh0ZW5kc0NsYXVzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQTtJQUFBO0lBQ0EsQ0FBQztJQUFELHNCQUFDO0FBQUQsQ0FBQyxBQURELElBQ0M7QUFFRDtJQUFzQiwyQkFBZTtJQUFyQzs7UUFDVyxPQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ1AsV0FBSyxHQUFHLEtBQUssQ0FBQzs7SUFDekIsQ0FBQztJQUFELGNBQUM7QUFBRCxDQUFDLEFBSEQsQ0FBc0IsZUFBZSxHQUdwQyJ9,Y2xhc3MgQWJzdHJhY3RHcmVldGVyIHsKfQoKY2xhc3MgR3JlZXRlciBleHRlbmRzIEFic3RyYWN0R3JlZXRlciB7CiAgICBwdWJsaWMgYSA9IDEwOwogICAgcHVibGljIG5hbWVBID0gIlRlbiI7Cn0= diff --git a/tests/baselines/reference/sourceMapValidationClassWithDefaultConstructorAndExtendsClause.sourcemap.txt b/tests/baselines/reference/sourceMapValidationClassWithDefaultConstructorAndExtendsClause.sourcemap.txt index cb8de191c8fba..63e48feb6dabd 100644 --- a/tests/baselines/reference/sourceMapValidationClassWithDefaultConstructorAndExtendsClause.sourcemap.txt +++ b/tests/baselines/reference/sourceMapValidationClassWithDefaultConstructorAndExtendsClause.sourcemap.txt @@ -92,29 +92,20 @@ sourceFile:sourceMapValidationClassWithDefaultConstructorAndExtendsClause.ts 1 >Emitted(23, 5) Source(4, 1) + SourceIndex(0) --- >>> var _this = _super !== null && _super.apply(this, arguments) || this; -1->^^^^^^^^ -2 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -1-> -2 > class Greeter extends AbstractGreeter { - > public a = 10; - > public nameA = "Ten"; - > } -1->Emitted(24, 9) Source(4, 1) + SourceIndex(0) -2 >Emitted(24, 78) Source(7, 2) + SourceIndex(0) ---- >>> _this.a = 10; -1 >^^^^^^^^ +1->^^^^^^^^ 2 > ^^^^^^^ 3 > ^^^ 4 > ^^ 5 > ^ 6 > ^^^^^^^^-> -1 > +1->class Greeter extends AbstractGreeter { + > public 2 > a 3 > = 4 > 10 5 > ; -1 >Emitted(25, 9) Source(5, 12) + SourceIndex(0) +1->Emitted(25, 9) Source(5, 12) + SourceIndex(0) 2 >Emitted(25, 16) Source(5, 13) + SourceIndex(0) 3 >Emitted(25, 19) Source(5, 16) + SourceIndex(0) 4 >Emitted(25, 21) Source(5, 18) + SourceIndex(0) diff --git a/tests/baselines/reference/strictModeInConstructor.js b/tests/baselines/reference/strictModeInConstructor.js index c0cf843fcec07..3009bd8e0183e 100644 --- a/tests/baselines/reference/strictModeInConstructor.js +++ b/tests/baselines/reference/strictModeInConstructor.js @@ -97,7 +97,7 @@ var B = /** @class */ (function (_super) { var C = /** @class */ (function (_super) { __extends(C, _super); function C() { - var _this = _super.call(this) || this; + var _this = _super.call(this) || this; // No error _this.s = 9; "use strict"; return _this; @@ -129,7 +129,7 @@ var Bs = /** @class */ (function (_super) { var Cs = /** @class */ (function (_super) { __extends(Cs, _super); function Cs() { - var _this = _super.call(this) || this; + var _this = _super.call(this) || this; // No error "use strict"; return _this; } diff --git a/tests/baselines/reference/superCallArgsMustMatch.js b/tests/baselines/reference/superCallArgsMustMatch.js index fb131390c7786..ef0926b4aed6e 100644 --- a/tests/baselines/reference/superCallArgsMustMatch.js +++ b/tests/baselines/reference/superCallArgsMustMatch.js @@ -52,10 +52,9 @@ var T5 = /** @class */ (function () { var T6 = /** @class */ (function (_super) { __extends(T6, _super); function T6() { - var _this = // Should error; base constructor has type T for first arg, // which is instantiated with 'number' in the extends clause - _super.call(this, "hi") || this; + var _this = _super.call(this, "hi") || this; var x = _this.foo; return _this; } diff --git a/tests/baselines/reference/superCallBeforeThisAccessing2.js b/tests/baselines/reference/superCallBeforeThisAccessing2.js index d98cc8c493ed2..fda977387edf3 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing2.js +++ b/tests/baselines/reference/superCallBeforeThisAccessing2.js @@ -36,7 +36,7 @@ var Base = /** @class */ (function () { var D = /** @class */ (function (_super) { __extends(D, _super); function D() { - var _this = _super.call(this, function () { _this._t; }) || this; + var _this = _super.call(this, function () { _this._t; }) || this; // no error. only check when this is directly accessing in constructor return _this; } return D; diff --git a/tests/baselines/reference/superCallBeforeThisAccessing3.js b/tests/baselines/reference/superCallBeforeThisAccessing3.js index 26f94d674d153..ea89301abe063 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing3.js +++ b/tests/baselines/reference/superCallBeforeThisAccessing3.js @@ -43,8 +43,7 @@ var D = /** @class */ (function (_super) { var x = function () { _this._t; }; x(); // no error; we only check super is called before this when the container is a constructor _this._t; // error - _this = _super.call(this, undefined) || this; - return _this; + return _this = _super.call(this, undefined) || this; } return D; }(Base)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing4.js b/tests/baselines/reference/superCallBeforeThisAccessing4.js index 118b1918eded7..74d9c4cced109 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing4.js +++ b/tests/baselines/reference/superCallBeforeThisAccessing4.js @@ -38,8 +38,7 @@ var D = /** @class */ (function (_super) { function D() { var _this = this; _this._t; - _this = _super.call(this) || this; - return _this; + return _this = _super.call(this) || this; } return D; }(null)); diff --git a/tests/baselines/reference/superCallBeforeThisAccessing7.js b/tests/baselines/reference/superCallBeforeThisAccessing7.js index 61e57f4ec495c..b0e64b0972988 100644 --- a/tests/baselines/reference/superCallBeforeThisAccessing7.js +++ b/tests/baselines/reference/superCallBeforeThisAccessing7.js @@ -43,8 +43,7 @@ var D = /** @class */ (function (_super) { var x = { j: _this._t, }; - _this = _super.call(this, undefined) || this; - return _this; + return _this = _super.call(this, undefined) || this; } return D; }(Base)); diff --git a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js index 63e50ca343a11..99a5146cd81f1 100644 --- a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js +++ b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js @@ -13,7 +13,7 @@ class Foo { //// [superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js] var Foo = /** @class */ (function () { function Foo() { - return _super.call(this) || this; + return _super.call(this) || this; // error } return Foo; }()); diff --git a/tests/baselines/reference/superCallInConstructorWithNoBaseType.js b/tests/baselines/reference/superCallInConstructorWithNoBaseType.js index 3e97ae986f6a3..af6d986156ce3 100644 --- a/tests/baselines/reference/superCallInConstructorWithNoBaseType.js +++ b/tests/baselines/reference/superCallInConstructorWithNoBaseType.js @@ -16,13 +16,13 @@ class D { //// [superCallInConstructorWithNoBaseType.js] var C = /** @class */ (function () { function C() { - return _super.call(this) || this; + return _super.call(this) || this; // error } return C; }()); var D = /** @class */ (function () { function D(x) { - var _this = _super.call(this) || this; + var _this = _super.call(this) || this; // error this.x = x; return _this; } diff --git a/tests/baselines/reference/superCallParameterContextualTyping3.js b/tests/baselines/reference/superCallParameterContextualTyping3.js index 68789b0312157..66bf7c33d3a4a 100644 --- a/tests/baselines/reference/superCallParameterContextualTyping3.js +++ b/tests/baselines/reference/superCallParameterContextualTyping3.js @@ -59,10 +59,9 @@ var CBase = /** @class */ (function () { var C = /** @class */ (function (_super) { __extends(C, _super); function C() { - var _this = // Should be okay. // 'p' should have type 'string'. - _super.call(this, { + var _this = _super.call(this, { method: function (p) { p.length; } diff --git a/tests/baselines/reference/superWithGenericSpecialization.js b/tests/baselines/reference/superWithGenericSpecialization.js index 738cebaaafb1f..ab58f494333c4 100644 --- a/tests/baselines/reference/superWithGenericSpecialization.js +++ b/tests/baselines/reference/superWithGenericSpecialization.js @@ -40,7 +40,7 @@ var C = /** @class */ (function () { var D = /** @class */ (function (_super) { __extends(D, _super); function D() { - return _super.call(this) || this; + return _super.call(this) || this; // uses the type parameter type of the base class, ie string } return D; }(C)); diff --git a/tests/baselines/reference/thisInConstructorParameter2.js b/tests/baselines/reference/thisInConstructorParameter2.js index 61abc7e52d4b9..b8540253c4d96 100644 --- a/tests/baselines/reference/thisInConstructorParameter2.js +++ b/tests/baselines/reference/thisInConstructorParameter2.js @@ -16,13 +16,13 @@ class P { //// [thisInConstructorParameter2.js] var P = /** @class */ (function () { function P(z, zz, zzz) { - var _this = this; if (z === void 0) { z = this; } if (zz === void 0) { zz = this; } if (zzz === void 0) { zzz = function (p) { if (p === void 0) { p = _this; } return _this; }; } + var _this = this; this.z = z; this.x = this; zzz = function (p) { diff --git a/tests/baselines/reference/thisInInvalidContexts.js b/tests/baselines/reference/thisInInvalidContexts.js index b28940e8725fe..0a00c94b7f3d3 100644 --- a/tests/baselines/reference/thisInInvalidContexts.js +++ b/tests/baselines/reference/thisInInvalidContexts.js @@ -70,7 +70,7 @@ var ClassWithNoInitializer = /** @class */ (function (_super) { __extends(ClassWithNoInitializer, _super); //'this' in optional super call function ClassWithNoInitializer() { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // Error return _this; } return ClassWithNoInitializer; @@ -79,7 +79,7 @@ var ClassWithInitializer = /** @class */ (function (_super) { __extends(ClassWithInitializer, _super); //'this' in required super call function ClassWithInitializer() { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // Error _this.t = 4; return _this; } diff --git a/tests/baselines/reference/thisInInvalidContextsExternalModule.js b/tests/baselines/reference/thisInInvalidContextsExternalModule.js index 4e21cfcda6c31..e57ab3102fba8 100644 --- a/tests/baselines/reference/thisInInvalidContextsExternalModule.js +++ b/tests/baselines/reference/thisInInvalidContextsExternalModule.js @@ -71,7 +71,7 @@ var ClassWithNoInitializer = /** @class */ (function (_super) { __extends(ClassWithNoInitializer, _super); //'this' in optional super call function ClassWithNoInitializer() { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // error: "super" has to be called before "this" accessing return _this; } return ClassWithNoInitializer; @@ -80,7 +80,7 @@ var ClassWithInitializer = /** @class */ (function (_super) { __extends(ClassWithInitializer, _super); //'this' in required super call function ClassWithInitializer() { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // Error _this.t = 4; return _this; } diff --git a/tests/baselines/reference/thisInSuperCall.js b/tests/baselines/reference/thisInSuperCall.js index 0e6656ce47826..db50c0c89b663 100644 --- a/tests/baselines/reference/thisInSuperCall.js +++ b/tests/baselines/reference/thisInSuperCall.js @@ -48,7 +48,7 @@ var Base = /** @class */ (function () { var Foo = /** @class */ (function (_super) { __extends(Foo, _super); function Foo() { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // error: "super" has to be called before "this" accessing return _this; } return Foo; @@ -56,7 +56,7 @@ var Foo = /** @class */ (function (_super) { var Foo2 = /** @class */ (function (_super) { __extends(Foo2, _super); function Foo2() { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // error _this.p = 0; return _this; } @@ -65,7 +65,7 @@ var Foo2 = /** @class */ (function (_super) { var Foo3 = /** @class */ (function (_super) { __extends(Foo3, _super); function Foo3(p) { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // error _this.p = p; return _this; } diff --git a/tests/baselines/reference/thisInSuperCall2.js b/tests/baselines/reference/thisInSuperCall2.js index 364634df4661e..decc6c4eb47a0 100644 --- a/tests/baselines/reference/thisInSuperCall2.js +++ b/tests/baselines/reference/thisInSuperCall2.js @@ -45,7 +45,7 @@ var Base = /** @class */ (function () { var Foo = /** @class */ (function (_super) { __extends(Foo, _super); function Foo() { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // error: "super" has to be called before "this" accessing return _this; } return Foo; @@ -53,7 +53,7 @@ var Foo = /** @class */ (function (_super) { var Foo2 = /** @class */ (function (_super) { __extends(Foo2, _super); function Foo2() { - var _this = _super.call(this, _this) || this; + var _this = _super.call(this, _this) || this; // error _this.x = 0; return _this; } diff --git a/tests/baselines/reference/usingDeclarations.1(target=es5).js b/tests/baselines/reference/usingDeclarations.1(target=es5).js index cbdb2e2317594..db78f5002a0de 100644 --- a/tests/baselines/reference/usingDeclarations.1(target=es5).js +++ b/tests/baselines/reference/usingDeclarations.1(target=es5).js @@ -572,10 +572,11 @@ try { __extends(C2, _super); function C2() { var _a; + var _this = this; var env_29 = { stack: [], error: void 0, hasError: false }; try { var d16 = __addDisposableResource(env_29, (_a = {}, _a[Symbol.dispose] = function () { }, _a), false); - return _super.call(this) || this; + _this = _super.call(this) || this; } catch (e_29) { env_29.error = e_29; @@ -584,6 +585,7 @@ try { finally { __disposeResources(env_29); } + return _this; } return C2; }(C1)); @@ -591,10 +593,11 @@ try { __extends(C3, _super); function C3() { var _a; + var _this = this; var env_30 = { stack: [], error: void 0, hasError: false }; try { - var _this = _super.call(this) || this; var d17 = __addDisposableResource(env_30, (_a = {}, _a[Symbol.dispose] = function () { }, _a), false); + _this = _super.call(this) || this; _this.y = 1; } catch (e_30) { diff --git a/tests/baselines/reference/usingDeclarations.11.js b/tests/baselines/reference/usingDeclarations.11.js index 449debe53d982..2451a196bd238 100644 --- a/tests/baselines/reference/usingDeclarations.11.js +++ b/tests/baselines/reference/usingDeclarations.11.js @@ -105,10 +105,11 @@ var A = /** @class */ (function () { var C1 = /** @class */ (function (_super) { __extends(C1, _super); function C1() { + var _this = this; var env_1 = { stack: [], error: void 0, hasError: false }; try { var x = __addDisposableResource(env_1, null, false); - return _super.call(this) || this; + _this = _super.call(this) || this; } catch (e_1) { env_1.error = e_1; @@ -117,15 +118,17 @@ var C1 = /** @class */ (function (_super) { finally { __disposeResources(env_1); } + return _this; } return C1; }(A)); var C2 = /** @class */ (function (_super) { __extends(C2, _super); function C2() { + var _this = this; var env_2 = { stack: [], error: void 0, hasError: false }; try { - var _this = _super.call(this) || this; + _this = _super.call(this) || this; var x = __addDisposableResource(env_2, null, false); } catch (e_2) { @@ -142,10 +145,11 @@ var C2 = /** @class */ (function (_super) { var C3 = /** @class */ (function (_super) { __extends(C3, _super); function C3() { + var _this = this; var env_3 = { stack: [], error: void 0, hasError: false }; try { - var _this = _super.call(this) || this; var x = __addDisposableResource(env_3, null, false); + _this = _super.call(this) || this; _this.y = 1; } catch (e_3) { @@ -162,10 +166,11 @@ var C3 = /** @class */ (function (_super) { var C4 = /** @class */ (function (_super) { __extends(C4, _super); function C4(y) { + var _this = this; var env_4 = { stack: [], error: void 0, hasError: false }; try { - var _this = _super.call(this) || this; var x = __addDisposableResource(env_4, null, false); + _this = _super.call(this) || this; _this.y = y; } catch (e_4) { @@ -182,10 +187,11 @@ var C4 = /** @class */ (function (_super) { var C5 = /** @class */ (function (_super) { __extends(C5, _super); function C5(y) { + var _this = this; var env_5 = { stack: [], error: void 0, hasError: false }; try { - var _this = _super.call(this) || this; var x = __addDisposableResource(env_5, null, false); + _this = _super.call(this) || this; _this.y = y; _this.z = 1; } diff --git a/tests/baselines/reference/validUseOfThisInSuper.js b/tests/baselines/reference/validUseOfThisInSuper.js index 3dd6398f27ad1..b6b559993d3af 100644 --- a/tests/baselines/reference/validUseOfThisInSuper.js +++ b/tests/baselines/reference/validUseOfThisInSuper.js @@ -36,7 +36,7 @@ var Base = /** @class */ (function () { var Super = /** @class */ (function (_super) { __extends(Super, _super); function Super() { - var _this = _super.call(this, (function () { return _this; })()) || this; + var _this = _super.call(this, (function () { return _this; })()) || this; // ok since this is not the case: The constructor declares parameter properties or the containing class declares instance member variables with initializers. return _this; } return Super; diff --git a/tests/cases/compiler/nestedSuperCallEmit.ts b/tests/cases/compiler/nestedSuperCallEmit.ts new file mode 100644 index 0000000000000..1c622f40dd016 --- /dev/null +++ b/tests/cases/compiler/nestedSuperCallEmit.ts @@ -0,0 +1,27 @@ +// @target: es5 +// @noTypesAndSymbols: true + +// https://github.com/microsoft/TypeScript/issues/55646 +abstract class Foo { + constructor(shouldThrow: boolean) { + if (shouldThrow) { + throw new Error('Please retry'); + } else { + console.log('OK'); + } + } +} + +class Bar extends Foo { + constructor() { + try { + super(true); + } catch (e: unknown) { + console.log('Error: ' + (e as Error).message); + // retry + super(false); + } + } +} + +new Bar();