From 7059008bbab207daecb9154b75ac334fd49fb850 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Thu, 5 Dec 2019 11:19:23 +0900 Subject: [PATCH 1/2] Add es2020 transformation --- src/compiler/binder.ts | 8 +- src/compiler/transformer.ts | 4 + src/compiler/transformers/es2020.ts | 207 ++++++++++++++++++ src/compiler/transformers/esnext.ts | 183 ---------------- src/compiler/tsconfig.json | 1 + src/compiler/types.ts | 38 ++-- .../callChainWithSuper(target=es2020).js | 4 +- ...js => nullishCoalescingOperator_es2020.js} | 7 +- .../nullishCoalescingOperator_es2020.symbols | 143 ++++++++++++ ...=> nullishCoalescingOperator_es2020.types} | 2 +- .../nullishCoalescingOperator_esnext.symbols | 143 ------------ ...ts => nullishCoalescingOperator_es2020.ts} | 4 +- 12 files changed, 388 insertions(+), 356 deletions(-) create mode 100644 src/compiler/transformers/es2020.ts rename tests/baselines/reference/{nullishCoalescingOperator_esnext.js => nullishCoalescingOperator_es2020.js} (93%) create mode 100644 tests/baselines/reference/nullishCoalescingOperator_es2020.symbols rename tests/baselines/reference/{nullishCoalescingOperator_esnext.types => nullishCoalescingOperator_es2020.types} (93%) delete mode 100644 tests/baselines/reference/nullishCoalescingOperator_esnext.symbols rename tests/cases/conformance/expressions/nullishCoalescingOperator/{nullishCoalescingOperator_esnext.ts => nullishCoalescingOperator_es2020.ts} (95%) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 0b19d7806ff07..2de2728744888 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3361,7 +3361,7 @@ namespace ts { const expression = node.expression; if (node.flags & NodeFlags.OptionalChain) { - transformFlags |= TransformFlags.ContainsESNext; + transformFlags |= TransformFlags.ContainsES2020; } if (node.typeArguments) { @@ -3405,7 +3405,7 @@ namespace ts { const leftKind = node.left.kind; if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) { - transformFlags |= TransformFlags.AssertESNext; + transformFlags |= TransformFlags.AssertES2020; } else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) { // Destructuring object assignments with are ES2015 syntax @@ -3764,7 +3764,7 @@ namespace ts { let transformFlags = subtreeFlags; if (node.flags & NodeFlags.OptionalChain) { - transformFlags |= TransformFlags.ContainsESNext; + transformFlags |= TransformFlags.ContainsES2020; } // If a PropertyAccessExpression starts with a super keyword, then it is @@ -3783,7 +3783,7 @@ namespace ts { let transformFlags = subtreeFlags; if (node.flags & NodeFlags.OptionalChain) { - transformFlags |= TransformFlags.ContainsESNext; + transformFlags |= TransformFlags.ContainsES2020; } // If an ElementAccessExpression starts with a super keyword, then it is diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index f6923e88f1582..4f308b57912f6 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -55,6 +55,10 @@ namespace ts { transformers.push(transformESNext); } + if (languageVersion < ScriptTarget.ES2020) { + transformers.push(transformES2020); + } + if (languageVersion < ScriptTarget.ES2019) { transformers.push(transformES2019); } diff --git a/src/compiler/transformers/es2020.ts b/src/compiler/transformers/es2020.ts new file mode 100644 index 0000000000000..bc5ea6771e6cb --- /dev/null +++ b/src/compiler/transformers/es2020.ts @@ -0,0 +1,207 @@ +/*@internal*/ +namespace ts { + export function transformES2020(context: TransformationContext) { + const { + hoistVariableDeclaration, + } = context; + + return chainBundle(transformSourceFile); + + function transformSourceFile(node: SourceFile) { + if (node.isDeclarationFile) { + return node; + } + + return visitEachChild(node, visitor, context); + } + + function visitor(node: Node): VisitResult { + if ((node.transformFlags & TransformFlags.ContainsES2020) === 0) { + return node; + } + switch (node.kind) { + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.CallExpression: + if (node.flags & NodeFlags.OptionalChain) { + const updated = visitOptionalExpression(node as OptionalChain, /*captureThisArg*/ false, /*isDelete*/ false); + Debug.assertNotNode(updated, isSyntheticReference); + return updated; + } + return visitEachChild(node, visitor, context); + case SyntaxKind.BinaryExpression: + if ((node).operatorToken.kind === SyntaxKind.QuestionQuestionToken) { + return transformNullishCoalescingExpression(node); + } + return visitEachChild(node, visitor, context); + case SyntaxKind.DeleteExpression: + return visitDeleteExpression(node as DeleteExpression); + default: + return visitEachChild(node, visitor, context); + } + } + + function flattenChain(chain: OptionalChain) { + const links: OptionalChain[] = [chain]; + while (!chain.questionDotToken && !isTaggedTemplateExpression(chain)) { + chain = cast(chain.expression, isOptionalChain); + links.unshift(chain); + } + return { expression: chain.expression, chain: links }; + } + + function visitNonOptionalParenthesizedExpression(node: ParenthesizedExpression, captureThisArg: boolean, isDelete: boolean): Expression { + const expression = visitNonOptionalExpression(node.expression, captureThisArg, isDelete); + if (isSyntheticReference(expression)) { + // `(a.b)` -> { expression `((_a = a).b)`, thisArg: `_a` } + // `(a[b])` -> { expression `((_a = a)[b])`, thisArg: `_a` } + return createSyntheticReferenceExpression(updateParen(node, expression.expression), expression.thisArg); + } + return updateParen(node, expression); + } + + function visitNonOptionalPropertyOrElementAccessExpression(node: AccessExpression, captureThisArg: boolean, isDelete: boolean): Expression { + if (isOptionalChain(node)) { + // If `node` is an optional chain, then it is the outermost chain of an optional expression. + return visitOptionalExpression(node, captureThisArg, isDelete); + } + + let expression: Expression = visitNode(node.expression, visitor, isExpression); + Debug.assertNotNode(expression, isSyntheticReference); + + let thisArg: Expression | undefined; + if (captureThisArg) { + if (shouldCaptureInTempVariable(expression)) { + thisArg = createTempVariable(hoistVariableDeclaration); + expression = createAssignment(thisArg, expression); + } + else { + thisArg = expression; + } + } + + expression = node.kind === SyntaxKind.PropertyAccessExpression + ? updatePropertyAccess(node, expression, visitNode(node.name, visitor, isIdentifier)) + : updateElementAccess(node, expression, visitNode(node.argumentExpression, visitor, isExpression)); + return thisArg ? createSyntheticReferenceExpression(expression, thisArg) : expression; + } + + function visitNonOptionalCallExpression(node: CallExpression, captureThisArg: boolean): Expression { + if (isOptionalChain(node)) { + // If `node` is an optional chain, then it is the outermost chain of an optional expression. + return visitOptionalExpression(node, captureThisArg, /*isDelete*/ false); + } + return visitEachChild(node, visitor, context); + } + + function visitNonOptionalExpression(node: Expression, captureThisArg: boolean, isDelete: boolean): Expression { + switch (node.kind) { + case SyntaxKind.ParenthesizedExpression: return visitNonOptionalParenthesizedExpression(node as ParenthesizedExpression, captureThisArg, isDelete); + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: return visitNonOptionalPropertyOrElementAccessExpression(node as AccessExpression, captureThisArg, isDelete); + case SyntaxKind.CallExpression: return visitNonOptionalCallExpression(node as CallExpression, captureThisArg); + default: return visitNode(node, visitor, isExpression); + } + } + + function visitOptionalExpression(node: OptionalChain, captureThisArg: boolean, isDelete: boolean): Expression { + const { expression, chain } = flattenChain(node); + const left = visitNonOptionalExpression(expression, isCallChain(chain[0]), /*isDelete*/ false); + const leftThisArg = isSyntheticReference(left) ? left.thisArg : undefined; + let leftExpression = isSyntheticReference(left) ? left.expression : left; + let capturedLeft: Expression = leftExpression; + if (shouldCaptureInTempVariable(leftExpression)) { + capturedLeft = createTempVariable(hoistVariableDeclaration); + leftExpression = createAssignment(capturedLeft, leftExpression); + } + let rightExpression = capturedLeft; + let thisArg: Expression | undefined; + for (let i = 0; i < chain.length; i++) { + const segment = chain[i]; + switch (segment.kind) { + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + if (i === chain.length - 1 && captureThisArg) { + if (shouldCaptureInTempVariable(rightExpression)) { + thisArg = createTempVariable(hoistVariableDeclaration); + rightExpression = createAssignment(thisArg, rightExpression); + } + else { + thisArg = rightExpression; + } + } + rightExpression = segment.kind === SyntaxKind.PropertyAccessExpression + ? createPropertyAccess(rightExpression, visitNode(segment.name, visitor, isIdentifier)) + : createElementAccess(rightExpression, visitNode(segment.argumentExpression, visitor, isExpression)); + break; + case SyntaxKind.CallExpression: + if (i === 0 && leftThisArg) { + rightExpression = createFunctionCall( + rightExpression, + leftThisArg.kind === SyntaxKind.SuperKeyword ? createThis() : leftThisArg, + visitNodes(segment.arguments, visitor, isExpression) + ); + } + else { + rightExpression = createCall( + rightExpression, + /*typeArguments*/ undefined, + visitNodes(segment.arguments, visitor, isExpression) + ); + } + break; + } + setOriginalNode(rightExpression, segment); + } + + const target = isDelete + ? createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createTrue(), createDelete(rightExpression)) + : createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createVoidZero(), rightExpression); + return thisArg ? createSyntheticReferenceExpression(target, thisArg) : target; + } + + function createNotNullCondition(left: Expression, right: Expression, invert?: boolean) { + return createBinary( + createBinary( + left, + createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), + createNull() + ), + createToken(invert ? SyntaxKind.BarBarToken : SyntaxKind.AmpersandAmpersandToken), + createBinary( + right, + createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), + createVoidZero() + ) + ); + } + + function transformNullishCoalescingExpression(node: BinaryExpression) { + let left = visitNode(node.left, visitor, isExpression); + let right = left; + if (shouldCaptureInTempVariable(left)) { + right = createTempVariable(hoistVariableDeclaration); + left = createAssignment(right, left); + } + return createConditional( + createNotNullCondition(left, right), + right, + visitNode(node.right, visitor, isExpression), + ); + } + + function shouldCaptureInTempVariable(expression: Expression): boolean { + // don't capture identifiers and `this` in a temporary variable + // `super` cannot be captured as it's no real variable + return !isIdentifier(expression) && + expression.kind !== SyntaxKind.ThisKeyword && + expression.kind !== SyntaxKind.SuperKeyword; + } + + function visitDeleteExpression(node: DeleteExpression) { + return isOptionalChain(skipParentheses(node.expression)) + ? setOriginalNode(visitNonOptionalExpression(node.expression, /*captureThisArg*/ false, /*isDelete*/ true), node) + : updateDelete(node, visitNode(node.expression, visitor, isExpression)); + } + } +} diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 2300feeb0e20d..80debb46f8a04 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -1,10 +1,6 @@ /*@internal*/ namespace ts { export function transformESNext(context: TransformationContext) { - const { - hoistVariableDeclaration, - } = context; - return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { @@ -20,188 +16,9 @@ namespace ts { return node; } switch (node.kind) { - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.CallExpression: - if (node.flags & NodeFlags.OptionalChain) { - const updated = visitOptionalExpression(node as OptionalChain, /*captureThisArg*/ false, /*isDelete*/ false); - Debug.assertNotNode(updated, isSyntheticReference); - return updated; - } - return visitEachChild(node, visitor, context); - case SyntaxKind.BinaryExpression: - if ((node).operatorToken.kind === SyntaxKind.QuestionQuestionToken) { - return transformNullishCoalescingExpression(node); - } - return visitEachChild(node, visitor, context); - case SyntaxKind.DeleteExpression: - return visitDeleteExpression(node as DeleteExpression); default: return visitEachChild(node, visitor, context); } } - - function flattenChain(chain: OptionalChain) { - const links: OptionalChain[] = [chain]; - while (!chain.questionDotToken && !isTaggedTemplateExpression(chain)) { - chain = cast(chain.expression, isOptionalChain); - links.unshift(chain); - } - return { expression: chain.expression, chain: links }; - } - - function visitNonOptionalParenthesizedExpression(node: ParenthesizedExpression, captureThisArg: boolean, isDelete: boolean): Expression { - const expression = visitNonOptionalExpression(node.expression, captureThisArg, isDelete); - if (isSyntheticReference(expression)) { - // `(a.b)` -> { expression `((_a = a).b)`, thisArg: `_a` } - // `(a[b])` -> { expression `((_a = a)[b])`, thisArg: `_a` } - return createSyntheticReferenceExpression(updateParen(node, expression.expression), expression.thisArg); - } - return updateParen(node, expression); - } - - function visitNonOptionalPropertyOrElementAccessExpression(node: AccessExpression, captureThisArg: boolean, isDelete: boolean): Expression { - if (isOptionalChain(node)) { - // If `node` is an optional chain, then it is the outermost chain of an optional expression. - return visitOptionalExpression(node, captureThisArg, isDelete); - } - - let expression: Expression = visitNode(node.expression, visitor, isExpression); - Debug.assertNotNode(expression, isSyntheticReference); - - let thisArg: Expression | undefined; - if (captureThisArg) { - if (shouldCaptureInTempVariable(expression)) { - thisArg = createTempVariable(hoistVariableDeclaration); - expression = createAssignment(thisArg, expression); - } - else { - thisArg = expression; - } - } - - expression = node.kind === SyntaxKind.PropertyAccessExpression - ? updatePropertyAccess(node, expression, visitNode(node.name, visitor, isIdentifier)) - : updateElementAccess(node, expression, visitNode(node.argumentExpression, visitor, isExpression)); - return thisArg ? createSyntheticReferenceExpression(expression, thisArg) : expression; - } - - function visitNonOptionalCallExpression(node: CallExpression, captureThisArg: boolean): Expression { - if (isOptionalChain(node)) { - // If `node` is an optional chain, then it is the outermost chain of an optional expression. - return visitOptionalExpression(node, captureThisArg, /*isDelete*/ false); - } - return visitEachChild(node, visitor, context); - } - - function visitNonOptionalExpression(node: Expression, captureThisArg: boolean, isDelete: boolean): Expression { - switch (node.kind) { - case SyntaxKind.ParenthesizedExpression: return visitNonOptionalParenthesizedExpression(node as ParenthesizedExpression, captureThisArg, isDelete); - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: return visitNonOptionalPropertyOrElementAccessExpression(node as AccessExpression, captureThisArg, isDelete); - case SyntaxKind.CallExpression: return visitNonOptionalCallExpression(node as CallExpression, captureThisArg); - default: return visitNode(node, visitor, isExpression); - } - } - - function visitOptionalExpression(node: OptionalChain, captureThisArg: boolean, isDelete: boolean): Expression { - const { expression, chain } = flattenChain(node); - const left = visitNonOptionalExpression(expression, isCallChain(chain[0]), /*isDelete*/ false); - const leftThisArg = isSyntheticReference(left) ? left.thisArg : undefined; - let leftExpression = isSyntheticReference(left) ? left.expression : left; - let capturedLeft: Expression = leftExpression; - if (shouldCaptureInTempVariable(leftExpression)) { - capturedLeft = createTempVariable(hoistVariableDeclaration); - leftExpression = createAssignment(capturedLeft, leftExpression); - } - let rightExpression = capturedLeft; - let thisArg: Expression | undefined; - for (let i = 0; i < chain.length; i++) { - const segment = chain[i]; - switch (segment.kind) { - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - if (i === chain.length - 1 && captureThisArg) { - if (shouldCaptureInTempVariable(rightExpression)) { - thisArg = createTempVariable(hoistVariableDeclaration); - rightExpression = createAssignment(thisArg, rightExpression); - } - else { - thisArg = rightExpression; - } - } - rightExpression = segment.kind === SyntaxKind.PropertyAccessExpression - ? createPropertyAccess(rightExpression, visitNode(segment.name, visitor, isIdentifier)) - : createElementAccess(rightExpression, visitNode(segment.argumentExpression, visitor, isExpression)); - break; - case SyntaxKind.CallExpression: - if (i === 0 && leftThisArg) { - rightExpression = createFunctionCall( - rightExpression, - leftThisArg.kind === SyntaxKind.SuperKeyword ? createThis() : leftThisArg, - visitNodes(segment.arguments, visitor, isExpression) - ); - } - else { - rightExpression = createCall( - rightExpression, - /*typeArguments*/ undefined, - visitNodes(segment.arguments, visitor, isExpression) - ); - } - break; - } - setOriginalNode(rightExpression, segment); - } - - const target = isDelete - ? createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createTrue(), createDelete(rightExpression)) - : createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createVoidZero(), rightExpression); - return thisArg ? createSyntheticReferenceExpression(target, thisArg) : target; - } - - function createNotNullCondition(left: Expression, right: Expression, invert?: boolean) { - return createBinary( - createBinary( - left, - createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), - createNull() - ), - createToken(invert ? SyntaxKind.BarBarToken : SyntaxKind.AmpersandAmpersandToken), - createBinary( - right, - createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken), - createVoidZero() - ) - ); - } - - function transformNullishCoalescingExpression(node: BinaryExpression) { - let left = visitNode(node.left, visitor, isExpression); - let right = left; - if (shouldCaptureInTempVariable(left)) { - right = createTempVariable(hoistVariableDeclaration); - left = createAssignment(right, left); - } - return createConditional( - createNotNullCondition(left, right), - right, - visitNode(node.right, visitor, isExpression), - ); - } - - function shouldCaptureInTempVariable(expression: Expression): boolean { - // don't capture identifiers and `this` in a temporary variable - // `super` cannot be captured as it's no real variable - return !isIdentifier(expression) && - expression.kind !== SyntaxKind.ThisKeyword && - expression.kind !== SyntaxKind.SuperKeyword; - } - - function visitDeleteExpression(node: DeleteExpression) { - return isOptionalChain(skipParentheses(node.expression)) - ? setOriginalNode(visitNonOptionalExpression(node.expression, /*captureThisArg*/ false, /*isDelete*/ true), node) - : updateDelete(node, visitNode(node.expression, visitor, isExpression)); - } } } diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 41048b59fdb22..945104db5f003 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -43,6 +43,7 @@ "transformers/es2017.ts", "transformers/es2018.ts", "transformers/es2019.ts", + "transformers/es2020.ts", "transformers/esnext.ts", "transformers/jsx.ts", "transformers/es2016.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5ef9e86b2544f..a8ce5092f8676 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5590,27 +5590,28 @@ namespace ts { ContainsTypeScript = 1 << 0, ContainsJsx = 1 << 1, ContainsESNext = 1 << 2, - ContainsES2019 = 1 << 3, - ContainsES2018 = 1 << 4, - ContainsES2017 = 1 << 5, - ContainsES2016 = 1 << 6, - ContainsES2015 = 1 << 7, - ContainsGenerator = 1 << 8, - ContainsDestructuringAssignment = 1 << 9, + ContainsES2020 = 1 << 3, + ContainsES2019 = 1 << 4, + ContainsES2018 = 1 << 5, + ContainsES2017 = 1 << 6, + ContainsES2016 = 1 << 7, + ContainsES2015 = 1 << 8, + ContainsGenerator = 1 << 9, + ContainsDestructuringAssignment = 1 << 10, // Markers // - Flags used to indicate that a subtree contains a specific transformation. - ContainsTypeScriptClassSyntax = 1 << 10, // Decorators, Property Initializers, Parameter Property Initializers - ContainsLexicalThis = 1 << 11, - ContainsRestOrSpread = 1 << 12, - ContainsObjectRestOrSpread = 1 << 13, - ContainsComputedPropertyName = 1 << 14, - ContainsBlockScopedBinding = 1 << 15, - ContainsBindingPattern = 1 << 16, - ContainsYield = 1 << 17, - ContainsHoistedDeclarationOrCompletion = 1 << 18, - ContainsDynamicImport = 1 << 19, - ContainsClassFields = 1 << 20, + ContainsTypeScriptClassSyntax = 1 << 11, // Decorators, Property Initializers, Parameter Property Initializers + ContainsLexicalThis = 1 << 12, + ContainsRestOrSpread = 1 << 13, + ContainsObjectRestOrSpread = 1 << 14, + ContainsComputedPropertyName = 1 << 15, + ContainsBlockScopedBinding = 1 << 16, + ContainsBindingPattern = 1 << 17, + ContainsYield = 1 << 18, + ContainsHoistedDeclarationOrCompletion = 1 << 19, + ContainsDynamicImport = 1 << 20, + ContainsClassFields = 1 << 21, // Please leave this as 1 << 29. // It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system. @@ -5622,6 +5623,7 @@ namespace ts { AssertTypeScript = ContainsTypeScript, AssertJsx = ContainsJsx, AssertESNext = ContainsESNext, + AssertES2020 = ContainsES2020, AssertES2019 = ContainsES2019, AssertES2018 = ContainsES2018, AssertES2017 = ContainsES2017, diff --git a/tests/baselines/reference/callChainWithSuper(target=es2020).js b/tests/baselines/reference/callChainWithSuper(target=es2020).js index fcfbb5db553f4..30e1ad3886dc5 100644 --- a/tests/baselines/reference/callChainWithSuper(target=es2020).js +++ b/tests/baselines/reference/callChainWithSuper(target=es2020).js @@ -13,6 +13,6 @@ class Base { method() { } } class Derived extends Base { - method1() { var _a; return (_a = super.method) === null || _a === void 0 ? void 0 : _a.call(this); } - method2() { var _a; return (_a = super["method"]) === null || _a === void 0 ? void 0 : _a.call(this); } + method1() { return super.method?.(); } + method2() { return super["method"]?.(); } } diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.js b/tests/baselines/reference/nullishCoalescingOperator_es2020.js similarity index 93% rename from tests/baselines/reference/nullishCoalescingOperator_esnext.js rename to tests/baselines/reference/nullishCoalescingOperator_es2020.js index d75fea492c6a8..f83a2f7567b4f 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_esnext.js +++ b/tests/baselines/reference/nullishCoalescingOperator_es2020.js @@ -1,4 +1,4 @@ -//// [nullishCoalescingOperator_esnext.ts] +//// [nullishCoalescingOperator_es2020.ts] declare const a1: 'literal' | undefined | null declare const a2: '' | undefined | null declare const a3: 1 | undefined | null @@ -35,9 +35,10 @@ let y2 = c && (a ?? b as any); let y3 = ((a ?? b) as any) && c; let y4 = c && ((a ?? b) as any); let y5 = (a ?? b) as any && c; -let y6 = c && (a ?? b) as any; +let y6 = c && (a ?? b) as any; -//// [nullishCoalescingOperator_esnext.js] + +//// [nullishCoalescingOperator_es2020.js] "use strict"; const aa1 = a1 ?? 'whatever'; const aa2 = a2 ?? 'whatever'; diff --git a/tests/baselines/reference/nullishCoalescingOperator_es2020.symbols b/tests/baselines/reference/nullishCoalescingOperator_es2020.symbols new file mode 100644 index 0000000000000..9887a069a62a0 --- /dev/null +++ b/tests/baselines/reference/nullishCoalescingOperator_es2020.symbols @@ -0,0 +1,143 @@ +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_es2020.ts === +declare const a1: 'literal' | undefined | null +>a1 : Symbol(a1, Decl(nullishCoalescingOperator_es2020.ts, 0, 13)) + +declare const a2: '' | undefined | null +>a2 : Symbol(a2, Decl(nullishCoalescingOperator_es2020.ts, 1, 13)) + +declare const a3: 1 | undefined | null +>a3 : Symbol(a3, Decl(nullishCoalescingOperator_es2020.ts, 2, 13)) + +declare const a4: 0 | undefined | null +>a4 : Symbol(a4, Decl(nullishCoalescingOperator_es2020.ts, 3, 13)) + +declare const a5: true | undefined | null +>a5 : Symbol(a5, Decl(nullishCoalescingOperator_es2020.ts, 4, 13)) + +declare const a6: false | undefined | null +>a6 : Symbol(a6, Decl(nullishCoalescingOperator_es2020.ts, 5, 13)) + +declare const a7: unknown | null +>a7 : Symbol(a7, Decl(nullishCoalescingOperator_es2020.ts, 6, 13)) + +declare const a8: never | null +>a8 : Symbol(a8, Decl(nullishCoalescingOperator_es2020.ts, 7, 13)) + +declare const a9: any | null +>a9 : Symbol(a9, Decl(nullishCoalescingOperator_es2020.ts, 8, 13)) + + +const aa1 = a1 ?? 'whatever' +>aa1 : Symbol(aa1, Decl(nullishCoalescingOperator_es2020.ts, 11, 5)) +>a1 : Symbol(a1, Decl(nullishCoalescingOperator_es2020.ts, 0, 13)) + +const aa2 = a2 ?? 'whatever' +>aa2 : Symbol(aa2, Decl(nullishCoalescingOperator_es2020.ts, 12, 5)) +>a2 : Symbol(a2, Decl(nullishCoalescingOperator_es2020.ts, 1, 13)) + +const aa3 = a3 ?? 'whatever' +>aa3 : Symbol(aa3, Decl(nullishCoalescingOperator_es2020.ts, 13, 5)) +>a3 : Symbol(a3, Decl(nullishCoalescingOperator_es2020.ts, 2, 13)) + +const aa4 = a4 ?? 'whatever' +>aa4 : Symbol(aa4, Decl(nullishCoalescingOperator_es2020.ts, 14, 5)) +>a4 : Symbol(a4, Decl(nullishCoalescingOperator_es2020.ts, 3, 13)) + +const aa5 = a5 ?? 'whatever' +>aa5 : Symbol(aa5, Decl(nullishCoalescingOperator_es2020.ts, 15, 5)) +>a5 : Symbol(a5, Decl(nullishCoalescingOperator_es2020.ts, 4, 13)) + +const aa6 = a6 ?? 'whatever' +>aa6 : Symbol(aa6, Decl(nullishCoalescingOperator_es2020.ts, 16, 5)) +>a6 : Symbol(a6, Decl(nullishCoalescingOperator_es2020.ts, 5, 13)) + +const aa7 = a7 ?? 'whatever' +>aa7 : Symbol(aa7, Decl(nullishCoalescingOperator_es2020.ts, 17, 5)) +>a7 : Symbol(a7, Decl(nullishCoalescingOperator_es2020.ts, 6, 13)) + +const aa8 = a8 ?? 'whatever' +>aa8 : Symbol(aa8, Decl(nullishCoalescingOperator_es2020.ts, 18, 5)) +>a8 : Symbol(a8, Decl(nullishCoalescingOperator_es2020.ts, 7, 13)) + +const aa9 = a9 ?? 'whatever' +>aa9 : Symbol(aa9, Decl(nullishCoalescingOperator_es2020.ts, 19, 5)) +>a9 : Symbol(a9, Decl(nullishCoalescingOperator_es2020.ts, 8, 13)) + + +declare let a: any, b: any, c: any; +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) + +let x1 = (a ?? b as any) || c; +>x1 : Symbol(x1, Decl(nullishCoalescingOperator_es2020.ts, 24, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) + +let x2 = c || (a ?? b as any); +>x2 : Symbol(x2, Decl(nullishCoalescingOperator_es2020.ts, 25, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) + +let x3 = ((a ?? b) as any) || c; +>x3 : Symbol(x3, Decl(nullishCoalescingOperator_es2020.ts, 26, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) + +let x4 = c || ((a ?? b) as any); +>x4 : Symbol(x4, Decl(nullishCoalescingOperator_es2020.ts, 27, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) + +let x5 = (a ?? b) as any || c; +>x5 : Symbol(x5, Decl(nullishCoalescingOperator_es2020.ts, 28, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) + +let x6 = c || (a ?? b) as any; +>x6 : Symbol(x6, Decl(nullishCoalescingOperator_es2020.ts, 29, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) + +let y1 = (a ?? b as any) && c; +>y1 : Symbol(y1, Decl(nullishCoalescingOperator_es2020.ts, 31, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) + +let y2 = c && (a ?? b as any); +>y2 : Symbol(y2, Decl(nullishCoalescingOperator_es2020.ts, 32, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) + +let y3 = ((a ?? b) as any) && c; +>y3 : Symbol(y3, Decl(nullishCoalescingOperator_es2020.ts, 33, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) + +let y4 = c && ((a ?? b) as any); +>y4 : Symbol(y4, Decl(nullishCoalescingOperator_es2020.ts, 34, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) + +let y5 = (a ?? b) as any && c; +>y5 : Symbol(y5, Decl(nullishCoalescingOperator_es2020.ts, 35, 3)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) + +let y6 = c && (a ?? b) as any; +>y6 : Symbol(y6, Decl(nullishCoalescingOperator_es2020.ts, 36, 3)) +>c : Symbol(c, Decl(nullishCoalescingOperator_es2020.ts, 22, 27)) +>a : Symbol(a, Decl(nullishCoalescingOperator_es2020.ts, 22, 11)) +>b : Symbol(b, Decl(nullishCoalescingOperator_es2020.ts, 22, 19)) + diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.types b/tests/baselines/reference/nullishCoalescingOperator_es2020.types similarity index 93% rename from tests/baselines/reference/nullishCoalescingOperator_esnext.types rename to tests/baselines/reference/nullishCoalescingOperator_es2020.types index 3de2d2c6b4d43..2dead6366b7a6 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_esnext.types +++ b/tests/baselines/reference/nullishCoalescingOperator_es2020.types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts === +=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_es2020.ts === declare const a1: 'literal' | undefined | null >a1 : "literal" | null | undefined >null : null diff --git a/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols b/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols deleted file mode 100644 index 42c382c9f1037..0000000000000 --- a/tests/baselines/reference/nullishCoalescingOperator_esnext.symbols +++ /dev/null @@ -1,143 +0,0 @@ -=== tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts === -declare const a1: 'literal' | undefined | null ->a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 0, 13)) - -declare const a2: '' | undefined | null ->a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 1, 13)) - -declare const a3: 1 | undefined | null ->a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 2, 13)) - -declare const a4: 0 | undefined | null ->a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 3, 13)) - -declare const a5: true | undefined | null ->a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 4, 13)) - -declare const a6: false | undefined | null ->a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 5, 13)) - -declare const a7: unknown | null ->a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 6, 13)) - -declare const a8: never | null ->a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 7, 13)) - -declare const a9: any | null ->a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 8, 13)) - - -const aa1 = a1 ?? 'whatever' ->aa1 : Symbol(aa1, Decl(nullishCoalescingOperator_esnext.ts, 11, 5)) ->a1 : Symbol(a1, Decl(nullishCoalescingOperator_esnext.ts, 0, 13)) - -const aa2 = a2 ?? 'whatever' ->aa2 : Symbol(aa2, Decl(nullishCoalescingOperator_esnext.ts, 12, 5)) ->a2 : Symbol(a2, Decl(nullishCoalescingOperator_esnext.ts, 1, 13)) - -const aa3 = a3 ?? 'whatever' ->aa3 : Symbol(aa3, Decl(nullishCoalescingOperator_esnext.ts, 13, 5)) ->a3 : Symbol(a3, Decl(nullishCoalescingOperator_esnext.ts, 2, 13)) - -const aa4 = a4 ?? 'whatever' ->aa4 : Symbol(aa4, Decl(nullishCoalescingOperator_esnext.ts, 14, 5)) ->a4 : Symbol(a4, Decl(nullishCoalescingOperator_esnext.ts, 3, 13)) - -const aa5 = a5 ?? 'whatever' ->aa5 : Symbol(aa5, Decl(nullishCoalescingOperator_esnext.ts, 15, 5)) ->a5 : Symbol(a5, Decl(nullishCoalescingOperator_esnext.ts, 4, 13)) - -const aa6 = a6 ?? 'whatever' ->aa6 : Symbol(aa6, Decl(nullishCoalescingOperator_esnext.ts, 16, 5)) ->a6 : Symbol(a6, Decl(nullishCoalescingOperator_esnext.ts, 5, 13)) - -const aa7 = a7 ?? 'whatever' ->aa7 : Symbol(aa7, Decl(nullishCoalescingOperator_esnext.ts, 17, 5)) ->a7 : Symbol(a7, Decl(nullishCoalescingOperator_esnext.ts, 6, 13)) - -const aa8 = a8 ?? 'whatever' ->aa8 : Symbol(aa8, Decl(nullishCoalescingOperator_esnext.ts, 18, 5)) ->a8 : Symbol(a8, Decl(nullishCoalescingOperator_esnext.ts, 7, 13)) - -const aa9 = a9 ?? 'whatever' ->aa9 : Symbol(aa9, Decl(nullishCoalescingOperator_esnext.ts, 19, 5)) ->a9 : Symbol(a9, Decl(nullishCoalescingOperator_esnext.ts, 8, 13)) - - -declare let a: any, b: any, c: any; ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) - -let x1 = (a ?? b as any) || c; ->x1 : Symbol(x1, Decl(nullishCoalescingOperator_esnext.ts, 24, 3)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) - -let x2 = c || (a ?? b as any); ->x2 : Symbol(x2, Decl(nullishCoalescingOperator_esnext.ts, 25, 3)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) - -let x3 = ((a ?? b) as any) || c; ->x3 : Symbol(x3, Decl(nullishCoalescingOperator_esnext.ts, 26, 3)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) - -let x4 = c || ((a ?? b) as any); ->x4 : Symbol(x4, Decl(nullishCoalescingOperator_esnext.ts, 27, 3)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) - -let x5 = (a ?? b) as any || c; ->x5 : Symbol(x5, Decl(nullishCoalescingOperator_esnext.ts, 28, 3)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) - -let x6 = c || (a ?? b) as any; ->x6 : Symbol(x6, Decl(nullishCoalescingOperator_esnext.ts, 29, 3)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) - -let y1 = (a ?? b as any) && c; ->y1 : Symbol(y1, Decl(nullishCoalescingOperator_esnext.ts, 31, 3)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) - -let y2 = c && (a ?? b as any); ->y2 : Symbol(y2, Decl(nullishCoalescingOperator_esnext.ts, 32, 3)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) - -let y3 = ((a ?? b) as any) && c; ->y3 : Symbol(y3, Decl(nullishCoalescingOperator_esnext.ts, 33, 3)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) - -let y4 = c && ((a ?? b) as any); ->y4 : Symbol(y4, Decl(nullishCoalescingOperator_esnext.ts, 34, 3)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) - -let y5 = (a ?? b) as any && c; ->y5 : Symbol(y5, Decl(nullishCoalescingOperator_esnext.ts, 35, 3)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) - -let y6 = c && (a ?? b) as any; ->y6 : Symbol(y6, Decl(nullishCoalescingOperator_esnext.ts, 36, 3)) ->c : Symbol(c, Decl(nullishCoalescingOperator_esnext.ts, 22, 27)) ->a : Symbol(a, Decl(nullishCoalescingOperator_esnext.ts, 22, 11)) ->b : Symbol(b, Decl(nullishCoalescingOperator_esnext.ts, 22, 19)) - diff --git a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_es2020.ts similarity index 95% rename from tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts rename to tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_es2020.ts index c718ca189e70d..e36db5370f057 100644 --- a/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_esnext.ts +++ b/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator_es2020.ts @@ -1,5 +1,5 @@ // @strict: true -// @target: esnext +// @target: es2020 declare const a1: 'literal' | undefined | null declare const a2: '' | undefined | null @@ -37,4 +37,4 @@ let y2 = c && (a ?? b as any); let y3 = ((a ?? b) as any) && c; let y4 = c && ((a ?? b) as any); let y5 = (a ?? b) as any && c; -let y6 = c && (a ?? b) as any; \ No newline at end of file +let y6 = c && (a ?? b) as any; From 34bf5196873008caf5fc946be9532890a7bc7748 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 23 Dec 2019 12:14:08 -0800 Subject: [PATCH 2/2] Add missing comma --- src/compiler/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 499d1bf95581a..7d2510b4f9a4b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5609,7 +5609,7 @@ namespace ts { ContainsBlockScopedBinding = 1 << 16, ContainsBindingPattern = 1 << 17, ContainsYield = 1 << 18, - ContainsAwait = 1 << 19 + ContainsAwait = 1 << 19, ContainsHoistedDeclarationOrCompletion = 1 << 20, ContainsDynamicImport = 1 << 21, ContainsClassFields = 1 << 22,