Add es2020 transformation (#35518)

* Add es2020 transformation

* Add missing comma

Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
This commit is contained in:
Kagami Sascha Rosylight
2019-12-24 09:45:17 +09:00
committed by Daniel Rosenwasser
parent 320adf5ce0
commit 0f5ddd2ea0
12 changed files with 389 additions and 357 deletions

View File

@@ -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

View File

@@ -55,6 +55,10 @@ namespace ts {
transformers.push(transformESNext);
}
if (languageVersion < ScriptTarget.ES2020) {
transformers.push(transformES2020);
}
if (languageVersion < ScriptTarget.ES2019) {
transformers.push(transformES2019);
}

View File

@@ -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<Node> {
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 ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.QuestionQuestionToken) {
return transformNullishCoalescingExpression(<BinaryExpression>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));
}
}
}

View File

@@ -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 ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.QuestionQuestionToken) {
return transformNullishCoalescingExpression(<BinaryExpression>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));
}
}
}

View File

@@ -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",

View File

@@ -5590,28 +5590,29 @@ 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,
ContainsAwait = 1 << 18,
ContainsHoistedDeclarationOrCompletion = 1 << 19,
ContainsDynamicImport = 1 << 20,
ContainsClassFields = 1 << 21,
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,
ContainsAwait = 1 << 19,
ContainsHoistedDeclarationOrCompletion = 1 << 20,
ContainsDynamicImport = 1 << 21,
ContainsClassFields = 1 << 22,
// 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.
@@ -5623,6 +5624,7 @@ namespace ts {
AssertTypeScript = ContainsTypeScript,
AssertJsx = ContainsJsx,
AssertESNext = ContainsESNext,
AssertES2020 = ContainsES2020,
AssertES2019 = ContainsES2019,
AssertES2018 = ContainsES2018,
AssertES2017 = ContainsES2017,

View File

@@ -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"]?.(); }
}

View File

@@ -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';

View File

@@ -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))

View File

@@ -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

View File

@@ -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))

View File

@@ -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;
let y6 = c && (a ?? b) as any;