From 1d93db81cc2182a026017b94a9a37730ed82aea1 Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 1 Apr 2020 11:08:26 +0800 Subject: [PATCH 01/24] Add logical assignment operator --- src/compiler/binder.ts | 3 + src/compiler/checker.ts | 24 +- src/compiler/scanner.ts | 24 +- src/compiler/transformers/esnext.ts | 37 ++ src/compiler/transformers/utilities.ts | 14 +- src/compiler/types.ts | 6 + src/compiler/utilities.ts | 16 + src/services/classifier.ts | 3 + src/services/codefixes/inferFromUsage.ts | 6 + src/testRunner/unittests/factory.ts | 3 + .../reference/api/tsserverlibrary.d.ts | 561 +++++++++--------- tests/baselines/reference/api/typescript.d.ts | 561 +++++++++--------- .../logicalAssignment1(target=es2015).js | 39 ++ .../logicalAssignment1(target=es2015).symbols | 57 ++ .../logicalAssignment1(target=es2015).types | 75 +++ .../logicalAssignment1(target=es2020).js | 39 ++ .../logicalAssignment1(target=es2020).symbols | 57 ++ .../logicalAssignment1(target=es2020).types | 75 +++ .../logicalAssignment1(target=esnext).js | 39 ++ .../logicalAssignment1(target=esnext).symbols | 57 ++ .../logicalAssignment1(target=esnext).types | 75 +++ .../logicalAssignment/logicalAssignment1.ts | 27 + 22 files changed, 1229 insertions(+), 569 deletions(-) create mode 100644 tests/baselines/reference/logicalAssignment1(target=es2015).js create mode 100644 tests/baselines/reference/logicalAssignment1(target=es2015).symbols create mode 100644 tests/baselines/reference/logicalAssignment1(target=es2015).types create mode 100644 tests/baselines/reference/logicalAssignment1(target=es2020).js create mode 100644 tests/baselines/reference/logicalAssignment1(target=es2020).symbols create mode 100644 tests/baselines/reference/logicalAssignment1(target=es2020).types create mode 100644 tests/baselines/reference/logicalAssignment1(target=esnext).js create mode 100644 tests/baselines/reference/logicalAssignment1(target=esnext).symbols create mode 100644 tests/baselines/reference/logicalAssignment1(target=esnext).types create mode 100644 tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8a47755498b34..93a3bc5538d5c 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3601,6 +3601,9 @@ namespace ts { if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) { transformFlags |= TransformFlags.AssertES2020; } + else if (isLogicalAssignmentOperator(operatorTokenKind)) { + transformFlags |= TransformFlags.AssertESNext; + } else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) { // Destructuring object assignments with are ES2015 syntax // and possibly ES2018 if they contain rest diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ee6a3a81c903c..4b52f2faab0b3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28579,17 +28579,35 @@ namespace ts { case SyntaxKind.InKeyword: return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: - return getTypeFacts(leftType) & TypeFacts.Truthy ? + case SyntaxKind.AmpersandAmpersandEqualsToken: { + const resultType = getTypeFacts(leftType) & TypeFacts.Truthy ? getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) : leftType; + if (operator === SyntaxKind.AmpersandAmpersandEqualsToken) { + checkAssignmentOperator(resultType); + } + return resultType; + } case SyntaxKind.BarBarToken: - return getTypeFacts(leftType) & TypeFacts.Falsy ? + case SyntaxKind.BarBarEqualsToken: { + const resultType = getTypeFacts(leftType) & TypeFacts.Falsy ? getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) : leftType; + if (operator === SyntaxKind.BarBarEqualsToken) { + checkAssignmentOperator(resultType); + } + return resultType; + } case SyntaxKind.QuestionQuestionToken: - return getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull ? + case SyntaxKind.QuestionQuestionEqualsToken: { + const resultType = getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull ? getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) : leftType; + if (operator === SyntaxKind.QuestionQuestionEqualsToken) { + checkAssignmentOperator(resultType); + } + return resultType; + } case SyntaxKind.EqualsToken: const declKind = isBinaryExpression(left.parent) ? getAssignmentDeclarationKind(left.parent) : AssignmentDeclarationKind.None; checkAssignmentDeclaration(declKind, rightType); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index a4513e8cdf6df..27c88e8e13d84 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -208,6 +208,9 @@ namespace ts { "&=": SyntaxKind.AmpersandEqualsToken, "|=": SyntaxKind.BarEqualsToken, "^=": SyntaxKind.CaretEqualsToken, + "||=": SyntaxKind.BarBarEqualsToken, + "&&=": SyntaxKind.AmpersandAmpersandEqualsToken, + "??=": SyntaxKind.QuestionQuestionEqualsToken, "@": SyntaxKind.AtToken, "`": SyntaxKind.BacktickToken }); @@ -1667,6 +1670,9 @@ namespace ts { return token = SyntaxKind.PercentToken; case CharacterCodes.ampersand: if (text.charCodeAt(pos + 1) === CharacterCodes.ampersand) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.AmpersandAmpersandEqualsToken; + } return pos += 2, token = SyntaxKind.AmpersandAmpersandToken; } if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { @@ -1928,15 +1934,16 @@ namespace ts { pos++; return token = SyntaxKind.GreaterThanToken; case CharacterCodes.question: - pos++; - if (text.charCodeAt(pos) === CharacterCodes.dot && !isDigit(text.charCodeAt(pos + 1))) { - pos++; - return token = SyntaxKind.QuestionDotToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.dot && !isDigit(text.charCodeAt(pos + 2))) { + return pos += 2, token = SyntaxKind.QuestionDotToken; } - if (text.charCodeAt(pos) === CharacterCodes.question) { - pos++; - return token = SyntaxKind.QuestionQuestionToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.question) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.QuestionQuestionEqualsToken; + } + return pos += 2, token = SyntaxKind.QuestionQuestionToken; } + pos++; return token = SyntaxKind.QuestionToken; case CharacterCodes.openBracket: pos++; @@ -1965,6 +1972,9 @@ namespace ts { } if (text.charCodeAt(pos + 1) === CharacterCodes.bar) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.BarBarEqualsToken; + } return pos += 2, token = SyntaxKind.BarBarToken; } if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 80debb46f8a04..96c0e0178a7b9 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -1,6 +1,10 @@ /*@internal*/ namespace ts { export function transformESNext(context: TransformationContext) { + const { + hoistVariableDeclaration + } = context; + return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { @@ -16,9 +20,42 @@ namespace ts { return node; } switch (node.kind) { + case SyntaxKind.BinaryExpression: + const binaryExpression = node; + if (isLogicalAssignmentOperator(binaryExpression.operatorToken.kind)) { + return transformLogicalAssignmentOperators(binaryExpression); + } + // falls through default: return visitEachChild(node, visitor, context); } } + + function transformLogicalAssignmentOperators(binaryExpression: BinaryExpression): VisitResult { + const operator = binaryExpression.operatorToken; + if (isCompoundAssignment(operator.kind) && isLogicalAssignmentOperator(operator.kind)) { + const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); + const left = visitNode(binaryExpression.left, visitor, isExpression); + const right = visitNode(binaryExpression.right, visitor, isExpression); + let cond = left; + if (shouldCaptureInTempVariable(left)) { + const temp = createTempVariable(hoistVariableDeclaration); + cond = createAssignment(temp, left); + } + + return createBinary( + cond, + nonAssignmentOperator, + createParen( + createAssignment( + left, + right + ) + ) + ) + + } + Debug.fail("unexpected operator: " + operator.kind); + } } } diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 4a4dc05de76a7..a54d1d05e5d73 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -259,7 +259,7 @@ namespace ts { && kind <= SyntaxKind.LastCompoundAssignment; } - export function getNonAssignmentOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): BitwiseOperatorOrHigher { + export function getNonAssignmentOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): LogicalOperatorOrHigher | SyntaxKind.QuestionQuestionToken { switch (kind) { case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken; case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken; @@ -273,9 +273,21 @@ namespace ts { case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken; case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken; case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken; + case SyntaxKind.BarBarEqualsToken: return SyntaxKind.BarBarToken; + case SyntaxKind.AmpersandAmpersandEqualsToken: return SyntaxKind.AmpersandAmpersandToken; + case SyntaxKind.QuestionQuestionEqualsToken: return SyntaxKind.QuestionQuestionToken; + } } + export 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; + } + /** * Adds super call and preceding prologue directives into the list of statements. * diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 54d889b2ff4fc..728673aa851fd 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -203,6 +203,9 @@ namespace ts { GreaterThanGreaterThanGreaterThanEqualsToken, AmpersandEqualsToken, BarEqualsToken, + BarBarEqualsToken, + AmpersandAmpersandEqualsToken, + QuestionQuestionEqualsToken, CaretEqualsToken, // Identifiers and PrivateIdentifiers Identifier, @@ -1597,6 +1600,9 @@ namespace ts { | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken + | SyntaxKind.BarBarEqualsToken + | SyntaxKind.AmpersandAmpersandEqualsToken + | SyntaxKind.QuestionQuestionEqualsToken ; // see: https://tc39.github.io/ecma262/#prod-AssignmentExpression diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 17ce0562122e0..4448e0f18bb27 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3220,6 +3220,9 @@ namespace ts { case SyntaxKind.AmpersandEqualsToken: case SyntaxKind.CaretEqualsToken: case SyntaxKind.BarEqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return Associativity.Right; } } @@ -3276,6 +3279,9 @@ namespace ts { case SyntaxKind.AmpersandEqualsToken: case SyntaxKind.CaretEqualsToken: case SyntaxKind.BarEqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return 3; default: @@ -3372,6 +3378,10 @@ namespace ts { return 14; case SyntaxKind.AsteriskAsteriskToken: return 15; + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: + return 16; } // -1 is lower than all other precedences. Returning it will cause binary expression @@ -4444,6 +4454,12 @@ namespace ts { || token === SyntaxKind.ExclamationToken; } + export function isLogicalAssignmentOperator(token: SyntaxKind): boolean { + return token === SyntaxKind.BarBarEqualsToken + || token === SyntaxKind.AmpersandAmpersandEqualsToken + || token === SyntaxKind.QuestionQuestionEqualsToken; + } + export function isAssignmentOperator(token: SyntaxKind): boolean { return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment; } diff --git a/src/services/classifier.ts b/src/services/classifier.ts index 1d8f86195b8ae..7144a28eebfbf 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -392,6 +392,9 @@ namespace ts { case SyntaxKind.EqualsToken: case SyntaxKind.CommaToken: case SyntaxKind.QuestionQuestionToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return true; default: return false; diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index bf6b918086041..ec17923d86210 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -785,6 +785,12 @@ namespace ts.codefix { } break; + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + // TODO: infer here + break; + case SyntaxKind.AmpersandAmpersandToken: case SyntaxKind.CommaToken: case SyntaxKind.InstanceOfKeyword: diff --git a/src/testRunner/unittests/factory.ts b/src/testRunner/unittests/factory.ts index ae4258287fedb..b7f510ecdfdc6 100644 --- a/src/testRunner/unittests/factory.ts +++ b/src/testRunner/unittests/factory.ts @@ -77,6 +77,9 @@ namespace ts { checkRhs(SyntaxKind.AmpersandAmpersandToken, /*expectParens*/ true); checkRhs(SyntaxKind.QuestionQuestionToken, /*expectParens*/ true); checkRhs(SyntaxKind.EqualsEqualsToken, /*expectParens*/ true); + checkRhs(SyntaxKind.BarBarEqualsToken, /*expectParens*/ false); + checkRhs(SyntaxKind.AmpersandAmpersandEqualsToken, /*expectParens*/ false); + checkRhs(SyntaxKind.QuestionQuestionEqualsToken, /*expectParens*/ false); }); }); }); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 2c7742fb88b97..efd6c9afd522c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -149,280 +149,283 @@ declare namespace ts { GreaterThanGreaterThanGreaterThanEqualsToken = 71, AmpersandEqualsToken = 72, BarEqualsToken = 73, - CaretEqualsToken = 74, - Identifier = 75, - PrivateIdentifier = 76, - BreakKeyword = 77, - CaseKeyword = 78, - CatchKeyword = 79, - ClassKeyword = 80, - ConstKeyword = 81, - ContinueKeyword = 82, - DebuggerKeyword = 83, - DefaultKeyword = 84, - DeleteKeyword = 85, - DoKeyword = 86, - ElseKeyword = 87, - EnumKeyword = 88, - ExportKeyword = 89, - ExtendsKeyword = 90, - FalseKeyword = 91, - FinallyKeyword = 92, - ForKeyword = 93, - FunctionKeyword = 94, - IfKeyword = 95, - ImportKeyword = 96, - InKeyword = 97, - InstanceOfKeyword = 98, - NewKeyword = 99, - NullKeyword = 100, - ReturnKeyword = 101, - SuperKeyword = 102, - SwitchKeyword = 103, - ThisKeyword = 104, - ThrowKeyword = 105, - TrueKeyword = 106, - TryKeyword = 107, - TypeOfKeyword = 108, - VarKeyword = 109, - VoidKeyword = 110, - WhileKeyword = 111, - WithKeyword = 112, - ImplementsKeyword = 113, - InterfaceKeyword = 114, - LetKeyword = 115, - PackageKeyword = 116, - PrivateKeyword = 117, - ProtectedKeyword = 118, - PublicKeyword = 119, - StaticKeyword = 120, - YieldKeyword = 121, - AbstractKeyword = 122, - AsKeyword = 123, - AssertsKeyword = 124, - AnyKeyword = 125, - AsyncKeyword = 126, - AwaitKeyword = 127, - BooleanKeyword = 128, - ConstructorKeyword = 129, - DeclareKeyword = 130, - GetKeyword = 131, - InferKeyword = 132, - IsKeyword = 133, - KeyOfKeyword = 134, - ModuleKeyword = 135, - NamespaceKeyword = 136, - NeverKeyword = 137, - ReadonlyKeyword = 138, - RequireKeyword = 139, - NumberKeyword = 140, - ObjectKeyword = 141, - SetKeyword = 142, - StringKeyword = 143, - SymbolKeyword = 144, - TypeKeyword = 145, - UndefinedKeyword = 146, - UniqueKeyword = 147, - UnknownKeyword = 148, - FromKeyword = 149, - GlobalKeyword = 150, - BigIntKeyword = 151, - OfKeyword = 152, - QualifiedName = 153, - ComputedPropertyName = 154, - TypeParameter = 155, - Parameter = 156, - Decorator = 157, - PropertySignature = 158, - PropertyDeclaration = 159, - MethodSignature = 160, - MethodDeclaration = 161, - Constructor = 162, - GetAccessor = 163, - SetAccessor = 164, - CallSignature = 165, - ConstructSignature = 166, - IndexSignature = 167, - TypePredicate = 168, - TypeReference = 169, - FunctionType = 170, - ConstructorType = 171, - TypeQuery = 172, - TypeLiteral = 173, - ArrayType = 174, - TupleType = 175, - OptionalType = 176, - RestType = 177, - UnionType = 178, - IntersectionType = 179, - ConditionalType = 180, - InferType = 181, - ParenthesizedType = 182, - ThisType = 183, - TypeOperator = 184, - IndexedAccessType = 185, - MappedType = 186, - LiteralType = 187, - ImportType = 188, - ObjectBindingPattern = 189, - ArrayBindingPattern = 190, - BindingElement = 191, - ArrayLiteralExpression = 192, - ObjectLiteralExpression = 193, - PropertyAccessExpression = 194, - ElementAccessExpression = 195, - CallExpression = 196, - NewExpression = 197, - TaggedTemplateExpression = 198, - TypeAssertionExpression = 199, - ParenthesizedExpression = 200, - FunctionExpression = 201, - ArrowFunction = 202, - DeleteExpression = 203, - TypeOfExpression = 204, - VoidExpression = 205, - AwaitExpression = 206, - PrefixUnaryExpression = 207, - PostfixUnaryExpression = 208, - BinaryExpression = 209, - ConditionalExpression = 210, - TemplateExpression = 211, - YieldExpression = 212, - SpreadElement = 213, - ClassExpression = 214, - OmittedExpression = 215, - ExpressionWithTypeArguments = 216, - AsExpression = 217, - NonNullExpression = 218, - MetaProperty = 219, - SyntheticExpression = 220, - TemplateSpan = 221, - SemicolonClassElement = 222, - Block = 223, - EmptyStatement = 224, - VariableStatement = 225, - ExpressionStatement = 226, - IfStatement = 227, - DoStatement = 228, - WhileStatement = 229, - ForStatement = 230, - ForInStatement = 231, - ForOfStatement = 232, - ContinueStatement = 233, - BreakStatement = 234, - ReturnStatement = 235, - WithStatement = 236, - SwitchStatement = 237, - LabeledStatement = 238, - ThrowStatement = 239, - TryStatement = 240, - DebuggerStatement = 241, - VariableDeclaration = 242, - VariableDeclarationList = 243, - FunctionDeclaration = 244, - ClassDeclaration = 245, - InterfaceDeclaration = 246, - TypeAliasDeclaration = 247, - EnumDeclaration = 248, - ModuleDeclaration = 249, - ModuleBlock = 250, - CaseBlock = 251, - NamespaceExportDeclaration = 252, - ImportEqualsDeclaration = 253, - ImportDeclaration = 254, - ImportClause = 255, - NamespaceImport = 256, - NamedImports = 257, - ImportSpecifier = 258, - ExportAssignment = 259, - ExportDeclaration = 260, - NamedExports = 261, - NamespaceExport = 262, - ExportSpecifier = 263, - MissingDeclaration = 264, - ExternalModuleReference = 265, - JsxElement = 266, - JsxSelfClosingElement = 267, - JsxOpeningElement = 268, - JsxClosingElement = 269, - JsxFragment = 270, - JsxOpeningFragment = 271, - JsxClosingFragment = 272, - JsxAttribute = 273, - JsxAttributes = 274, - JsxSpreadAttribute = 275, - JsxExpression = 276, - CaseClause = 277, - DefaultClause = 278, - HeritageClause = 279, - CatchClause = 280, - PropertyAssignment = 281, - ShorthandPropertyAssignment = 282, - SpreadAssignment = 283, - EnumMember = 284, - UnparsedPrologue = 285, - UnparsedPrepend = 286, - UnparsedText = 287, - UnparsedInternalText = 288, - UnparsedSyntheticReference = 289, - SourceFile = 290, - Bundle = 291, - UnparsedSource = 292, - InputFiles = 293, - JSDocTypeExpression = 294, - JSDocAllType = 295, - JSDocUnknownType = 296, - JSDocNullableType = 297, - JSDocNonNullableType = 298, - JSDocOptionalType = 299, - JSDocFunctionType = 300, - JSDocVariadicType = 301, - JSDocNamepathType = 302, - JSDocComment = 303, - JSDocTypeLiteral = 304, - JSDocSignature = 305, - JSDocTag = 306, - JSDocAugmentsTag = 307, - JSDocImplementsTag = 308, - JSDocAuthorTag = 309, - JSDocClassTag = 310, - JSDocPublicTag = 311, - JSDocPrivateTag = 312, - JSDocProtectedTag = 313, - JSDocReadonlyTag = 314, - JSDocCallbackTag = 315, - JSDocEnumTag = 316, - JSDocParameterTag = 317, - JSDocReturnTag = 318, - JSDocThisTag = 319, - JSDocTypeTag = 320, - JSDocTemplateTag = 321, - JSDocTypedefTag = 322, - JSDocPropertyTag = 323, - SyntaxList = 324, - NotEmittedStatement = 325, - PartiallyEmittedExpression = 326, - CommaListExpression = 327, - MergeDeclarationMarker = 328, - EndOfDeclarationMarker = 329, - SyntheticReferenceExpression = 330, - Count = 331, + BarBarEqualsToken = 74, + AmpersandAmpersandEqualsToken = 75, + QuestionQuestionEqualsToken = 76, + CaretEqualsToken = 77, + Identifier = 78, + PrivateIdentifier = 79, + BreakKeyword = 80, + CaseKeyword = 81, + CatchKeyword = 82, + ClassKeyword = 83, + ConstKeyword = 84, + ContinueKeyword = 85, + DebuggerKeyword = 86, + DefaultKeyword = 87, + DeleteKeyword = 88, + DoKeyword = 89, + ElseKeyword = 90, + EnumKeyword = 91, + ExportKeyword = 92, + ExtendsKeyword = 93, + FalseKeyword = 94, + FinallyKeyword = 95, + ForKeyword = 96, + FunctionKeyword = 97, + IfKeyword = 98, + ImportKeyword = 99, + InKeyword = 100, + InstanceOfKeyword = 101, + NewKeyword = 102, + NullKeyword = 103, + ReturnKeyword = 104, + SuperKeyword = 105, + SwitchKeyword = 106, + ThisKeyword = 107, + ThrowKeyword = 108, + TrueKeyword = 109, + TryKeyword = 110, + TypeOfKeyword = 111, + VarKeyword = 112, + VoidKeyword = 113, + WhileKeyword = 114, + WithKeyword = 115, + ImplementsKeyword = 116, + InterfaceKeyword = 117, + LetKeyword = 118, + PackageKeyword = 119, + PrivateKeyword = 120, + ProtectedKeyword = 121, + PublicKeyword = 122, + StaticKeyword = 123, + YieldKeyword = 124, + AbstractKeyword = 125, + AsKeyword = 126, + AssertsKeyword = 127, + AnyKeyword = 128, + AsyncKeyword = 129, + AwaitKeyword = 130, + BooleanKeyword = 131, + ConstructorKeyword = 132, + DeclareKeyword = 133, + GetKeyword = 134, + InferKeyword = 135, + IsKeyword = 136, + KeyOfKeyword = 137, + ModuleKeyword = 138, + NamespaceKeyword = 139, + NeverKeyword = 140, + ReadonlyKeyword = 141, + RequireKeyword = 142, + NumberKeyword = 143, + ObjectKeyword = 144, + SetKeyword = 145, + StringKeyword = 146, + SymbolKeyword = 147, + TypeKeyword = 148, + UndefinedKeyword = 149, + UniqueKeyword = 150, + UnknownKeyword = 151, + FromKeyword = 152, + GlobalKeyword = 153, + BigIntKeyword = 154, + OfKeyword = 155, + QualifiedName = 156, + ComputedPropertyName = 157, + TypeParameter = 158, + Parameter = 159, + Decorator = 160, + PropertySignature = 161, + PropertyDeclaration = 162, + MethodSignature = 163, + MethodDeclaration = 164, + Constructor = 165, + GetAccessor = 166, + SetAccessor = 167, + CallSignature = 168, + ConstructSignature = 169, + IndexSignature = 170, + TypePredicate = 171, + TypeReference = 172, + FunctionType = 173, + ConstructorType = 174, + TypeQuery = 175, + TypeLiteral = 176, + ArrayType = 177, + TupleType = 178, + OptionalType = 179, + RestType = 180, + UnionType = 181, + IntersectionType = 182, + ConditionalType = 183, + InferType = 184, + ParenthesizedType = 185, + ThisType = 186, + TypeOperator = 187, + IndexedAccessType = 188, + MappedType = 189, + LiteralType = 190, + ImportType = 191, + ObjectBindingPattern = 192, + ArrayBindingPattern = 193, + BindingElement = 194, + ArrayLiteralExpression = 195, + ObjectLiteralExpression = 196, + PropertyAccessExpression = 197, + ElementAccessExpression = 198, + CallExpression = 199, + NewExpression = 200, + TaggedTemplateExpression = 201, + TypeAssertionExpression = 202, + ParenthesizedExpression = 203, + FunctionExpression = 204, + ArrowFunction = 205, + DeleteExpression = 206, + TypeOfExpression = 207, + VoidExpression = 208, + AwaitExpression = 209, + PrefixUnaryExpression = 210, + PostfixUnaryExpression = 211, + BinaryExpression = 212, + ConditionalExpression = 213, + TemplateExpression = 214, + YieldExpression = 215, + SpreadElement = 216, + ClassExpression = 217, + OmittedExpression = 218, + ExpressionWithTypeArguments = 219, + AsExpression = 220, + NonNullExpression = 221, + MetaProperty = 222, + SyntheticExpression = 223, + TemplateSpan = 224, + SemicolonClassElement = 225, + Block = 226, + EmptyStatement = 227, + VariableStatement = 228, + ExpressionStatement = 229, + IfStatement = 230, + DoStatement = 231, + WhileStatement = 232, + ForStatement = 233, + ForInStatement = 234, + ForOfStatement = 235, + ContinueStatement = 236, + BreakStatement = 237, + ReturnStatement = 238, + WithStatement = 239, + SwitchStatement = 240, + LabeledStatement = 241, + ThrowStatement = 242, + TryStatement = 243, + DebuggerStatement = 244, + VariableDeclaration = 245, + VariableDeclarationList = 246, + FunctionDeclaration = 247, + ClassDeclaration = 248, + InterfaceDeclaration = 249, + TypeAliasDeclaration = 250, + EnumDeclaration = 251, + ModuleDeclaration = 252, + ModuleBlock = 253, + CaseBlock = 254, + NamespaceExportDeclaration = 255, + ImportEqualsDeclaration = 256, + ImportDeclaration = 257, + ImportClause = 258, + NamespaceImport = 259, + NamedImports = 260, + ImportSpecifier = 261, + ExportAssignment = 262, + ExportDeclaration = 263, + NamedExports = 264, + NamespaceExport = 265, + ExportSpecifier = 266, + MissingDeclaration = 267, + ExternalModuleReference = 268, + JsxElement = 269, + JsxSelfClosingElement = 270, + JsxOpeningElement = 271, + JsxClosingElement = 272, + JsxFragment = 273, + JsxOpeningFragment = 274, + JsxClosingFragment = 275, + JsxAttribute = 276, + JsxAttributes = 277, + JsxSpreadAttribute = 278, + JsxExpression = 279, + CaseClause = 280, + DefaultClause = 281, + HeritageClause = 282, + CatchClause = 283, + PropertyAssignment = 284, + ShorthandPropertyAssignment = 285, + SpreadAssignment = 286, + EnumMember = 287, + UnparsedPrologue = 288, + UnparsedPrepend = 289, + UnparsedText = 290, + UnparsedInternalText = 291, + UnparsedSyntheticReference = 292, + SourceFile = 293, + Bundle = 294, + UnparsedSource = 295, + InputFiles = 296, + JSDocTypeExpression = 297, + JSDocAllType = 298, + JSDocUnknownType = 299, + JSDocNullableType = 300, + JSDocNonNullableType = 301, + JSDocOptionalType = 302, + JSDocFunctionType = 303, + JSDocVariadicType = 304, + JSDocNamepathType = 305, + JSDocComment = 306, + JSDocTypeLiteral = 307, + JSDocSignature = 308, + JSDocTag = 309, + JSDocAugmentsTag = 310, + JSDocImplementsTag = 311, + JSDocAuthorTag = 312, + JSDocClassTag = 313, + JSDocPublicTag = 314, + JSDocPrivateTag = 315, + JSDocProtectedTag = 316, + JSDocReadonlyTag = 317, + JSDocCallbackTag = 318, + JSDocEnumTag = 319, + JSDocParameterTag = 320, + JSDocReturnTag = 321, + JSDocThisTag = 322, + JSDocTypeTag = 323, + JSDocTemplateTag = 324, + JSDocTypedefTag = 325, + JSDocPropertyTag = 326, + SyntaxList = 327, + NotEmittedStatement = 328, + PartiallyEmittedExpression = 329, + CommaListExpression = 330, + MergeDeclarationMarker = 331, + EndOfDeclarationMarker = 332, + SyntheticReferenceExpression = 333, + Count = 334, FirstAssignment = 62, - LastAssignment = 74, + LastAssignment = 77, FirstCompoundAssignment = 63, - LastCompoundAssignment = 74, - FirstReservedWord = 77, - LastReservedWord = 112, - FirstKeyword = 77, - LastKeyword = 152, - FirstFutureReservedWord = 113, - LastFutureReservedWord = 121, - FirstTypeNode = 168, - LastTypeNode = 188, + LastCompoundAssignment = 77, + FirstReservedWord = 80, + LastReservedWord = 115, + FirstKeyword = 80, + LastKeyword = 155, + FirstFutureReservedWord = 116, + LastFutureReservedWord = 124, + FirstTypeNode = 171, + LastTypeNode = 191, FirstPunctuation = 18, - LastPunctuation = 74, + LastPunctuation = 77, FirstToken = 0, - LastToken = 152, + LastToken = 155, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -430,14 +433,14 @@ declare namespace ts { FirstTemplateToken = 14, LastTemplateToken = 17, FirstBinaryOperator = 29, - LastBinaryOperator = 74, - FirstStatement = 225, - LastStatement = 241, - FirstNode = 153, - FirstJSDocNode = 294, - LastJSDocNode = 323, - FirstJSDocTagNode = 306, - LastJSDocTagNode = 323, + LastBinaryOperator = 77, + FirstStatement = 228, + LastStatement = 244, + FirstNode = 156, + FirstJSDocNode = 297, + LastJSDocNode = 326, + FirstJSDocTagNode = 309, + LastJSDocTagNode = 326, } export enum NodeFlags { None = 0, @@ -963,7 +966,7 @@ declare namespace ts { export type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken; export type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; - export type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; + export type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; export type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; export type AssignmentOperatorOrHigher = SyntaxKind.QuestionQuestionToken | LogicalOperatorOrHigher | AssignmentOperator; export type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index c901f86e38499..1efec605a9e13 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -149,280 +149,283 @@ declare namespace ts { GreaterThanGreaterThanGreaterThanEqualsToken = 71, AmpersandEqualsToken = 72, BarEqualsToken = 73, - CaretEqualsToken = 74, - Identifier = 75, - PrivateIdentifier = 76, - BreakKeyword = 77, - CaseKeyword = 78, - CatchKeyword = 79, - ClassKeyword = 80, - ConstKeyword = 81, - ContinueKeyword = 82, - DebuggerKeyword = 83, - DefaultKeyword = 84, - DeleteKeyword = 85, - DoKeyword = 86, - ElseKeyword = 87, - EnumKeyword = 88, - ExportKeyword = 89, - ExtendsKeyword = 90, - FalseKeyword = 91, - FinallyKeyword = 92, - ForKeyword = 93, - FunctionKeyword = 94, - IfKeyword = 95, - ImportKeyword = 96, - InKeyword = 97, - InstanceOfKeyword = 98, - NewKeyword = 99, - NullKeyword = 100, - ReturnKeyword = 101, - SuperKeyword = 102, - SwitchKeyword = 103, - ThisKeyword = 104, - ThrowKeyword = 105, - TrueKeyword = 106, - TryKeyword = 107, - TypeOfKeyword = 108, - VarKeyword = 109, - VoidKeyword = 110, - WhileKeyword = 111, - WithKeyword = 112, - ImplementsKeyword = 113, - InterfaceKeyword = 114, - LetKeyword = 115, - PackageKeyword = 116, - PrivateKeyword = 117, - ProtectedKeyword = 118, - PublicKeyword = 119, - StaticKeyword = 120, - YieldKeyword = 121, - AbstractKeyword = 122, - AsKeyword = 123, - AssertsKeyword = 124, - AnyKeyword = 125, - AsyncKeyword = 126, - AwaitKeyword = 127, - BooleanKeyword = 128, - ConstructorKeyword = 129, - DeclareKeyword = 130, - GetKeyword = 131, - InferKeyword = 132, - IsKeyword = 133, - KeyOfKeyword = 134, - ModuleKeyword = 135, - NamespaceKeyword = 136, - NeverKeyword = 137, - ReadonlyKeyword = 138, - RequireKeyword = 139, - NumberKeyword = 140, - ObjectKeyword = 141, - SetKeyword = 142, - StringKeyword = 143, - SymbolKeyword = 144, - TypeKeyword = 145, - UndefinedKeyword = 146, - UniqueKeyword = 147, - UnknownKeyword = 148, - FromKeyword = 149, - GlobalKeyword = 150, - BigIntKeyword = 151, - OfKeyword = 152, - QualifiedName = 153, - ComputedPropertyName = 154, - TypeParameter = 155, - Parameter = 156, - Decorator = 157, - PropertySignature = 158, - PropertyDeclaration = 159, - MethodSignature = 160, - MethodDeclaration = 161, - Constructor = 162, - GetAccessor = 163, - SetAccessor = 164, - CallSignature = 165, - ConstructSignature = 166, - IndexSignature = 167, - TypePredicate = 168, - TypeReference = 169, - FunctionType = 170, - ConstructorType = 171, - TypeQuery = 172, - TypeLiteral = 173, - ArrayType = 174, - TupleType = 175, - OptionalType = 176, - RestType = 177, - UnionType = 178, - IntersectionType = 179, - ConditionalType = 180, - InferType = 181, - ParenthesizedType = 182, - ThisType = 183, - TypeOperator = 184, - IndexedAccessType = 185, - MappedType = 186, - LiteralType = 187, - ImportType = 188, - ObjectBindingPattern = 189, - ArrayBindingPattern = 190, - BindingElement = 191, - ArrayLiteralExpression = 192, - ObjectLiteralExpression = 193, - PropertyAccessExpression = 194, - ElementAccessExpression = 195, - CallExpression = 196, - NewExpression = 197, - TaggedTemplateExpression = 198, - TypeAssertionExpression = 199, - ParenthesizedExpression = 200, - FunctionExpression = 201, - ArrowFunction = 202, - DeleteExpression = 203, - TypeOfExpression = 204, - VoidExpression = 205, - AwaitExpression = 206, - PrefixUnaryExpression = 207, - PostfixUnaryExpression = 208, - BinaryExpression = 209, - ConditionalExpression = 210, - TemplateExpression = 211, - YieldExpression = 212, - SpreadElement = 213, - ClassExpression = 214, - OmittedExpression = 215, - ExpressionWithTypeArguments = 216, - AsExpression = 217, - NonNullExpression = 218, - MetaProperty = 219, - SyntheticExpression = 220, - TemplateSpan = 221, - SemicolonClassElement = 222, - Block = 223, - EmptyStatement = 224, - VariableStatement = 225, - ExpressionStatement = 226, - IfStatement = 227, - DoStatement = 228, - WhileStatement = 229, - ForStatement = 230, - ForInStatement = 231, - ForOfStatement = 232, - ContinueStatement = 233, - BreakStatement = 234, - ReturnStatement = 235, - WithStatement = 236, - SwitchStatement = 237, - LabeledStatement = 238, - ThrowStatement = 239, - TryStatement = 240, - DebuggerStatement = 241, - VariableDeclaration = 242, - VariableDeclarationList = 243, - FunctionDeclaration = 244, - ClassDeclaration = 245, - InterfaceDeclaration = 246, - TypeAliasDeclaration = 247, - EnumDeclaration = 248, - ModuleDeclaration = 249, - ModuleBlock = 250, - CaseBlock = 251, - NamespaceExportDeclaration = 252, - ImportEqualsDeclaration = 253, - ImportDeclaration = 254, - ImportClause = 255, - NamespaceImport = 256, - NamedImports = 257, - ImportSpecifier = 258, - ExportAssignment = 259, - ExportDeclaration = 260, - NamedExports = 261, - NamespaceExport = 262, - ExportSpecifier = 263, - MissingDeclaration = 264, - ExternalModuleReference = 265, - JsxElement = 266, - JsxSelfClosingElement = 267, - JsxOpeningElement = 268, - JsxClosingElement = 269, - JsxFragment = 270, - JsxOpeningFragment = 271, - JsxClosingFragment = 272, - JsxAttribute = 273, - JsxAttributes = 274, - JsxSpreadAttribute = 275, - JsxExpression = 276, - CaseClause = 277, - DefaultClause = 278, - HeritageClause = 279, - CatchClause = 280, - PropertyAssignment = 281, - ShorthandPropertyAssignment = 282, - SpreadAssignment = 283, - EnumMember = 284, - UnparsedPrologue = 285, - UnparsedPrepend = 286, - UnparsedText = 287, - UnparsedInternalText = 288, - UnparsedSyntheticReference = 289, - SourceFile = 290, - Bundle = 291, - UnparsedSource = 292, - InputFiles = 293, - JSDocTypeExpression = 294, - JSDocAllType = 295, - JSDocUnknownType = 296, - JSDocNullableType = 297, - JSDocNonNullableType = 298, - JSDocOptionalType = 299, - JSDocFunctionType = 300, - JSDocVariadicType = 301, - JSDocNamepathType = 302, - JSDocComment = 303, - JSDocTypeLiteral = 304, - JSDocSignature = 305, - JSDocTag = 306, - JSDocAugmentsTag = 307, - JSDocImplementsTag = 308, - JSDocAuthorTag = 309, - JSDocClassTag = 310, - JSDocPublicTag = 311, - JSDocPrivateTag = 312, - JSDocProtectedTag = 313, - JSDocReadonlyTag = 314, - JSDocCallbackTag = 315, - JSDocEnumTag = 316, - JSDocParameterTag = 317, - JSDocReturnTag = 318, - JSDocThisTag = 319, - JSDocTypeTag = 320, - JSDocTemplateTag = 321, - JSDocTypedefTag = 322, - JSDocPropertyTag = 323, - SyntaxList = 324, - NotEmittedStatement = 325, - PartiallyEmittedExpression = 326, - CommaListExpression = 327, - MergeDeclarationMarker = 328, - EndOfDeclarationMarker = 329, - SyntheticReferenceExpression = 330, - Count = 331, + BarBarEqualsToken = 74, + AmpersandAmpersandEqualsToken = 75, + QuestionQuestionEqualsToken = 76, + CaretEqualsToken = 77, + Identifier = 78, + PrivateIdentifier = 79, + BreakKeyword = 80, + CaseKeyword = 81, + CatchKeyword = 82, + ClassKeyword = 83, + ConstKeyword = 84, + ContinueKeyword = 85, + DebuggerKeyword = 86, + DefaultKeyword = 87, + DeleteKeyword = 88, + DoKeyword = 89, + ElseKeyword = 90, + EnumKeyword = 91, + ExportKeyword = 92, + ExtendsKeyword = 93, + FalseKeyword = 94, + FinallyKeyword = 95, + ForKeyword = 96, + FunctionKeyword = 97, + IfKeyword = 98, + ImportKeyword = 99, + InKeyword = 100, + InstanceOfKeyword = 101, + NewKeyword = 102, + NullKeyword = 103, + ReturnKeyword = 104, + SuperKeyword = 105, + SwitchKeyword = 106, + ThisKeyword = 107, + ThrowKeyword = 108, + TrueKeyword = 109, + TryKeyword = 110, + TypeOfKeyword = 111, + VarKeyword = 112, + VoidKeyword = 113, + WhileKeyword = 114, + WithKeyword = 115, + ImplementsKeyword = 116, + InterfaceKeyword = 117, + LetKeyword = 118, + PackageKeyword = 119, + PrivateKeyword = 120, + ProtectedKeyword = 121, + PublicKeyword = 122, + StaticKeyword = 123, + YieldKeyword = 124, + AbstractKeyword = 125, + AsKeyword = 126, + AssertsKeyword = 127, + AnyKeyword = 128, + AsyncKeyword = 129, + AwaitKeyword = 130, + BooleanKeyword = 131, + ConstructorKeyword = 132, + DeclareKeyword = 133, + GetKeyword = 134, + InferKeyword = 135, + IsKeyword = 136, + KeyOfKeyword = 137, + ModuleKeyword = 138, + NamespaceKeyword = 139, + NeverKeyword = 140, + ReadonlyKeyword = 141, + RequireKeyword = 142, + NumberKeyword = 143, + ObjectKeyword = 144, + SetKeyword = 145, + StringKeyword = 146, + SymbolKeyword = 147, + TypeKeyword = 148, + UndefinedKeyword = 149, + UniqueKeyword = 150, + UnknownKeyword = 151, + FromKeyword = 152, + GlobalKeyword = 153, + BigIntKeyword = 154, + OfKeyword = 155, + QualifiedName = 156, + ComputedPropertyName = 157, + TypeParameter = 158, + Parameter = 159, + Decorator = 160, + PropertySignature = 161, + PropertyDeclaration = 162, + MethodSignature = 163, + MethodDeclaration = 164, + Constructor = 165, + GetAccessor = 166, + SetAccessor = 167, + CallSignature = 168, + ConstructSignature = 169, + IndexSignature = 170, + TypePredicate = 171, + TypeReference = 172, + FunctionType = 173, + ConstructorType = 174, + TypeQuery = 175, + TypeLiteral = 176, + ArrayType = 177, + TupleType = 178, + OptionalType = 179, + RestType = 180, + UnionType = 181, + IntersectionType = 182, + ConditionalType = 183, + InferType = 184, + ParenthesizedType = 185, + ThisType = 186, + TypeOperator = 187, + IndexedAccessType = 188, + MappedType = 189, + LiteralType = 190, + ImportType = 191, + ObjectBindingPattern = 192, + ArrayBindingPattern = 193, + BindingElement = 194, + ArrayLiteralExpression = 195, + ObjectLiteralExpression = 196, + PropertyAccessExpression = 197, + ElementAccessExpression = 198, + CallExpression = 199, + NewExpression = 200, + TaggedTemplateExpression = 201, + TypeAssertionExpression = 202, + ParenthesizedExpression = 203, + FunctionExpression = 204, + ArrowFunction = 205, + DeleteExpression = 206, + TypeOfExpression = 207, + VoidExpression = 208, + AwaitExpression = 209, + PrefixUnaryExpression = 210, + PostfixUnaryExpression = 211, + BinaryExpression = 212, + ConditionalExpression = 213, + TemplateExpression = 214, + YieldExpression = 215, + SpreadElement = 216, + ClassExpression = 217, + OmittedExpression = 218, + ExpressionWithTypeArguments = 219, + AsExpression = 220, + NonNullExpression = 221, + MetaProperty = 222, + SyntheticExpression = 223, + TemplateSpan = 224, + SemicolonClassElement = 225, + Block = 226, + EmptyStatement = 227, + VariableStatement = 228, + ExpressionStatement = 229, + IfStatement = 230, + DoStatement = 231, + WhileStatement = 232, + ForStatement = 233, + ForInStatement = 234, + ForOfStatement = 235, + ContinueStatement = 236, + BreakStatement = 237, + ReturnStatement = 238, + WithStatement = 239, + SwitchStatement = 240, + LabeledStatement = 241, + ThrowStatement = 242, + TryStatement = 243, + DebuggerStatement = 244, + VariableDeclaration = 245, + VariableDeclarationList = 246, + FunctionDeclaration = 247, + ClassDeclaration = 248, + InterfaceDeclaration = 249, + TypeAliasDeclaration = 250, + EnumDeclaration = 251, + ModuleDeclaration = 252, + ModuleBlock = 253, + CaseBlock = 254, + NamespaceExportDeclaration = 255, + ImportEqualsDeclaration = 256, + ImportDeclaration = 257, + ImportClause = 258, + NamespaceImport = 259, + NamedImports = 260, + ImportSpecifier = 261, + ExportAssignment = 262, + ExportDeclaration = 263, + NamedExports = 264, + NamespaceExport = 265, + ExportSpecifier = 266, + MissingDeclaration = 267, + ExternalModuleReference = 268, + JsxElement = 269, + JsxSelfClosingElement = 270, + JsxOpeningElement = 271, + JsxClosingElement = 272, + JsxFragment = 273, + JsxOpeningFragment = 274, + JsxClosingFragment = 275, + JsxAttribute = 276, + JsxAttributes = 277, + JsxSpreadAttribute = 278, + JsxExpression = 279, + CaseClause = 280, + DefaultClause = 281, + HeritageClause = 282, + CatchClause = 283, + PropertyAssignment = 284, + ShorthandPropertyAssignment = 285, + SpreadAssignment = 286, + EnumMember = 287, + UnparsedPrologue = 288, + UnparsedPrepend = 289, + UnparsedText = 290, + UnparsedInternalText = 291, + UnparsedSyntheticReference = 292, + SourceFile = 293, + Bundle = 294, + UnparsedSource = 295, + InputFiles = 296, + JSDocTypeExpression = 297, + JSDocAllType = 298, + JSDocUnknownType = 299, + JSDocNullableType = 300, + JSDocNonNullableType = 301, + JSDocOptionalType = 302, + JSDocFunctionType = 303, + JSDocVariadicType = 304, + JSDocNamepathType = 305, + JSDocComment = 306, + JSDocTypeLiteral = 307, + JSDocSignature = 308, + JSDocTag = 309, + JSDocAugmentsTag = 310, + JSDocImplementsTag = 311, + JSDocAuthorTag = 312, + JSDocClassTag = 313, + JSDocPublicTag = 314, + JSDocPrivateTag = 315, + JSDocProtectedTag = 316, + JSDocReadonlyTag = 317, + JSDocCallbackTag = 318, + JSDocEnumTag = 319, + JSDocParameterTag = 320, + JSDocReturnTag = 321, + JSDocThisTag = 322, + JSDocTypeTag = 323, + JSDocTemplateTag = 324, + JSDocTypedefTag = 325, + JSDocPropertyTag = 326, + SyntaxList = 327, + NotEmittedStatement = 328, + PartiallyEmittedExpression = 329, + CommaListExpression = 330, + MergeDeclarationMarker = 331, + EndOfDeclarationMarker = 332, + SyntheticReferenceExpression = 333, + Count = 334, FirstAssignment = 62, - LastAssignment = 74, + LastAssignment = 77, FirstCompoundAssignment = 63, - LastCompoundAssignment = 74, - FirstReservedWord = 77, - LastReservedWord = 112, - FirstKeyword = 77, - LastKeyword = 152, - FirstFutureReservedWord = 113, - LastFutureReservedWord = 121, - FirstTypeNode = 168, - LastTypeNode = 188, + LastCompoundAssignment = 77, + FirstReservedWord = 80, + LastReservedWord = 115, + FirstKeyword = 80, + LastKeyword = 155, + FirstFutureReservedWord = 116, + LastFutureReservedWord = 124, + FirstTypeNode = 171, + LastTypeNode = 191, FirstPunctuation = 18, - LastPunctuation = 74, + LastPunctuation = 77, FirstToken = 0, - LastToken = 152, + LastToken = 155, FirstTriviaToken = 2, LastTriviaToken = 7, FirstLiteralToken = 8, @@ -430,14 +433,14 @@ declare namespace ts { FirstTemplateToken = 14, LastTemplateToken = 17, FirstBinaryOperator = 29, - LastBinaryOperator = 74, - FirstStatement = 225, - LastStatement = 241, - FirstNode = 153, - FirstJSDocNode = 294, - LastJSDocNode = 323, - FirstJSDocTagNode = 306, - LastJSDocTagNode = 323, + LastBinaryOperator = 77, + FirstStatement = 228, + LastStatement = 244, + FirstNode = 156, + FirstJSDocNode = 297, + LastJSDocNode = 326, + FirstJSDocTagNode = 309, + LastJSDocTagNode = 326, } export enum NodeFlags { None = 0, @@ -963,7 +966,7 @@ declare namespace ts { export type BitwiseOperatorOrHigher = EqualityOperatorOrHigher | BitwiseOperator; export type LogicalOperator = SyntaxKind.AmpersandAmpersandToken | SyntaxKind.BarBarToken; export type LogicalOperatorOrHigher = BitwiseOperatorOrHigher | LogicalOperator; - export type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken; + export type CompoundAssignmentOperator = SyntaxKind.PlusEqualsToken | SyntaxKind.MinusEqualsToken | SyntaxKind.AsteriskAsteriskEqualsToken | SyntaxKind.AsteriskEqualsToken | SyntaxKind.SlashEqualsToken | SyntaxKind.PercentEqualsToken | SyntaxKind.AmpersandEqualsToken | SyntaxKind.BarEqualsToken | SyntaxKind.CaretEqualsToken | SyntaxKind.LessThanLessThanEqualsToken | SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken | SyntaxKind.GreaterThanGreaterThanEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; export type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; export type AssignmentOperatorOrHigher = SyntaxKind.QuestionQuestionToken | LogicalOperatorOrHigher | AssignmentOperator; export type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; diff --git a/tests/baselines/reference/logicalAssignment1(target=es2015).js b/tests/baselines/reference/logicalAssignment1(target=es2015).js new file mode 100644 index 0000000000000..db6e540789a5e --- /dev/null +++ b/tests/baselines/reference/logicalAssignment1(target=es2015).js @@ -0,0 +1,39 @@ +//// [logicalAssignment1.ts] +declare let a: string | undefined +declare let b: string | undefined +declare let c: string | undefined + +declare let d: number | undefined +declare let e: number | undefined +declare let f: number | undefined + +declare let g: 0 | 1 | 42 +declare let h: 0 | 1 | 42 +declare let i: 0 | 1 | 42 + + +a &&= "foo" +b ||= "foo" +c ??= "foo" + + +d &&= 42 +e ||= 42 +f ??= 42 + +g &&= 42 +h ||= 42 +i ??= 42 + + +//// [logicalAssignment1.js] +"use strict"; +a && (a = "foo"); +b || (b = "foo"); +c !== null && c !== void 0 ? c : (c = "foo"); +d && (d = 42); +e || (e = 42); +f !== null && f !== void 0 ? f : (f = 42); +g && (g = 42); +h || (h = 42); +i !== null && i !== void 0 ? i : (i = 42); diff --git a/tests/baselines/reference/logicalAssignment1(target=es2015).symbols b/tests/baselines/reference/logicalAssignment1(target=es2015).symbols new file mode 100644 index 0000000000000..5705fc2d1042a --- /dev/null +++ b/tests/baselines/reference/logicalAssignment1(target=es2015).symbols @@ -0,0 +1,57 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts === +declare let a: string | undefined +>a : Symbol(a, Decl(logicalAssignment1.ts, 0, 11)) + +declare let b: string | undefined +>b : Symbol(b, Decl(logicalAssignment1.ts, 1, 11)) + +declare let c: string | undefined +>c : Symbol(c, Decl(logicalAssignment1.ts, 2, 11)) + +declare let d: number | undefined +>d : Symbol(d, Decl(logicalAssignment1.ts, 4, 11)) + +declare let e: number | undefined +>e : Symbol(e, Decl(logicalAssignment1.ts, 5, 11)) + +declare let f: number | undefined +>f : Symbol(f, Decl(logicalAssignment1.ts, 6, 11)) + +declare let g: 0 | 1 | 42 +>g : Symbol(g, Decl(logicalAssignment1.ts, 8, 11)) + +declare let h: 0 | 1 | 42 +>h : Symbol(h, Decl(logicalAssignment1.ts, 9, 11)) + +declare let i: 0 | 1 | 42 +>i : Symbol(i, Decl(logicalAssignment1.ts, 10, 11)) + + +a &&= "foo" +>a : Symbol(a, Decl(logicalAssignment1.ts, 0, 11)) + +b ||= "foo" +>b : Symbol(b, Decl(logicalAssignment1.ts, 1, 11)) + +c ??= "foo" +>c : Symbol(c, Decl(logicalAssignment1.ts, 2, 11)) + + +d &&= 42 +>d : Symbol(d, Decl(logicalAssignment1.ts, 4, 11)) + +e ||= 42 +>e : Symbol(e, Decl(logicalAssignment1.ts, 5, 11)) + +f ??= 42 +>f : Symbol(f, Decl(logicalAssignment1.ts, 6, 11)) + +g &&= 42 +>g : Symbol(g, Decl(logicalAssignment1.ts, 8, 11)) + +h ||= 42 +>h : Symbol(h, Decl(logicalAssignment1.ts, 9, 11)) + +i ??= 42 +>i : Symbol(i, Decl(logicalAssignment1.ts, 10, 11)) + diff --git a/tests/baselines/reference/logicalAssignment1(target=es2015).types b/tests/baselines/reference/logicalAssignment1(target=es2015).types new file mode 100644 index 0000000000000..98bae7b837cfc --- /dev/null +++ b/tests/baselines/reference/logicalAssignment1(target=es2015).types @@ -0,0 +1,75 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts === +declare let a: string | undefined +>a : string | undefined + +declare let b: string | undefined +>b : string | undefined + +declare let c: string | undefined +>c : string | undefined + +declare let d: number | undefined +>d : number | undefined + +declare let e: number | undefined +>e : number | undefined + +declare let f: number | undefined +>f : number | undefined + +declare let g: 0 | 1 | 42 +>g : 0 | 1 | 42 + +declare let h: 0 | 1 | 42 +>h : 0 | 1 | 42 + +declare let i: 0 | 1 | 42 +>i : 0 | 1 | 42 + + +a &&= "foo" +>a &&= "foo" : "" | "foo" | undefined +>a : string | undefined +>"foo" : "foo" + +b ||= "foo" +>b ||= "foo" : string +>b : string | undefined +>"foo" : "foo" + +c ??= "foo" +>c ??= "foo" : string +>c : string | undefined +>"foo" : "foo" + + +d &&= 42 +>d &&= 42 : 0 | 42 | undefined +>d : number | undefined +>42 : 42 + +e ||= 42 +>e ||= 42 : number +>e : number | undefined +>42 : 42 + +f ??= 42 +>f ??= 42 : number +>f : number | undefined +>42 : 42 + +g &&= 42 +>g &&= 42 : 0 | 42 +>g : number +>42 : 42 + +h ||= 42 +>h ||= 42 : number +>h : number +>42 : 42 + +i ??= 42 +>i ??= 42 : number +>i : number +>42 : 42 + diff --git a/tests/baselines/reference/logicalAssignment1(target=es2020).js b/tests/baselines/reference/logicalAssignment1(target=es2020).js new file mode 100644 index 0000000000000..dd527ab2139d8 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment1(target=es2020).js @@ -0,0 +1,39 @@ +//// [logicalAssignment1.ts] +declare let a: string | undefined +declare let b: string | undefined +declare let c: string | undefined + +declare let d: number | undefined +declare let e: number | undefined +declare let f: number | undefined + +declare let g: 0 | 1 | 42 +declare let h: 0 | 1 | 42 +declare let i: 0 | 1 | 42 + + +a &&= "foo" +b ||= "foo" +c ??= "foo" + + +d &&= 42 +e ||= 42 +f ??= 42 + +g &&= 42 +h ||= 42 +i ??= 42 + + +//// [logicalAssignment1.js] +"use strict"; +a && (a = "foo"); +b || (b = "foo"); +c ?? (c = "foo"); +d && (d = 42); +e || (e = 42); +f ?? (f = 42); +g && (g = 42); +h || (h = 42); +i ?? (i = 42); diff --git a/tests/baselines/reference/logicalAssignment1(target=es2020).symbols b/tests/baselines/reference/logicalAssignment1(target=es2020).symbols new file mode 100644 index 0000000000000..5705fc2d1042a --- /dev/null +++ b/tests/baselines/reference/logicalAssignment1(target=es2020).symbols @@ -0,0 +1,57 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts === +declare let a: string | undefined +>a : Symbol(a, Decl(logicalAssignment1.ts, 0, 11)) + +declare let b: string | undefined +>b : Symbol(b, Decl(logicalAssignment1.ts, 1, 11)) + +declare let c: string | undefined +>c : Symbol(c, Decl(logicalAssignment1.ts, 2, 11)) + +declare let d: number | undefined +>d : Symbol(d, Decl(logicalAssignment1.ts, 4, 11)) + +declare let e: number | undefined +>e : Symbol(e, Decl(logicalAssignment1.ts, 5, 11)) + +declare let f: number | undefined +>f : Symbol(f, Decl(logicalAssignment1.ts, 6, 11)) + +declare let g: 0 | 1 | 42 +>g : Symbol(g, Decl(logicalAssignment1.ts, 8, 11)) + +declare let h: 0 | 1 | 42 +>h : Symbol(h, Decl(logicalAssignment1.ts, 9, 11)) + +declare let i: 0 | 1 | 42 +>i : Symbol(i, Decl(logicalAssignment1.ts, 10, 11)) + + +a &&= "foo" +>a : Symbol(a, Decl(logicalAssignment1.ts, 0, 11)) + +b ||= "foo" +>b : Symbol(b, Decl(logicalAssignment1.ts, 1, 11)) + +c ??= "foo" +>c : Symbol(c, Decl(logicalAssignment1.ts, 2, 11)) + + +d &&= 42 +>d : Symbol(d, Decl(logicalAssignment1.ts, 4, 11)) + +e ||= 42 +>e : Symbol(e, Decl(logicalAssignment1.ts, 5, 11)) + +f ??= 42 +>f : Symbol(f, Decl(logicalAssignment1.ts, 6, 11)) + +g &&= 42 +>g : Symbol(g, Decl(logicalAssignment1.ts, 8, 11)) + +h ||= 42 +>h : Symbol(h, Decl(logicalAssignment1.ts, 9, 11)) + +i ??= 42 +>i : Symbol(i, Decl(logicalAssignment1.ts, 10, 11)) + diff --git a/tests/baselines/reference/logicalAssignment1(target=es2020).types b/tests/baselines/reference/logicalAssignment1(target=es2020).types new file mode 100644 index 0000000000000..98bae7b837cfc --- /dev/null +++ b/tests/baselines/reference/logicalAssignment1(target=es2020).types @@ -0,0 +1,75 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts === +declare let a: string | undefined +>a : string | undefined + +declare let b: string | undefined +>b : string | undefined + +declare let c: string | undefined +>c : string | undefined + +declare let d: number | undefined +>d : number | undefined + +declare let e: number | undefined +>e : number | undefined + +declare let f: number | undefined +>f : number | undefined + +declare let g: 0 | 1 | 42 +>g : 0 | 1 | 42 + +declare let h: 0 | 1 | 42 +>h : 0 | 1 | 42 + +declare let i: 0 | 1 | 42 +>i : 0 | 1 | 42 + + +a &&= "foo" +>a &&= "foo" : "" | "foo" | undefined +>a : string | undefined +>"foo" : "foo" + +b ||= "foo" +>b ||= "foo" : string +>b : string | undefined +>"foo" : "foo" + +c ??= "foo" +>c ??= "foo" : string +>c : string | undefined +>"foo" : "foo" + + +d &&= 42 +>d &&= 42 : 0 | 42 | undefined +>d : number | undefined +>42 : 42 + +e ||= 42 +>e ||= 42 : number +>e : number | undefined +>42 : 42 + +f ??= 42 +>f ??= 42 : number +>f : number | undefined +>42 : 42 + +g &&= 42 +>g &&= 42 : 0 | 42 +>g : number +>42 : 42 + +h ||= 42 +>h ||= 42 : number +>h : number +>42 : 42 + +i ??= 42 +>i ??= 42 : number +>i : number +>42 : 42 + diff --git a/tests/baselines/reference/logicalAssignment1(target=esnext).js b/tests/baselines/reference/logicalAssignment1(target=esnext).js new file mode 100644 index 0000000000000..4adf005014e39 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment1(target=esnext).js @@ -0,0 +1,39 @@ +//// [logicalAssignment1.ts] +declare let a: string | undefined +declare let b: string | undefined +declare let c: string | undefined + +declare let d: number | undefined +declare let e: number | undefined +declare let f: number | undefined + +declare let g: 0 | 1 | 42 +declare let h: 0 | 1 | 42 +declare let i: 0 | 1 | 42 + + +a &&= "foo" +b ||= "foo" +c ??= "foo" + + +d &&= 42 +e ||= 42 +f ??= 42 + +g &&= 42 +h ||= 42 +i ??= 42 + + +//// [logicalAssignment1.js] +"use strict"; +a &&= "foo"; +b ||= "foo"; +c ??= "foo"; +d &&= 42; +e ||= 42; +f ??= 42; +g &&= 42; +h ||= 42; +i ??= 42; diff --git a/tests/baselines/reference/logicalAssignment1(target=esnext).symbols b/tests/baselines/reference/logicalAssignment1(target=esnext).symbols new file mode 100644 index 0000000000000..5705fc2d1042a --- /dev/null +++ b/tests/baselines/reference/logicalAssignment1(target=esnext).symbols @@ -0,0 +1,57 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts === +declare let a: string | undefined +>a : Symbol(a, Decl(logicalAssignment1.ts, 0, 11)) + +declare let b: string | undefined +>b : Symbol(b, Decl(logicalAssignment1.ts, 1, 11)) + +declare let c: string | undefined +>c : Symbol(c, Decl(logicalAssignment1.ts, 2, 11)) + +declare let d: number | undefined +>d : Symbol(d, Decl(logicalAssignment1.ts, 4, 11)) + +declare let e: number | undefined +>e : Symbol(e, Decl(logicalAssignment1.ts, 5, 11)) + +declare let f: number | undefined +>f : Symbol(f, Decl(logicalAssignment1.ts, 6, 11)) + +declare let g: 0 | 1 | 42 +>g : Symbol(g, Decl(logicalAssignment1.ts, 8, 11)) + +declare let h: 0 | 1 | 42 +>h : Symbol(h, Decl(logicalAssignment1.ts, 9, 11)) + +declare let i: 0 | 1 | 42 +>i : Symbol(i, Decl(logicalAssignment1.ts, 10, 11)) + + +a &&= "foo" +>a : Symbol(a, Decl(logicalAssignment1.ts, 0, 11)) + +b ||= "foo" +>b : Symbol(b, Decl(logicalAssignment1.ts, 1, 11)) + +c ??= "foo" +>c : Symbol(c, Decl(logicalAssignment1.ts, 2, 11)) + + +d &&= 42 +>d : Symbol(d, Decl(logicalAssignment1.ts, 4, 11)) + +e ||= 42 +>e : Symbol(e, Decl(logicalAssignment1.ts, 5, 11)) + +f ??= 42 +>f : Symbol(f, Decl(logicalAssignment1.ts, 6, 11)) + +g &&= 42 +>g : Symbol(g, Decl(logicalAssignment1.ts, 8, 11)) + +h ||= 42 +>h : Symbol(h, Decl(logicalAssignment1.ts, 9, 11)) + +i ??= 42 +>i : Symbol(i, Decl(logicalAssignment1.ts, 10, 11)) + diff --git a/tests/baselines/reference/logicalAssignment1(target=esnext).types b/tests/baselines/reference/logicalAssignment1(target=esnext).types new file mode 100644 index 0000000000000..98bae7b837cfc --- /dev/null +++ b/tests/baselines/reference/logicalAssignment1(target=esnext).types @@ -0,0 +1,75 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts === +declare let a: string | undefined +>a : string | undefined + +declare let b: string | undefined +>b : string | undefined + +declare let c: string | undefined +>c : string | undefined + +declare let d: number | undefined +>d : number | undefined + +declare let e: number | undefined +>e : number | undefined + +declare let f: number | undefined +>f : number | undefined + +declare let g: 0 | 1 | 42 +>g : 0 | 1 | 42 + +declare let h: 0 | 1 | 42 +>h : 0 | 1 | 42 + +declare let i: 0 | 1 | 42 +>i : 0 | 1 | 42 + + +a &&= "foo" +>a &&= "foo" : "" | "foo" | undefined +>a : string | undefined +>"foo" : "foo" + +b ||= "foo" +>b ||= "foo" : string +>b : string | undefined +>"foo" : "foo" + +c ??= "foo" +>c ??= "foo" : string +>c : string | undefined +>"foo" : "foo" + + +d &&= 42 +>d &&= 42 : 0 | 42 | undefined +>d : number | undefined +>42 : 42 + +e ||= 42 +>e ||= 42 : number +>e : number | undefined +>42 : 42 + +f ??= 42 +>f ??= 42 : number +>f : number | undefined +>42 : 42 + +g &&= 42 +>g &&= 42 : 0 | 42 +>g : number +>42 : 42 + +h ||= 42 +>h ||= 42 : number +>h : number +>42 : 42 + +i ??= 42 +>i ??= 42 : number +>i : number +>42 : 42 + diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts new file mode 100644 index 0000000000000..cb1b51369e6d3 --- /dev/null +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment1.ts @@ -0,0 +1,27 @@ +// @strict: true +// @target: esnext, es2020, es2015 +declare let a: string | undefined +declare let b: string | undefined +declare let c: string | undefined + +declare let d: number | undefined +declare let e: number | undefined +declare let f: number | undefined + +declare let g: 0 | 1 | 42 +declare let h: 0 | 1 | 42 +declare let i: 0 | 1 | 42 + + +a &&= "foo" +b ||= "foo" +c ??= "foo" + + +d &&= 42 +e ||= 42 +f ??= 42 + +g &&= 42 +h ||= 42 +i ??= 42 From da16b3e30beeeb0601c120f66ed75fe26f496375 Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 1 Apr 2020 11:37:58 +0800 Subject: [PATCH 02/24] Add more case --- src/compiler/transformers/esnext.ts | 11 +- .../logicalAssignment2(target=es2015).js | 42 +++++ .../logicalAssignment2(target=es2015).symbols | 142 ++++++++++++++++ .../logicalAssignment2(target=es2015).types | 154 ++++++++++++++++++ .../logicalAssignment2(target=es2020).js | 41 +++++ .../logicalAssignment2(target=es2020).symbols | 142 ++++++++++++++++ .../logicalAssignment2(target=es2020).types | 154 ++++++++++++++++++ .../logicalAssignment2(target=esnext).js | 41 +++++ .../logicalAssignment2(target=esnext).symbols | 142 ++++++++++++++++ .../logicalAssignment2(target=esnext).types | 154 ++++++++++++++++++ .../logicalAssignment3(target=es2015).js | 22 +++ .../logicalAssignment3(target=es2015).symbols | 49 ++++++ .../logicalAssignment3(target=es2015).types | 49 ++++++ .../logicalAssignment3(target=es2020).js | 21 +++ .../logicalAssignment3(target=es2020).symbols | 49 ++++++ .../logicalAssignment3(target=es2020).types | 49 ++++++ .../logicalAssignment3(target=esnext).js | 21 +++ .../logicalAssignment3(target=esnext).symbols | 49 ++++++ .../logicalAssignment3(target=esnext).types | 49 ++++++ .../logicalAssignment4(target=es2015).js | 17 ++ .../logicalAssignment4(target=es2015).symbols | 20 +++ .../logicalAssignment4(target=es2015).types | 30 ++++ .../logicalAssignment4(target=es2020).js | 17 ++ .../logicalAssignment4(target=es2020).symbols | 20 +++ .../logicalAssignment4(target=es2020).types | 30 ++++ .../logicalAssignment4(target=esnext).js | 17 ++ .../logicalAssignment4(target=esnext).symbols | 20 +++ .../logicalAssignment4(target=esnext).types | 30 ++++ .../logicalAssignment/logicalAssignment2.ts | 29 ++++ .../logicalAssignment/logicalAssignment3.ts | 15 ++ .../logicalAssignment/logicalAssignment4.ts | 10 ++ 31 files changed, 1626 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/logicalAssignment2(target=es2015).js create mode 100644 tests/baselines/reference/logicalAssignment2(target=es2015).symbols create mode 100644 tests/baselines/reference/logicalAssignment2(target=es2015).types create mode 100644 tests/baselines/reference/logicalAssignment2(target=es2020).js create mode 100644 tests/baselines/reference/logicalAssignment2(target=es2020).symbols create mode 100644 tests/baselines/reference/logicalAssignment2(target=es2020).types create mode 100644 tests/baselines/reference/logicalAssignment2(target=esnext).js create mode 100644 tests/baselines/reference/logicalAssignment2(target=esnext).symbols create mode 100644 tests/baselines/reference/logicalAssignment2(target=esnext).types create mode 100644 tests/baselines/reference/logicalAssignment3(target=es2015).js create mode 100644 tests/baselines/reference/logicalAssignment3(target=es2015).symbols create mode 100644 tests/baselines/reference/logicalAssignment3(target=es2015).types create mode 100644 tests/baselines/reference/logicalAssignment3(target=es2020).js create mode 100644 tests/baselines/reference/logicalAssignment3(target=es2020).symbols create mode 100644 tests/baselines/reference/logicalAssignment3(target=es2020).types create mode 100644 tests/baselines/reference/logicalAssignment3(target=esnext).js create mode 100644 tests/baselines/reference/logicalAssignment3(target=esnext).symbols create mode 100644 tests/baselines/reference/logicalAssignment3(target=esnext).types create mode 100644 tests/baselines/reference/logicalAssignment4(target=es2015).js create mode 100644 tests/baselines/reference/logicalAssignment4(target=es2015).symbols create mode 100644 tests/baselines/reference/logicalAssignment4(target=es2015).types create mode 100644 tests/baselines/reference/logicalAssignment4(target=es2020).js create mode 100644 tests/baselines/reference/logicalAssignment4(target=es2020).symbols create mode 100644 tests/baselines/reference/logicalAssignment4(target=es2020).types create mode 100644 tests/baselines/reference/logicalAssignment4(target=esnext).js create mode 100644 tests/baselines/reference/logicalAssignment4(target=esnext).symbols create mode 100644 tests/baselines/reference/logicalAssignment4(target=esnext).types create mode 100644 tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts create mode 100644 tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts create mode 100644 tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 96c0e0178a7b9..8004e7bc4ded5 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) { @@ -37,14 +33,9 @@ namespace ts { const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); const left = visitNode(binaryExpression.left, visitor, isExpression); const right = visitNode(binaryExpression.right, visitor, isExpression); - let cond = left; - if (shouldCaptureInTempVariable(left)) { - const temp = createTempVariable(hoistVariableDeclaration); - cond = createAssignment(temp, left); - } return createBinary( - cond, + left, nonAssignmentOperator, createParen( createAssignment( diff --git a/tests/baselines/reference/logicalAssignment2(target=es2015).js b/tests/baselines/reference/logicalAssignment2(target=es2015).js new file mode 100644 index 0000000000000..f07da1575f23c --- /dev/null +++ b/tests/baselines/reference/logicalAssignment2(target=es2015).js @@ -0,0 +1,42 @@ +//// [logicalAssignment2.ts] +interface A { + foo: { + bar(): { + baz: 0 | 1 | 42 | undefined | '' + } + baz: 0 | 1 | 42 | undefined | '' + } + baz: 0 | 1 | 42 | undefined | '' +} + +declare const result: A +declare const a: A +declare const b: A +declare const c: A + +a.baz &&= result.baz +b.baz ||= result.baz +c.baz ??= result.baz + +a.foo["baz"] &&= result.foo.baz +b.foo["baz"] &&= result.foo.baz +c.foo["baz"] &&= result.foo.baz + +a.foo.bar().baz &&= result.foo.bar().baz +b.foo.bar().baz ||= result.foo.bar().baz +c.foo.bar().baz ??= result.foo.bar().baz + + + +//// [logicalAssignment2.js] +"use strict"; +var _a, _b; +a.baz && (a.baz = result.baz); +b.baz || (b.baz = result.baz); +(_a = c.baz) !== null && _a !== void 0 ? _a : (c.baz = result.baz); +a.foo["baz"] && (a.foo["baz"] = result.foo.baz); +b.foo["baz"] && (b.foo["baz"] = result.foo.baz); +c.foo["baz"] && (c.foo["baz"] = result.foo.baz); +a.foo.bar().baz && (a.foo.bar().baz = result.foo.bar().baz); +b.foo.bar().baz || (b.foo.bar().baz = result.foo.bar().baz); +(_b = c.foo.bar().baz) !== null && _b !== void 0 ? _b : (c.foo.bar().baz = result.foo.bar().baz); diff --git a/tests/baselines/reference/logicalAssignment2(target=es2015).symbols b/tests/baselines/reference/logicalAssignment2(target=es2015).symbols new file mode 100644 index 0000000000000..7fe47ddad4009 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment2(target=es2015).symbols @@ -0,0 +1,142 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts === +interface A { +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + + foo: { +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) + + bar(): { +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) + + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + } + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + } + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +} + +declare const result: A +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +declare const a: A +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +declare const b: A +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +declare const c: A +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +a.baz &&= result.baz +>a.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) + +b.baz ||= result.baz +>b.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) + +c.baz ??= result.baz +>c.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) + +a.foo["baz"] &&= result.foo.baz +>a.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>"baz" : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo.baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + +b.foo["baz"] &&= result.foo.baz +>b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>"baz" : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo.baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + +c.foo["baz"] &&= result.foo.baz +>c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>"baz" : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo.baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + +a.foo.bar().baz &&= result.foo.bar().baz +>a.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>a.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>a.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + +b.foo.bar().baz ||= result.foo.bar().baz +>b.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>b.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + +c.foo.bar().baz ??= result.foo.bar().baz +>c.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>c.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + + diff --git a/tests/baselines/reference/logicalAssignment2(target=es2015).types b/tests/baselines/reference/logicalAssignment2(target=es2015).types new file mode 100644 index 0000000000000..e0940ed680600 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment2(target=es2015).types @@ -0,0 +1,154 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts === +interface A { + foo: { +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } + + bar(): { +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } + + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined + } + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined + } + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined +} + +declare const result: A +>result : A + +declare const a: A +>a : A + +declare const b: A +>b : A + +declare const c: A +>c : A + +a.baz &&= result.baz +>a.baz &&= result.baz : "" | 0 | 1 | 42 | undefined +>a.baz : string | number | undefined +>a : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +b.baz ||= result.baz +>b.baz ||= result.baz : string | number | undefined +>b.baz : string | number | undefined +>b : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +c.baz ??= result.baz +>c.baz ??= result.baz : string | number | undefined +>c.baz : string | number | undefined +>c : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +a.foo["baz"] &&= result.foo.baz +>a.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +>a.foo["baz"] : string | number | undefined +>a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>a : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>"baz" : "baz" +>result.foo.baz : "" | 0 | 1 | 42 | undefined +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +b.foo["baz"] &&= result.foo.baz +>b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +>b.foo["baz"] : string | number | undefined +>b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>b : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>"baz" : "baz" +>result.foo.baz : "" | 0 | 1 | 42 | undefined +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +c.foo["baz"] &&= result.foo.baz +>c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +>c.foo["baz"] : string | number | undefined +>c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>c : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>"baz" : "baz" +>result.foo.baz : "" | 0 | 1 | 42 | undefined +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +a.foo.bar().baz &&= result.foo.bar().baz +>a.foo.bar().baz &&= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>a.foo.bar().baz : string | number | undefined +>a.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>a.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>a : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : string | number | undefined +>result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +b.foo.bar().baz ||= result.foo.bar().baz +>b.foo.bar().baz ||= result.foo.bar().baz : string | number | undefined +>b.foo.bar().baz : string | number | undefined +>b.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>b.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>b : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : string | number | undefined +>result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +c.foo.bar().baz ??= result.foo.bar().baz +>c.foo.bar().baz ??= result.foo.bar().baz : string | number | undefined +>c.foo.bar().baz : string | number | undefined +>c.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>c.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>c : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : string | number | undefined +>result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + + diff --git a/tests/baselines/reference/logicalAssignment2(target=es2020).js b/tests/baselines/reference/logicalAssignment2(target=es2020).js new file mode 100644 index 0000000000000..258de5d01e379 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment2(target=es2020).js @@ -0,0 +1,41 @@ +//// [logicalAssignment2.ts] +interface A { + foo: { + bar(): { + baz: 0 | 1 | 42 | undefined | '' + } + baz: 0 | 1 | 42 | undefined | '' + } + baz: 0 | 1 | 42 | undefined | '' +} + +declare const result: A +declare const a: A +declare const b: A +declare const c: A + +a.baz &&= result.baz +b.baz ||= result.baz +c.baz ??= result.baz + +a.foo["baz"] &&= result.foo.baz +b.foo["baz"] &&= result.foo.baz +c.foo["baz"] &&= result.foo.baz + +a.foo.bar().baz &&= result.foo.bar().baz +b.foo.bar().baz ||= result.foo.bar().baz +c.foo.bar().baz ??= result.foo.bar().baz + + + +//// [logicalAssignment2.js] +"use strict"; +a.baz && (a.baz = result.baz); +b.baz || (b.baz = result.baz); +c.baz ?? (c.baz = result.baz); +a.foo["baz"] && (a.foo["baz"] = result.foo.baz); +b.foo["baz"] && (b.foo["baz"] = result.foo.baz); +c.foo["baz"] && (c.foo["baz"] = result.foo.baz); +a.foo.bar().baz && (a.foo.bar().baz = result.foo.bar().baz); +b.foo.bar().baz || (b.foo.bar().baz = result.foo.bar().baz); +c.foo.bar().baz ?? (c.foo.bar().baz = result.foo.bar().baz); diff --git a/tests/baselines/reference/logicalAssignment2(target=es2020).symbols b/tests/baselines/reference/logicalAssignment2(target=es2020).symbols new file mode 100644 index 0000000000000..7fe47ddad4009 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment2(target=es2020).symbols @@ -0,0 +1,142 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts === +interface A { +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + + foo: { +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) + + bar(): { +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) + + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + } + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + } + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +} + +declare const result: A +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +declare const a: A +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +declare const b: A +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +declare const c: A +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +a.baz &&= result.baz +>a.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) + +b.baz ||= result.baz +>b.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) + +c.baz ??= result.baz +>c.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) + +a.foo["baz"] &&= result.foo.baz +>a.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>"baz" : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo.baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + +b.foo["baz"] &&= result.foo.baz +>b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>"baz" : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo.baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + +c.foo["baz"] &&= result.foo.baz +>c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>"baz" : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo.baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + +a.foo.bar().baz &&= result.foo.bar().baz +>a.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>a.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>a.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + +b.foo.bar().baz ||= result.foo.bar().baz +>b.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>b.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + +c.foo.bar().baz ??= result.foo.bar().baz +>c.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>c.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + + diff --git a/tests/baselines/reference/logicalAssignment2(target=es2020).types b/tests/baselines/reference/logicalAssignment2(target=es2020).types new file mode 100644 index 0000000000000..e0940ed680600 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment2(target=es2020).types @@ -0,0 +1,154 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts === +interface A { + foo: { +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } + + bar(): { +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } + + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined + } + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined + } + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined +} + +declare const result: A +>result : A + +declare const a: A +>a : A + +declare const b: A +>b : A + +declare const c: A +>c : A + +a.baz &&= result.baz +>a.baz &&= result.baz : "" | 0 | 1 | 42 | undefined +>a.baz : string | number | undefined +>a : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +b.baz ||= result.baz +>b.baz ||= result.baz : string | number | undefined +>b.baz : string | number | undefined +>b : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +c.baz ??= result.baz +>c.baz ??= result.baz : string | number | undefined +>c.baz : string | number | undefined +>c : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +a.foo["baz"] &&= result.foo.baz +>a.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +>a.foo["baz"] : string | number | undefined +>a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>a : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>"baz" : "baz" +>result.foo.baz : "" | 0 | 1 | 42 | undefined +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +b.foo["baz"] &&= result.foo.baz +>b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +>b.foo["baz"] : string | number | undefined +>b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>b : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>"baz" : "baz" +>result.foo.baz : "" | 0 | 1 | 42 | undefined +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +c.foo["baz"] &&= result.foo.baz +>c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +>c.foo["baz"] : string | number | undefined +>c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>c : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>"baz" : "baz" +>result.foo.baz : "" | 0 | 1 | 42 | undefined +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +a.foo.bar().baz &&= result.foo.bar().baz +>a.foo.bar().baz &&= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>a.foo.bar().baz : string | number | undefined +>a.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>a.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>a : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : string | number | undefined +>result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +b.foo.bar().baz ||= result.foo.bar().baz +>b.foo.bar().baz ||= result.foo.bar().baz : string | number | undefined +>b.foo.bar().baz : string | number | undefined +>b.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>b.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>b : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : string | number | undefined +>result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +c.foo.bar().baz ??= result.foo.bar().baz +>c.foo.bar().baz ??= result.foo.bar().baz : string | number | undefined +>c.foo.bar().baz : string | number | undefined +>c.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>c.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>c : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : string | number | undefined +>result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + + diff --git a/tests/baselines/reference/logicalAssignment2(target=esnext).js b/tests/baselines/reference/logicalAssignment2(target=esnext).js new file mode 100644 index 0000000000000..69b06e5a01dc2 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment2(target=esnext).js @@ -0,0 +1,41 @@ +//// [logicalAssignment2.ts] +interface A { + foo: { + bar(): { + baz: 0 | 1 | 42 | undefined | '' + } + baz: 0 | 1 | 42 | undefined | '' + } + baz: 0 | 1 | 42 | undefined | '' +} + +declare const result: A +declare const a: A +declare const b: A +declare const c: A + +a.baz &&= result.baz +b.baz ||= result.baz +c.baz ??= result.baz + +a.foo["baz"] &&= result.foo.baz +b.foo["baz"] &&= result.foo.baz +c.foo["baz"] &&= result.foo.baz + +a.foo.bar().baz &&= result.foo.bar().baz +b.foo.bar().baz ||= result.foo.bar().baz +c.foo.bar().baz ??= result.foo.bar().baz + + + +//// [logicalAssignment2.js] +"use strict"; +a.baz &&= result.baz; +b.baz ||= result.baz; +c.baz ??= result.baz; +a.foo["baz"] &&= result.foo.baz; +b.foo["baz"] &&= result.foo.baz; +c.foo["baz"] &&= result.foo.baz; +a.foo.bar().baz &&= result.foo.bar().baz; +b.foo.bar().baz ||= result.foo.bar().baz; +c.foo.bar().baz ??= result.foo.bar().baz; diff --git a/tests/baselines/reference/logicalAssignment2(target=esnext).symbols b/tests/baselines/reference/logicalAssignment2(target=esnext).symbols new file mode 100644 index 0000000000000..7fe47ddad4009 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment2(target=esnext).symbols @@ -0,0 +1,142 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts === +interface A { +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + + foo: { +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) + + bar(): { +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) + + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + } + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + } + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +} + +declare const result: A +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +declare const a: A +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +declare const b: A +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +declare const c: A +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>A : Symbol(A, Decl(logicalAssignment2.ts, 0, 0)) + +a.baz &&= result.baz +>a.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) + +b.baz ||= result.baz +>b.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) + +c.baz ??= result.baz +>c.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment2.ts, 6, 5)) + +a.foo["baz"] &&= result.foo.baz +>a.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>"baz" : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo.baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + +b.foo["baz"] &&= result.foo.baz +>b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>"baz" : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo.baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + +c.foo["baz"] &&= result.foo.baz +>c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>"baz" : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo.baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) + +a.foo.bar().baz &&= result.foo.bar().baz +>a.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>a.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>a.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>a : Symbol(a, Decl(logicalAssignment2.ts, 11, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + +b.foo.bar().baz ||= result.foo.bar().baz +>b.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>b.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + +c.foo.bar().baz ??= result.foo.bar().baz +>c.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>c.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar().baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) +>result.foo.bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>result.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment2.ts, 10, 13)) +>foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) +>bar : Symbol(bar, Decl(logicalAssignment2.ts, 1, 10)) +>baz : Symbol(baz, Decl(logicalAssignment2.ts, 2, 16)) + + diff --git a/tests/baselines/reference/logicalAssignment2(target=esnext).types b/tests/baselines/reference/logicalAssignment2(target=esnext).types new file mode 100644 index 0000000000000..e0940ed680600 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment2(target=esnext).types @@ -0,0 +1,154 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts === +interface A { + foo: { +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } + + bar(): { +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } + + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined + } + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined + } + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined +} + +declare const result: A +>result : A + +declare const a: A +>a : A + +declare const b: A +>b : A + +declare const c: A +>c : A + +a.baz &&= result.baz +>a.baz &&= result.baz : "" | 0 | 1 | 42 | undefined +>a.baz : string | number | undefined +>a : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +b.baz ||= result.baz +>b.baz ||= result.baz : string | number | undefined +>b.baz : string | number | undefined +>b : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +c.baz ??= result.baz +>c.baz ??= result.baz : string | number | undefined +>c.baz : string | number | undefined +>c : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +a.foo["baz"] &&= result.foo.baz +>a.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +>a.foo["baz"] : string | number | undefined +>a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>a : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>"baz" : "baz" +>result.foo.baz : "" | 0 | 1 | 42 | undefined +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +b.foo["baz"] &&= result.foo.baz +>b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +>b.foo["baz"] : string | number | undefined +>b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>b : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>"baz" : "baz" +>result.foo.baz : "" | 0 | 1 | 42 | undefined +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +c.foo["baz"] &&= result.foo.baz +>c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +>c.foo["baz"] : string | number | undefined +>c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>c : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>"baz" : "baz" +>result.foo.baz : "" | 0 | 1 | 42 | undefined +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +a.foo.bar().baz &&= result.foo.bar().baz +>a.foo.bar().baz &&= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>a.foo.bar().baz : string | number | undefined +>a.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>a.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>a : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : string | number | undefined +>result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +b.foo.bar().baz ||= result.foo.bar().baz +>b.foo.bar().baz ||= result.foo.bar().baz : string | number | undefined +>b.foo.bar().baz : string | number | undefined +>b.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>b.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>b : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : string | number | undefined +>result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + +c.foo.bar().baz ??= result.foo.bar().baz +>c.foo.bar().baz ??= result.foo.bar().baz : string | number | undefined +>c.foo.bar().baz : string | number | undefined +>c.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>c.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>c : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : string | number | undefined +>result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>result.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>result : A +>foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>baz : "" | 0 | 1 | 42 | undefined + + diff --git a/tests/baselines/reference/logicalAssignment3(target=es2015).js b/tests/baselines/reference/logicalAssignment3(target=es2015).js new file mode 100644 index 0000000000000..24012130a538a --- /dev/null +++ b/tests/baselines/reference/logicalAssignment3(target=es2015).js @@ -0,0 +1,22 @@ +//// [logicalAssignment3.ts] +interface A { + baz: 0 | 1 | 42 | undefined | '' +} + +declare const result: A; +declare const a: A; +declare const b: A; +declare const c: A; + +(a.baz) &&= result.baz; +(b.baz) ||= result.baz; +(c.baz) ??= result.baz; + + + +//// [logicalAssignment3.js] +"use strict"; +var _a; +(a.baz) && ((a.baz) = result.baz); +(b.baz) || ((b.baz) = result.baz); +(_a = (c.baz)) !== null && _a !== void 0 ? _a : ((c.baz) = result.baz); diff --git a/tests/baselines/reference/logicalAssignment3(target=es2015).symbols b/tests/baselines/reference/logicalAssignment3(target=es2015).symbols new file mode 100644 index 0000000000000..5d17ac406b683 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment3(target=es2015).symbols @@ -0,0 +1,49 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts === +interface A { +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +} + +declare const result: A; +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +declare const a: A; +>a : Symbol(a, Decl(logicalAssignment3.ts, 5, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +declare const b: A; +>b : Symbol(b, Decl(logicalAssignment3.ts, 6, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +declare const c: A; +>c : Symbol(c, Decl(logicalAssignment3.ts, 7, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +(a.baz) &&= result.baz; +>a.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>a : Symbol(a, Decl(logicalAssignment3.ts, 5, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) + +(b.baz) ||= result.baz; +>b.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>b : Symbol(b, Decl(logicalAssignment3.ts, 6, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) + +(c.baz) ??= result.baz; +>c.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>c : Symbol(c, Decl(logicalAssignment3.ts, 7, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) + + diff --git a/tests/baselines/reference/logicalAssignment3(target=es2015).types b/tests/baselines/reference/logicalAssignment3(target=es2015).types new file mode 100644 index 0000000000000..c18cad97c3377 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment3(target=es2015).types @@ -0,0 +1,49 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts === +interface A { + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined +} + +declare const result: A; +>result : A + +declare const a: A; +>a : A + +declare const b: A; +>b : A + +declare const c: A; +>c : A + +(a.baz) &&= result.baz; +>(a.baz) &&= result.baz : "" | 0 | 1 | 42 | undefined +>(a.baz) : string | number | undefined +>a.baz : string | number | undefined +>a : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +(b.baz) ||= result.baz; +>(b.baz) ||= result.baz : string | number | undefined +>(b.baz) : string | number | undefined +>b.baz : string | number | undefined +>b : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +(c.baz) ??= result.baz; +>(c.baz) ??= result.baz : string | number | undefined +>(c.baz) : string | number | undefined +>c.baz : string | number | undefined +>c : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + + diff --git a/tests/baselines/reference/logicalAssignment3(target=es2020).js b/tests/baselines/reference/logicalAssignment3(target=es2020).js new file mode 100644 index 0000000000000..854fa1567137b --- /dev/null +++ b/tests/baselines/reference/logicalAssignment3(target=es2020).js @@ -0,0 +1,21 @@ +//// [logicalAssignment3.ts] +interface A { + baz: 0 | 1 | 42 | undefined | '' +} + +declare const result: A; +declare const a: A; +declare const b: A; +declare const c: A; + +(a.baz) &&= result.baz; +(b.baz) ||= result.baz; +(c.baz) ??= result.baz; + + + +//// [logicalAssignment3.js] +"use strict"; +(a.baz) && ((a.baz) = result.baz); +(b.baz) || ((b.baz) = result.baz); +(c.baz) ?? ((c.baz) = result.baz); diff --git a/tests/baselines/reference/logicalAssignment3(target=es2020).symbols b/tests/baselines/reference/logicalAssignment3(target=es2020).symbols new file mode 100644 index 0000000000000..5d17ac406b683 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment3(target=es2020).symbols @@ -0,0 +1,49 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts === +interface A { +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +} + +declare const result: A; +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +declare const a: A; +>a : Symbol(a, Decl(logicalAssignment3.ts, 5, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +declare const b: A; +>b : Symbol(b, Decl(logicalAssignment3.ts, 6, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +declare const c: A; +>c : Symbol(c, Decl(logicalAssignment3.ts, 7, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +(a.baz) &&= result.baz; +>a.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>a : Symbol(a, Decl(logicalAssignment3.ts, 5, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) + +(b.baz) ||= result.baz; +>b.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>b : Symbol(b, Decl(logicalAssignment3.ts, 6, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) + +(c.baz) ??= result.baz; +>c.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>c : Symbol(c, Decl(logicalAssignment3.ts, 7, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) + + diff --git a/tests/baselines/reference/logicalAssignment3(target=es2020).types b/tests/baselines/reference/logicalAssignment3(target=es2020).types new file mode 100644 index 0000000000000..c18cad97c3377 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment3(target=es2020).types @@ -0,0 +1,49 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts === +interface A { + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined +} + +declare const result: A; +>result : A + +declare const a: A; +>a : A + +declare const b: A; +>b : A + +declare const c: A; +>c : A + +(a.baz) &&= result.baz; +>(a.baz) &&= result.baz : "" | 0 | 1 | 42 | undefined +>(a.baz) : string | number | undefined +>a.baz : string | number | undefined +>a : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +(b.baz) ||= result.baz; +>(b.baz) ||= result.baz : string | number | undefined +>(b.baz) : string | number | undefined +>b.baz : string | number | undefined +>b : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +(c.baz) ??= result.baz; +>(c.baz) ??= result.baz : string | number | undefined +>(c.baz) : string | number | undefined +>c.baz : string | number | undefined +>c : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + + diff --git a/tests/baselines/reference/logicalAssignment3(target=esnext).js b/tests/baselines/reference/logicalAssignment3(target=esnext).js new file mode 100644 index 0000000000000..113bdd39d3f19 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment3(target=esnext).js @@ -0,0 +1,21 @@ +//// [logicalAssignment3.ts] +interface A { + baz: 0 | 1 | 42 | undefined | '' +} + +declare const result: A; +declare const a: A; +declare const b: A; +declare const c: A; + +(a.baz) &&= result.baz; +(b.baz) ||= result.baz; +(c.baz) ??= result.baz; + + + +//// [logicalAssignment3.js] +"use strict"; +(a.baz) &&= result.baz; +(b.baz) ||= result.baz; +(c.baz) ??= result.baz; diff --git a/tests/baselines/reference/logicalAssignment3(target=esnext).symbols b/tests/baselines/reference/logicalAssignment3(target=esnext).symbols new file mode 100644 index 0000000000000..5d17ac406b683 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment3(target=esnext).symbols @@ -0,0 +1,49 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts === +interface A { +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + + baz: 0 | 1 | 42 | undefined | '' +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +} + +declare const result: A; +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +declare const a: A; +>a : Symbol(a, Decl(logicalAssignment3.ts, 5, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +declare const b: A; +>b : Symbol(b, Decl(logicalAssignment3.ts, 6, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +declare const c: A; +>c : Symbol(c, Decl(logicalAssignment3.ts, 7, 13)) +>A : Symbol(A, Decl(logicalAssignment3.ts, 0, 0)) + +(a.baz) &&= result.baz; +>a.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>a : Symbol(a, Decl(logicalAssignment3.ts, 5, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) + +(b.baz) ||= result.baz; +>b.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>b : Symbol(b, Decl(logicalAssignment3.ts, 6, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) + +(c.baz) ??= result.baz; +>c.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>c : Symbol(c, Decl(logicalAssignment3.ts, 7, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result.baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) +>result : Symbol(result, Decl(logicalAssignment3.ts, 4, 13)) +>baz : Symbol(A.baz, Decl(logicalAssignment3.ts, 0, 13)) + + diff --git a/tests/baselines/reference/logicalAssignment3(target=esnext).types b/tests/baselines/reference/logicalAssignment3(target=esnext).types new file mode 100644 index 0000000000000..c18cad97c3377 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment3(target=esnext).types @@ -0,0 +1,49 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts === +interface A { + baz: 0 | 1 | 42 | undefined | '' +>baz : "" | 0 | 1 | 42 | undefined +} + +declare const result: A; +>result : A + +declare const a: A; +>a : A + +declare const b: A; +>b : A + +declare const c: A; +>c : A + +(a.baz) &&= result.baz; +>(a.baz) &&= result.baz : "" | 0 | 1 | 42 | undefined +>(a.baz) : string | number | undefined +>a.baz : string | number | undefined +>a : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +(b.baz) ||= result.baz; +>(b.baz) ||= result.baz : string | number | undefined +>(b.baz) : string | number | undefined +>b.baz : string | number | undefined +>b : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + +(c.baz) ??= result.baz; +>(c.baz) ??= result.baz : string | number | undefined +>(c.baz) : string | number | undefined +>c.baz : string | number | undefined +>c : A +>baz : string | number | undefined +>result.baz : "" | 0 | 1 | 42 | undefined +>result : A +>baz : "" | 0 | 1 | 42 | undefined + + diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).js b/tests/baselines/reference/logicalAssignment4(target=es2015).js new file mode 100644 index 0000000000000..57478da71acbe --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).js @@ -0,0 +1,17 @@ +//// [logicalAssignment4.ts] +function foo1(results: number[] | undefined) { + (results ||= []).push(100); +} + +function foo2(results: number[] | undefined) { + (results ??= []).push(100); +} + +//// [logicalAssignment4.js] +"use strict"; +function foo1(results) { + (results || (results = [])).push(100); +} +function foo2(results) { + (results !== null && results !== void 0 ? results : (results = [])).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).symbols b/tests/baselines/reference/logicalAssignment4(target=es2015).symbols new file mode 100644 index 0000000000000..7d114427014e6 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).symbols @@ -0,0 +1,20 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts === +function foo1(results: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment4.ts, 0, 0)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 0, 14)) + + (results ||= []).push(100); +>(results ||= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 0, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment4.ts, 2, 1)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 4, 14)) + + (results ??= []).push(100); +>(results ??= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 4, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).types b/tests/baselines/reference/logicalAssignment4(target=es2015).types new file mode 100644 index 0000000000000..da48e3848b8f0 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).types @@ -0,0 +1,30 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts === +function foo1(results: number[] | undefined) { +>foo1 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ||= []).push(100); +>(results ||= []).push(100) : number +>(results ||= []).push : (...items: number[]) => number +>(results ||= []) : number[] +>results ||= [] : number[] +>results : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined) { +>foo2 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ??= []).push(100); +>(results ??= []).push(100) : number +>(results ??= []).push : (...items: number[]) => number +>(results ??= []) : number[] +>results ??= [] : number[] +>results : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).js b/tests/baselines/reference/logicalAssignment4(target=es2020).js new file mode 100644 index 0000000000000..91d60e88aa9da --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).js @@ -0,0 +1,17 @@ +//// [logicalAssignment4.ts] +function foo1(results: number[] | undefined) { + (results ||= []).push(100); +} + +function foo2(results: number[] | undefined) { + (results ??= []).push(100); +} + +//// [logicalAssignment4.js] +"use strict"; +function foo1(results) { + (results || (results = [])).push(100); +} +function foo2(results) { + (results ?? (results = [])).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).symbols b/tests/baselines/reference/logicalAssignment4(target=es2020).symbols new file mode 100644 index 0000000000000..7d114427014e6 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).symbols @@ -0,0 +1,20 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts === +function foo1(results: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment4.ts, 0, 0)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 0, 14)) + + (results ||= []).push(100); +>(results ||= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 0, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment4.ts, 2, 1)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 4, 14)) + + (results ??= []).push(100); +>(results ??= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 4, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).types b/tests/baselines/reference/logicalAssignment4(target=es2020).types new file mode 100644 index 0000000000000..da48e3848b8f0 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).types @@ -0,0 +1,30 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts === +function foo1(results: number[] | undefined) { +>foo1 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ||= []).push(100); +>(results ||= []).push(100) : number +>(results ||= []).push : (...items: number[]) => number +>(results ||= []) : number[] +>results ||= [] : number[] +>results : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined) { +>foo2 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ??= []).push(100); +>(results ??= []).push(100) : number +>(results ??= []).push : (...items: number[]) => number +>(results ??= []) : number[] +>results ??= [] : number[] +>results : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).js b/tests/baselines/reference/logicalAssignment4(target=esnext).js new file mode 100644 index 0000000000000..3b749b6d8c7b3 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).js @@ -0,0 +1,17 @@ +//// [logicalAssignment4.ts] +function foo1(results: number[] | undefined) { + (results ||= []).push(100); +} + +function foo2(results: number[] | undefined) { + (results ??= []).push(100); +} + +//// [logicalAssignment4.js] +"use strict"; +function foo1(results) { + (results ||= []).push(100); +} +function foo2(results) { + (results ??= []).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).symbols b/tests/baselines/reference/logicalAssignment4(target=esnext).symbols new file mode 100644 index 0000000000000..7d114427014e6 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).symbols @@ -0,0 +1,20 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts === +function foo1(results: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment4.ts, 0, 0)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 0, 14)) + + (results ||= []).push(100); +>(results ||= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 0, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment4.ts, 2, 1)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 4, 14)) + + (results ??= []).push(100); +>(results ??= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 4, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).types b/tests/baselines/reference/logicalAssignment4(target=esnext).types new file mode 100644 index 0000000000000..da48e3848b8f0 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).types @@ -0,0 +1,30 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts === +function foo1(results: number[] | undefined) { +>foo1 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ||= []).push(100); +>(results ||= []).push(100) : number +>(results ||= []).push : (...items: number[]) => number +>(results ||= []) : number[] +>results ||= [] : number[] +>results : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined) { +>foo2 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ??= []).push(100); +>(results ??= []).push(100) : number +>(results ??= []).push : (...items: number[]) => number +>(results ??= []) : number[] +>results ??= [] : number[] +>results : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts new file mode 100644 index 0000000000000..4bf3dd3581a11 --- /dev/null +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts @@ -0,0 +1,29 @@ +// @strict: true +// @target: esnext, es2020, es2015 +interface A { + foo: { + bar(): { + baz: 0 | 1 | 42 | undefined | '' + } + baz: 0 | 1 | 42 | undefined | '' + } + baz: 0 | 1 | 42 | undefined | '' +} + +declare const result: A +declare const a: A +declare const b: A +declare const c: A + +a.baz &&= result.baz +b.baz ||= result.baz +c.baz ??= result.baz + +a.foo["baz"] &&= result.foo.baz +b.foo["baz"] &&= result.foo.baz +c.foo["baz"] &&= result.foo.baz + +a.foo.bar().baz &&= result.foo.bar().baz +b.foo.bar().baz ||= result.foo.bar().baz +c.foo.bar().baz ??= result.foo.bar().baz + diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts new file mode 100644 index 0000000000000..ea6085ece8023 --- /dev/null +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment3.ts @@ -0,0 +1,15 @@ +// @strict: true +// @target: esnext, es2020, es2015 +interface A { + baz: 0 | 1 | 42 | undefined | '' +} + +declare const result: A; +declare const a: A; +declare const b: A; +declare const c: A; + +(a.baz) &&= result.baz; +(b.baz) ||= result.baz; +(c.baz) ??= result.baz; + diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts new file mode 100644 index 0000000000000..69cd3aad50ba0 --- /dev/null +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts @@ -0,0 +1,10 @@ +// @strict: true +// @target: esnext, es2020, es2015 + +function foo1(results: number[] | undefined) { + (results ||= []).push(100); +} + +function foo2(results: number[] | undefined) { + (results ??= []).push(100); +} \ No newline at end of file From f92242719601224ecab193700d0b2e7b341eecfc Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 1 Apr 2020 11:43:18 +0800 Subject: [PATCH 03/24] Add mission semi --- src/compiler/transformers/esnext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 8004e7bc4ded5..b9bbbffe5fed1 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -43,7 +43,7 @@ namespace ts { right ) ) - ) + ); } Debug.fail("unexpected operator: " + operator.kind); From 9190a2c4e8a9c5b87a3843d5268a3142d3406adb Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 1 Apr 2020 16:28:48 +0800 Subject: [PATCH 04/24] Add contextual types infer --- src/compiler/checker.ts | 2 ++ .../esnext/logicalAssignment/logicalAssignment5.ts | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4b52f2faab0b3..89ee4693ffe92 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22365,6 +22365,8 @@ namespace ts { return contextSensitive === true ? getTypeOfExpression(left) : contextSensitive; case SyntaxKind.BarBarToken: case SyntaxKind.QuestionQuestionToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: // When an || expression has a contextual type, the operands are contextually typed by that type, except // when that type originates in a binding pattern, the right operand is contextually typed by the type of // the left operand. When an || expression has no contextual type, the right operand is contextually typed diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts new file mode 100644 index 0000000000000..08176cce75b8e --- /dev/null +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts @@ -0,0 +1,7 @@ +// @strict: true +// @target: esnext, es2020, es2015 + +function foo (f: (a: number) => void | undefined) { + f ??= (a => a++) + f ||= (a => a++) +} From 82fe658a48076cb3d0aa53e9c2d49b75508735f6 Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 1 Apr 2020 23:39:38 +0800 Subject: [PATCH 05/24] Add cfa --- src/compiler/binder.ts | 40 +++++- ...gicalAssignment4(target=es2015).errors.txt | 33 +++++ .../logicalAssignment4(target=es2015).js | 33 +++++ .../logicalAssignment4(target=es2015).symbols | 57 ++++++++ .../logicalAssignment4(target=es2015).types | 63 +++++++++ ...gicalAssignment4(target=es2020).errors.txt | 33 +++++ .../logicalAssignment4(target=es2020).js | 33 +++++ .../logicalAssignment4(target=es2020).symbols | 57 ++++++++ .../logicalAssignment4(target=es2020).types | 63 +++++++++ ...gicalAssignment4(target=esnext).errors.txt | 33 +++++ .../logicalAssignment4(target=esnext).js | 33 +++++ .../logicalAssignment4(target=esnext).symbols | 57 ++++++++ .../logicalAssignment4(target=esnext).types | 63 +++++++++ ...gicalAssignment5(target=es2015).errors.txt | 51 +++++++ .../logicalAssignment5(target=es2015).js | 58 ++++++++ .../logicalAssignment5(target=es2015).symbols | 90 ++++++++++++ .../logicalAssignment5(target=es2015).types | 133 ++++++++++++++++++ ...gicalAssignment5(target=es2020).errors.txt | 51 +++++++ .../logicalAssignment5(target=es2020).js | 58 ++++++++ .../logicalAssignment5(target=es2020).symbols | 90 ++++++++++++ .../logicalAssignment5(target=es2020).types | 133 ++++++++++++++++++ ...gicalAssignment5(target=esnext).errors.txt | 51 +++++++ .../logicalAssignment5(target=esnext).js | 58 ++++++++ .../logicalAssignment5(target=esnext).symbols | 90 ++++++++++++ .../logicalAssignment5(target=esnext).types | 133 ++++++++++++++++++ ...gicalAssignment6(target=es2015).errors.txt | 20 +++ .../logicalAssignment6(target=es2015).js | 24 ++++ .../logicalAssignment6(target=es2015).symbols | 36 +++++ .../logicalAssignment6(target=es2015).types | 57 ++++++++ ...gicalAssignment6(target=es2020).errors.txt | 20 +++ .../logicalAssignment6(target=es2020).js | 24 ++++ .../logicalAssignment6(target=es2020).symbols | 36 +++++ .../logicalAssignment6(target=es2020).types | 57 ++++++++ ...gicalAssignment6(target=esnext).errors.txt | 20 +++ .../logicalAssignment6(target=esnext).js | 24 ++++ .../logicalAssignment6(target=esnext).symbols | 36 +++++ .../logicalAssignment6(target=esnext).types | 57 ++++++++ ...gicalAssignment7(target=es2015).errors.txt | 29 ++++ .../logicalAssignment7(target=es2015).js | 25 ++++ .../logicalAssignment7(target=es2015).symbols | 36 +++++ .../logicalAssignment7(target=es2015).types | 54 +++++++ ...gicalAssignment7(target=es2020).errors.txt | 29 ++++ .../logicalAssignment7(target=es2020).js | 24 ++++ .../logicalAssignment7(target=es2020).symbols | 36 +++++ .../logicalAssignment7(target=es2020).types | 54 +++++++ ...gicalAssignment7(target=esnext).errors.txt | 29 ++++ .../logicalAssignment7(target=esnext).js | 24 ++++ .../logicalAssignment7(target=esnext).symbols | 36 +++++ .../logicalAssignment7(target=esnext).types | 54 +++++++ .../logicalAssignment/logicalAssignment4.ts | 20 +++ .../logicalAssignment/logicalAssignment5.ts | 31 +++- .../logicalAssignment/logicalAssignment6.ts | 14 ++ .../logicalAssignment/logicalAssignment7.ts | 14 ++ 53 files changed, 2510 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment5(target=es2015).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment5(target=es2015).js create mode 100644 tests/baselines/reference/logicalAssignment5(target=es2015).symbols create mode 100644 tests/baselines/reference/logicalAssignment5(target=es2015).types create mode 100644 tests/baselines/reference/logicalAssignment5(target=es2020).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment5(target=es2020).js create mode 100644 tests/baselines/reference/logicalAssignment5(target=es2020).symbols create mode 100644 tests/baselines/reference/logicalAssignment5(target=es2020).types create mode 100644 tests/baselines/reference/logicalAssignment5(target=esnext).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment5(target=esnext).js create mode 100644 tests/baselines/reference/logicalAssignment5(target=esnext).symbols create mode 100644 tests/baselines/reference/logicalAssignment5(target=esnext).types create mode 100644 tests/baselines/reference/logicalAssignment6(target=es2015).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment6(target=es2015).js create mode 100644 tests/baselines/reference/logicalAssignment6(target=es2015).symbols create mode 100644 tests/baselines/reference/logicalAssignment6(target=es2015).types create mode 100644 tests/baselines/reference/logicalAssignment6(target=es2020).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment6(target=es2020).js create mode 100644 tests/baselines/reference/logicalAssignment6(target=es2020).symbols create mode 100644 tests/baselines/reference/logicalAssignment6(target=es2020).types create mode 100644 tests/baselines/reference/logicalAssignment6(target=esnext).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment6(target=esnext).js create mode 100644 tests/baselines/reference/logicalAssignment6(target=esnext).symbols create mode 100644 tests/baselines/reference/logicalAssignment6(target=esnext).types create mode 100644 tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment7(target=es2015).js create mode 100644 tests/baselines/reference/logicalAssignment7(target=es2015).symbols create mode 100644 tests/baselines/reference/logicalAssignment7(target=es2015).types create mode 100644 tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment7(target=es2020).js create mode 100644 tests/baselines/reference/logicalAssignment7(target=es2020).symbols create mode 100644 tests/baselines/reference/logicalAssignment7(target=es2020).types create mode 100644 tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment7(target=esnext).js create mode 100644 tests/baselines/reference/logicalAssignment7(target=esnext).symbols create mode 100644 tests/baselines/reference/logicalAssignment7(target=esnext).types create mode 100644 tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts create mode 100644 tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 93a3bc5538d5c..5e57002094154 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1041,6 +1041,17 @@ namespace ts { } } + function isLogicalAssignmentExpressioin(node: Node) { + while (true) { + if (isParenthesizedExpression(node)) { + node = node.expression + } + else { + return isBinaryExpression(node) && isLogicalAssignmentOperator(node.operatorToken.kind); + } + } + } + function isTopLevelLogicalExpression(node: Node): boolean { while (isParenthesizedExpression(node.parent) || isPrefixUnaryExpression(node.parent) && node.parent.operator === SyntaxKind.ExclamationToken) { @@ -1063,7 +1074,7 @@ namespace ts { function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) { doWithConditionalBranches(bind, node, trueTarget, falseTarget); - if (!node || !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) { + if (!node || !isLogicalAssignmentExpressioin(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) { addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); } @@ -1163,6 +1174,25 @@ namespace ts { currentFlow = finishFlowLabel(postIfLabel); } + function bindLogicalAssignmentExpression(node: BinaryExpression) { + const preRightLabel = createBranchLabel(); + const postExpressionLabel = createBranchLabel(); + + if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) { + bindCondition(node.left, preRightLabel, postExpressionLabel); + } + else { + bindCondition(node.left, postExpressionLabel, preRightLabel); + } + + currentFlow = finishFlowLabel(preRightLabel); + bind(node.operatorToken); + bind(node.right); + bindAssignmentTargetFlow(node.left); + + currentFlow = finishFlowLabel(postExpressionLabel); + } + function bindReturnOrThrow(node: ReturnStatement | ThrowStatement): void { bind(node.expression); if (node.kind === SyntaxKind.ReturnStatement) { @@ -1450,6 +1480,10 @@ namespace ts { } function bindBinaryExpressionFlow(node: BinaryExpression) { + const flow = currentFlow + if (flow) { + + } const workStacks: { expr: BinaryExpression[], state: BindBinaryExpressionFlowState[], @@ -1511,6 +1545,10 @@ namespace ts { } completeNode(); } + else if(isLogicalAssignmentOperator(operator)) { + bindLogicalAssignmentExpression(node); + completeNode(); + } else { advanceState(BindBinaryExpressionFlowState.BindToken); maybeBind(node.left); diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt new file mode 100644 index 0000000000000..939c5699f6a9b --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt @@ -0,0 +1,33 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): error TS2532: Object is possibly 'undefined'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts (1 errors) ==== + function foo1(results: number[] | undefined) { + (results ||= []).push(100); + } + + function foo2(results: number[] | undefined) { + (results ??= []).push(100); + } + + function foo3(results: number[] | undefined) { + results ||= []; + results.push(100); + } + + function foo4(results: number[] | undefined) { + results ||= []; + results.push(100); + } + + interface ThingWithOriginal { + name: string; + original?: ThingWithOriginal + } + function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { + if (thing &&= thing.original) { + console.log(thing.name); + ~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).js b/tests/baselines/reference/logicalAssignment4(target=es2015).js index 57478da71acbe..1a69ceeb70a3f 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).js @@ -5,6 +5,26 @@ function foo1(results: number[] | undefined) { function foo2(results: number[] | undefined) { (results ??= []).push(100); +} + +function foo3(results: number[] | undefined) { + results ||= []; + results.push(100); +} + +function foo4(results: number[] | undefined) { + results ||= []; + results.push(100); +} + +interface ThingWithOriginal { + name: string; + original?: ThingWithOriginal +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { + if (thing &&= thing.original) { + console.log(thing.name); + } } //// [logicalAssignment4.js] @@ -15,3 +35,16 @@ function foo1(results) { function foo2(results) { (results !== null && results !== void 0 ? results : (results = [])).push(100); } +function foo3(results) { + results || (results = []); + results.push(100); +} +function foo4(results) { + results || (results = []); + results.push(100); +} +function doSomethingWithAlias(thing) { + if (thing && (thing = thing.original)) { + console.log(thing.name); + } +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).symbols b/tests/baselines/reference/logicalAssignment4(target=es2015).symbols index 7d114427014e6..4f25669f53e1e 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).symbols +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).symbols @@ -18,3 +18,60 @@ function foo2(results: number[] | undefined) { >results : Symbol(results, Decl(logicalAssignment4.ts, 4, 14)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) } + +function foo3(results: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment4.ts, 6, 1)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 8, 14)) + + results ||= []; +>results : Symbol(results, Decl(logicalAssignment4.ts, 8, 14)) + + results.push(100); +>results.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 8, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo4(results: number[] | undefined) { +>foo4 : Symbol(foo4, Decl(logicalAssignment4.ts, 11, 1)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) + + results ||= []; +>results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) + + results.push(100); +>results.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +interface ThingWithOriginal { +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) + + name: string; +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + original?: ThingWithOriginal +>original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { +>doSomethingWithAlias : Symbol(doSomethingWithAlias, Decl(logicalAssignment4.ts, 21, 1)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) + + if (thing &&= thing.original) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>thing.original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) + + console.log(thing.name); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).types b/tests/baselines/reference/logicalAssignment4(target=es2015).types index da48e3848b8f0..a2669aa6f28ab 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).types @@ -28,3 +28,66 @@ function foo2(results: number[] | undefined) { >push : (...items: number[]) => number >100 : 100 } + +function foo3(results: number[] | undefined) { +>foo3 : (results: number[] | undefined) => void +>results : number[] | undefined + + results ||= []; +>results ||= [] : number[] +>results : number[] | undefined +>[] : never[] + + results.push(100); +>results.push(100) : number +>results.push : (...items: number[]) => number +>results : number[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo4(results: number[] | undefined) { +>foo4 : (results: number[] | undefined) => void +>results : number[] | undefined + + results ||= []; +>results ||= [] : number[] +>results : number[] | undefined +>[] : never[] + + results.push(100); +>results.push(100) : number +>results.push : (...items: number[]) => number +>results : number[] +>push : (...items: number[]) => number +>100 : 100 +} + +interface ThingWithOriginal { + name: string; +>name : string + + original?: ThingWithOriginal +>original : ThingWithOriginal | undefined +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { +>doSomethingWithAlias : (thing?: ThingWithOriginal | undefined) => void +>thing : ThingWithOriginal | undefined + + if (thing &&= thing.original) { +>thing &&= thing.original : ThingWithOriginal | undefined +>thing : ThingWithOriginal | undefined +>thing.original : ThingWithOriginal | undefined +>thing : ThingWithOriginal +>original : ThingWithOriginal | undefined + + console.log(thing.name); +>console.log(thing.name) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>thing.name : string +>thing : ThingWithOriginal | undefined +>name : string + } +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt new file mode 100644 index 0000000000000..939c5699f6a9b --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt @@ -0,0 +1,33 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): error TS2532: Object is possibly 'undefined'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts (1 errors) ==== + function foo1(results: number[] | undefined) { + (results ||= []).push(100); + } + + function foo2(results: number[] | undefined) { + (results ??= []).push(100); + } + + function foo3(results: number[] | undefined) { + results ||= []; + results.push(100); + } + + function foo4(results: number[] | undefined) { + results ||= []; + results.push(100); + } + + interface ThingWithOriginal { + name: string; + original?: ThingWithOriginal + } + function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { + if (thing &&= thing.original) { + console.log(thing.name); + ~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).js b/tests/baselines/reference/logicalAssignment4(target=es2020).js index 91d60e88aa9da..f2dfaa8e3c9c1 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).js @@ -5,6 +5,26 @@ function foo1(results: number[] | undefined) { function foo2(results: number[] | undefined) { (results ??= []).push(100); +} + +function foo3(results: number[] | undefined) { + results ||= []; + results.push(100); +} + +function foo4(results: number[] | undefined) { + results ||= []; + results.push(100); +} + +interface ThingWithOriginal { + name: string; + original?: ThingWithOriginal +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { + if (thing &&= thing.original) { + console.log(thing.name); + } } //// [logicalAssignment4.js] @@ -15,3 +35,16 @@ function foo1(results) { function foo2(results) { (results ?? (results = [])).push(100); } +function foo3(results) { + results || (results = []); + results.push(100); +} +function foo4(results) { + results || (results = []); + results.push(100); +} +function doSomethingWithAlias(thing) { + if (thing && (thing = thing.original)) { + console.log(thing.name); + } +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).symbols b/tests/baselines/reference/logicalAssignment4(target=es2020).symbols index 7d114427014e6..4f25669f53e1e 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).symbols +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).symbols @@ -18,3 +18,60 @@ function foo2(results: number[] | undefined) { >results : Symbol(results, Decl(logicalAssignment4.ts, 4, 14)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) } + +function foo3(results: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment4.ts, 6, 1)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 8, 14)) + + results ||= []; +>results : Symbol(results, Decl(logicalAssignment4.ts, 8, 14)) + + results.push(100); +>results.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 8, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo4(results: number[] | undefined) { +>foo4 : Symbol(foo4, Decl(logicalAssignment4.ts, 11, 1)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) + + results ||= []; +>results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) + + results.push(100); +>results.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +interface ThingWithOriginal { +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) + + name: string; +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + original?: ThingWithOriginal +>original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { +>doSomethingWithAlias : Symbol(doSomethingWithAlias, Decl(logicalAssignment4.ts, 21, 1)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) + + if (thing &&= thing.original) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>thing.original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) + + console.log(thing.name); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } +} diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).types b/tests/baselines/reference/logicalAssignment4(target=es2020).types index da48e3848b8f0..a2669aa6f28ab 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).types @@ -28,3 +28,66 @@ function foo2(results: number[] | undefined) { >push : (...items: number[]) => number >100 : 100 } + +function foo3(results: number[] | undefined) { +>foo3 : (results: number[] | undefined) => void +>results : number[] | undefined + + results ||= []; +>results ||= [] : number[] +>results : number[] | undefined +>[] : never[] + + results.push(100); +>results.push(100) : number +>results.push : (...items: number[]) => number +>results : number[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo4(results: number[] | undefined) { +>foo4 : (results: number[] | undefined) => void +>results : number[] | undefined + + results ||= []; +>results ||= [] : number[] +>results : number[] | undefined +>[] : never[] + + results.push(100); +>results.push(100) : number +>results.push : (...items: number[]) => number +>results : number[] +>push : (...items: number[]) => number +>100 : 100 +} + +interface ThingWithOriginal { + name: string; +>name : string + + original?: ThingWithOriginal +>original : ThingWithOriginal | undefined +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { +>doSomethingWithAlias : (thing?: ThingWithOriginal | undefined) => void +>thing : ThingWithOriginal | undefined + + if (thing &&= thing.original) { +>thing &&= thing.original : ThingWithOriginal | undefined +>thing : ThingWithOriginal | undefined +>thing.original : ThingWithOriginal | undefined +>thing : ThingWithOriginal +>original : ThingWithOriginal | undefined + + console.log(thing.name); +>console.log(thing.name) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>thing.name : string +>thing : ThingWithOriginal | undefined +>name : string + } +} diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt new file mode 100644 index 0000000000000..939c5699f6a9b --- /dev/null +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt @@ -0,0 +1,33 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): error TS2532: Object is possibly 'undefined'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts (1 errors) ==== + function foo1(results: number[] | undefined) { + (results ||= []).push(100); + } + + function foo2(results: number[] | undefined) { + (results ??= []).push(100); + } + + function foo3(results: number[] | undefined) { + results ||= []; + results.push(100); + } + + function foo4(results: number[] | undefined) { + results ||= []; + results.push(100); + } + + interface ThingWithOriginal { + name: string; + original?: ThingWithOriginal + } + function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { + if (thing &&= thing.original) { + console.log(thing.name); + ~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).js b/tests/baselines/reference/logicalAssignment4(target=esnext).js index 3b749b6d8c7b3..b9c254e977806 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).js +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).js @@ -5,6 +5,26 @@ function foo1(results: number[] | undefined) { function foo2(results: number[] | undefined) { (results ??= []).push(100); +} + +function foo3(results: number[] | undefined) { + results ||= []; + results.push(100); +} + +function foo4(results: number[] | undefined) { + results ||= []; + results.push(100); +} + +interface ThingWithOriginal { + name: string; + original?: ThingWithOriginal +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { + if (thing &&= thing.original) { + console.log(thing.name); + } } //// [logicalAssignment4.js] @@ -15,3 +35,16 @@ function foo1(results) { function foo2(results) { (results ??= []).push(100); } +function foo3(results) { + results ||= []; + results.push(100); +} +function foo4(results) { + results ||= []; + results.push(100); +} +function doSomethingWithAlias(thing) { + if (thing &&= thing.original) { + console.log(thing.name); + } +} diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).symbols b/tests/baselines/reference/logicalAssignment4(target=esnext).symbols index 7d114427014e6..4f25669f53e1e 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).symbols +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).symbols @@ -18,3 +18,60 @@ function foo2(results: number[] | undefined) { >results : Symbol(results, Decl(logicalAssignment4.ts, 4, 14)) >push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) } + +function foo3(results: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment4.ts, 6, 1)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 8, 14)) + + results ||= []; +>results : Symbol(results, Decl(logicalAssignment4.ts, 8, 14)) + + results.push(100); +>results.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 8, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo4(results: number[] | undefined) { +>foo4 : Symbol(foo4, Decl(logicalAssignment4.ts, 11, 1)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) + + results ||= []; +>results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) + + results.push(100); +>results.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +interface ThingWithOriginal { +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) + + name: string; +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + original?: ThingWithOriginal +>original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { +>doSomethingWithAlias : Symbol(doSomethingWithAlias, Decl(logicalAssignment4.ts, 21, 1)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) + + if (thing &&= thing.original) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>thing.original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) + + console.log(thing.name); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } +} diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).types b/tests/baselines/reference/logicalAssignment4(target=esnext).types index da48e3848b8f0..a2669aa6f28ab 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).types @@ -28,3 +28,66 @@ function foo2(results: number[] | undefined) { >push : (...items: number[]) => number >100 : 100 } + +function foo3(results: number[] | undefined) { +>foo3 : (results: number[] | undefined) => void +>results : number[] | undefined + + results ||= []; +>results ||= [] : number[] +>results : number[] | undefined +>[] : never[] + + results.push(100); +>results.push(100) : number +>results.push : (...items: number[]) => number +>results : number[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo4(results: number[] | undefined) { +>foo4 : (results: number[] | undefined) => void +>results : number[] | undefined + + results ||= []; +>results ||= [] : number[] +>results : number[] | undefined +>[] : never[] + + results.push(100); +>results.push(100) : number +>results.push : (...items: number[]) => number +>results : number[] +>push : (...items: number[]) => number +>100 : 100 +} + +interface ThingWithOriginal { + name: string; +>name : string + + original?: ThingWithOriginal +>original : ThingWithOriginal | undefined +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { +>doSomethingWithAlias : (thing?: ThingWithOriginal | undefined) => void +>thing : ThingWithOriginal | undefined + + if (thing &&= thing.original) { +>thing &&= thing.original : ThingWithOriginal | undefined +>thing : ThingWithOriginal | undefined +>thing.original : ThingWithOriginal | undefined +>thing : ThingWithOriginal +>original : ThingWithOriginal | undefined + + console.log(thing.name); +>console.log(thing.name) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>thing.name : string +>thing : ThingWithOriginal | undefined +>name : string + } +} diff --git a/tests/baselines/reference/logicalAssignment5(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment5(target=es2015).errors.txt new file mode 100644 index 0000000000000..663162e916547 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=es2015).errors.txt @@ -0,0 +1,51 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(12,12): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(13,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(17,12): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(22,12): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(27,27): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts (6 errors) ==== + function foo1 (f?: (a: number) => void) { + f ??= (a => a) + f(42) + } + + function foo2 (f?: (a: number) => void) { + f ||= (a => a) + f(42) + } + + function foo3 (f?: (a: number) => void) { + f &&= (a => a) + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + f(42) + ~ +!!! error TS2722: Cannot invoke an object which is possibly 'undefined'. + } + + function bar1 (f?: (a: number) => void) { + f ??= (f.toString(), (a => a)) + ~ +!!! error TS2532: Object is possibly 'undefined'. + f(42) + } + + function bar2 (f?: (a: number) => void) { + f ||= (f.toString(), (a => a)) + ~ +!!! error TS2532: Object is possibly 'undefined'. + f(42) + } + + function bar3 (f?: (a: number) => void) { + f &&= (f.toString(), (a => a)) + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + f(42) + ~ +!!! error TS2722: Cannot invoke an object which is possibly 'undefined'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment5(target=es2015).js b/tests/baselines/reference/logicalAssignment5(target=es2015).js new file mode 100644 index 0000000000000..f42fd755c1ddf --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=es2015).js @@ -0,0 +1,58 @@ +//// [logicalAssignment5.ts] +function foo1 (f?: (a: number) => void) { + f ??= (a => a) + f(42) +} + +function foo2 (f?: (a: number) => void) { + f ||= (a => a) + f(42) +} + +function foo3 (f?: (a: number) => void) { + f &&= (a => a) + f(42) +} + +function bar1 (f?: (a: number) => void) { + f ??= (f.toString(), (a => a)) + f(42) +} + +function bar2 (f?: (a: number) => void) { + f ||= (f.toString(), (a => a)) + f(42) +} + +function bar3 (f?: (a: number) => void) { + f &&= (f.toString(), (a => a)) + f(42) +} + + +//// [logicalAssignment5.js] +"use strict"; +function foo1(f) { + f !== null && f !== void 0 ? f : (f = (a => a)); + f(42); +} +function foo2(f) { + f || (f = (a => a)); + f(42); +} +function foo3(f) { + f && (f = (a => a)); + f(42); +} +function bar1(f) { + f !== null && f !== void 0 ? f : (f = (f.toString(), (a => a))); + f(42); +} +function bar2(f) { + f || (f = (f.toString(), (a => a))); + f(42); +} +function bar3(f) { + f && (f = (f.toString(), (a => a))); + f(42); +} diff --git a/tests/baselines/reference/logicalAssignment5(target=es2015).symbols b/tests/baselines/reference/logicalAssignment5(target=es2015).symbols new file mode 100644 index 0000000000000..5862d6b68d406 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=es2015).symbols @@ -0,0 +1,90 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts === +function foo1 (f?: (a: number) => void) { +>foo1 : Symbol(foo1, Decl(logicalAssignment5.ts, 0, 0)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 0, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 0, 20)) + + f ??= (a => a) +>f : Symbol(f, Decl(logicalAssignment5.ts, 0, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 1, 11)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 1, 11)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 0, 15)) +} + +function foo2 (f?: (a: number) => void) { +>foo2 : Symbol(foo2, Decl(logicalAssignment5.ts, 3, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 5, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 5, 20)) + + f ||= (a => a) +>f : Symbol(f, Decl(logicalAssignment5.ts, 5, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 6, 11)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 6, 11)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 5, 15)) +} + +function foo3 (f?: (a: number) => void) { +>foo3 : Symbol(foo3, Decl(logicalAssignment5.ts, 8, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 10, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 10, 20)) + + f &&= (a => a) +>f : Symbol(f, Decl(logicalAssignment5.ts, 10, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 11, 11)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 11, 11)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 10, 15)) +} + +function bar1 (f?: (a: number) => void) { +>bar1 : Symbol(bar1, Decl(logicalAssignment5.ts, 13, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 15, 20)) + + f ??= (f.toString(), (a => a)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 16, 26)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 16, 26)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +} + +function bar2 (f?: (a: number) => void) { +>bar2 : Symbol(bar2, Decl(logicalAssignment5.ts, 18, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 20, 20)) + + f ||= (f.toString(), (a => a)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 21, 26)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 21, 26)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +} + +function bar3 (f?: (a: number) => void) { +>bar3 : Symbol(bar3, Decl(logicalAssignment5.ts, 23, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 25, 20)) + + f &&= (f.toString(), (a => a)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +>f.toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +>toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 26, 26)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 26, 26)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +} + diff --git a/tests/baselines/reference/logicalAssignment5(target=es2015).types b/tests/baselines/reference/logicalAssignment5(target=es2015).types new file mode 100644 index 0000000000000..694c3db90a50c --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=es2015).types @@ -0,0 +1,133 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts === +function foo1 (f?: (a: number) => void) { +>foo1 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ??= (a => a) +>f ??= (a => a) : (a: number) => void +>f : ((a: number) => void) | undefined +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function foo2 (f?: (a: number) => void) { +>foo2 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ||= (a => a) +>f ||= (a => a) : (a: number) => void +>f : ((a: number) => void) | undefined +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function foo3 (f?: (a: number) => void) { +>foo3 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f &&= (a => a) +>f &&= (a => a) : ((a: any) => any) | undefined +>f : ((a: number) => void) | undefined +>(a => a) : (a: any) => any +>a => a : (a: any) => any +>a : any +>a : any + + f(42) +>f(42) : any +>f : undefined +>42 : 42 +} + +function bar1 (f?: (a: number) => void) { +>bar1 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ??= (f.toString(), (a => a)) +>f ??= (f.toString(), (a => a)) : (a: number) => void +>f : ((a: number) => void) | undefined +>(f.toString(), (a => a)) : (a: number) => number +>f.toString(), (a => a) : (a: number) => number +>f.toString() : any +>f.toString : any +>f : undefined +>toString : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function bar2 (f?: (a: number) => void) { +>bar2 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ||= (f.toString(), (a => a)) +>f ||= (f.toString(), (a => a)) : (a: number) => void +>f : ((a: number) => void) | undefined +>(f.toString(), (a => a)) : (a: number) => number +>f.toString(), (a => a) : (a: number) => number +>f.toString() : any +>f.toString : any +>f : undefined +>toString : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function bar3 (f?: (a: number) => void) { +>bar3 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f &&= (f.toString(), (a => a)) +>f &&= (f.toString(), (a => a)) : ((a: any) => any) | undefined +>f : ((a: number) => void) | undefined +>(f.toString(), (a => a)) : (a: any) => any +>f.toString(), (a => a) : (a: any) => any +>f.toString() : string +>f.toString : () => string +>f : (a: number) => void +>toString : () => string +>(a => a) : (a: any) => any +>a => a : (a: any) => any +>a : any +>a : any + + f(42) +>f(42) : any +>f : undefined +>42 : 42 +} + diff --git a/tests/baselines/reference/logicalAssignment5(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment5(target=es2020).errors.txt new file mode 100644 index 0000000000000..663162e916547 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=es2020).errors.txt @@ -0,0 +1,51 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(12,12): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(13,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(17,12): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(22,12): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(27,27): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts (6 errors) ==== + function foo1 (f?: (a: number) => void) { + f ??= (a => a) + f(42) + } + + function foo2 (f?: (a: number) => void) { + f ||= (a => a) + f(42) + } + + function foo3 (f?: (a: number) => void) { + f &&= (a => a) + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + f(42) + ~ +!!! error TS2722: Cannot invoke an object which is possibly 'undefined'. + } + + function bar1 (f?: (a: number) => void) { + f ??= (f.toString(), (a => a)) + ~ +!!! error TS2532: Object is possibly 'undefined'. + f(42) + } + + function bar2 (f?: (a: number) => void) { + f ||= (f.toString(), (a => a)) + ~ +!!! error TS2532: Object is possibly 'undefined'. + f(42) + } + + function bar3 (f?: (a: number) => void) { + f &&= (f.toString(), (a => a)) + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + f(42) + ~ +!!! error TS2722: Cannot invoke an object which is possibly 'undefined'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment5(target=es2020).js b/tests/baselines/reference/logicalAssignment5(target=es2020).js new file mode 100644 index 0000000000000..58f3a4553dd70 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=es2020).js @@ -0,0 +1,58 @@ +//// [logicalAssignment5.ts] +function foo1 (f?: (a: number) => void) { + f ??= (a => a) + f(42) +} + +function foo2 (f?: (a: number) => void) { + f ||= (a => a) + f(42) +} + +function foo3 (f?: (a: number) => void) { + f &&= (a => a) + f(42) +} + +function bar1 (f?: (a: number) => void) { + f ??= (f.toString(), (a => a)) + f(42) +} + +function bar2 (f?: (a: number) => void) { + f ||= (f.toString(), (a => a)) + f(42) +} + +function bar3 (f?: (a: number) => void) { + f &&= (f.toString(), (a => a)) + f(42) +} + + +//// [logicalAssignment5.js] +"use strict"; +function foo1(f) { + f ?? (f = (a => a)); + f(42); +} +function foo2(f) { + f || (f = (a => a)); + f(42); +} +function foo3(f) { + f && (f = (a => a)); + f(42); +} +function bar1(f) { + f ?? (f = (f.toString(), (a => a))); + f(42); +} +function bar2(f) { + f || (f = (f.toString(), (a => a))); + f(42); +} +function bar3(f) { + f && (f = (f.toString(), (a => a))); + f(42); +} diff --git a/tests/baselines/reference/logicalAssignment5(target=es2020).symbols b/tests/baselines/reference/logicalAssignment5(target=es2020).symbols new file mode 100644 index 0000000000000..5862d6b68d406 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=es2020).symbols @@ -0,0 +1,90 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts === +function foo1 (f?: (a: number) => void) { +>foo1 : Symbol(foo1, Decl(logicalAssignment5.ts, 0, 0)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 0, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 0, 20)) + + f ??= (a => a) +>f : Symbol(f, Decl(logicalAssignment5.ts, 0, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 1, 11)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 1, 11)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 0, 15)) +} + +function foo2 (f?: (a: number) => void) { +>foo2 : Symbol(foo2, Decl(logicalAssignment5.ts, 3, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 5, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 5, 20)) + + f ||= (a => a) +>f : Symbol(f, Decl(logicalAssignment5.ts, 5, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 6, 11)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 6, 11)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 5, 15)) +} + +function foo3 (f?: (a: number) => void) { +>foo3 : Symbol(foo3, Decl(logicalAssignment5.ts, 8, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 10, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 10, 20)) + + f &&= (a => a) +>f : Symbol(f, Decl(logicalAssignment5.ts, 10, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 11, 11)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 11, 11)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 10, 15)) +} + +function bar1 (f?: (a: number) => void) { +>bar1 : Symbol(bar1, Decl(logicalAssignment5.ts, 13, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 15, 20)) + + f ??= (f.toString(), (a => a)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 16, 26)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 16, 26)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +} + +function bar2 (f?: (a: number) => void) { +>bar2 : Symbol(bar2, Decl(logicalAssignment5.ts, 18, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 20, 20)) + + f ||= (f.toString(), (a => a)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 21, 26)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 21, 26)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +} + +function bar3 (f?: (a: number) => void) { +>bar3 : Symbol(bar3, Decl(logicalAssignment5.ts, 23, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 25, 20)) + + f &&= (f.toString(), (a => a)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +>f.toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +>toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 26, 26)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 26, 26)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +} + diff --git a/tests/baselines/reference/logicalAssignment5(target=es2020).types b/tests/baselines/reference/logicalAssignment5(target=es2020).types new file mode 100644 index 0000000000000..694c3db90a50c --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=es2020).types @@ -0,0 +1,133 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts === +function foo1 (f?: (a: number) => void) { +>foo1 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ??= (a => a) +>f ??= (a => a) : (a: number) => void +>f : ((a: number) => void) | undefined +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function foo2 (f?: (a: number) => void) { +>foo2 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ||= (a => a) +>f ||= (a => a) : (a: number) => void +>f : ((a: number) => void) | undefined +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function foo3 (f?: (a: number) => void) { +>foo3 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f &&= (a => a) +>f &&= (a => a) : ((a: any) => any) | undefined +>f : ((a: number) => void) | undefined +>(a => a) : (a: any) => any +>a => a : (a: any) => any +>a : any +>a : any + + f(42) +>f(42) : any +>f : undefined +>42 : 42 +} + +function bar1 (f?: (a: number) => void) { +>bar1 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ??= (f.toString(), (a => a)) +>f ??= (f.toString(), (a => a)) : (a: number) => void +>f : ((a: number) => void) | undefined +>(f.toString(), (a => a)) : (a: number) => number +>f.toString(), (a => a) : (a: number) => number +>f.toString() : any +>f.toString : any +>f : undefined +>toString : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function bar2 (f?: (a: number) => void) { +>bar2 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ||= (f.toString(), (a => a)) +>f ||= (f.toString(), (a => a)) : (a: number) => void +>f : ((a: number) => void) | undefined +>(f.toString(), (a => a)) : (a: number) => number +>f.toString(), (a => a) : (a: number) => number +>f.toString() : any +>f.toString : any +>f : undefined +>toString : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function bar3 (f?: (a: number) => void) { +>bar3 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f &&= (f.toString(), (a => a)) +>f &&= (f.toString(), (a => a)) : ((a: any) => any) | undefined +>f : ((a: number) => void) | undefined +>(f.toString(), (a => a)) : (a: any) => any +>f.toString(), (a => a) : (a: any) => any +>f.toString() : string +>f.toString : () => string +>f : (a: number) => void +>toString : () => string +>(a => a) : (a: any) => any +>a => a : (a: any) => any +>a : any +>a : any + + f(42) +>f(42) : any +>f : undefined +>42 : 42 +} + diff --git a/tests/baselines/reference/logicalAssignment5(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment5(target=esnext).errors.txt new file mode 100644 index 0000000000000..663162e916547 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=esnext).errors.txt @@ -0,0 +1,51 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(12,12): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(13,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(17,12): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(22,12): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(27,27): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts (6 errors) ==== + function foo1 (f?: (a: number) => void) { + f ??= (a => a) + f(42) + } + + function foo2 (f?: (a: number) => void) { + f ||= (a => a) + f(42) + } + + function foo3 (f?: (a: number) => void) { + f &&= (a => a) + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + f(42) + ~ +!!! error TS2722: Cannot invoke an object which is possibly 'undefined'. + } + + function bar1 (f?: (a: number) => void) { + f ??= (f.toString(), (a => a)) + ~ +!!! error TS2532: Object is possibly 'undefined'. + f(42) + } + + function bar2 (f?: (a: number) => void) { + f ||= (f.toString(), (a => a)) + ~ +!!! error TS2532: Object is possibly 'undefined'. + f(42) + } + + function bar3 (f?: (a: number) => void) { + f &&= (f.toString(), (a => a)) + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + f(42) + ~ +!!! error TS2722: Cannot invoke an object which is possibly 'undefined'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment5(target=esnext).js b/tests/baselines/reference/logicalAssignment5(target=esnext).js new file mode 100644 index 0000000000000..21d965459dc6f --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=esnext).js @@ -0,0 +1,58 @@ +//// [logicalAssignment5.ts] +function foo1 (f?: (a: number) => void) { + f ??= (a => a) + f(42) +} + +function foo2 (f?: (a: number) => void) { + f ||= (a => a) + f(42) +} + +function foo3 (f?: (a: number) => void) { + f &&= (a => a) + f(42) +} + +function bar1 (f?: (a: number) => void) { + f ??= (f.toString(), (a => a)) + f(42) +} + +function bar2 (f?: (a: number) => void) { + f ||= (f.toString(), (a => a)) + f(42) +} + +function bar3 (f?: (a: number) => void) { + f &&= (f.toString(), (a => a)) + f(42) +} + + +//// [logicalAssignment5.js] +"use strict"; +function foo1(f) { + f ??= (a => a); + f(42); +} +function foo2(f) { + f ||= (a => a); + f(42); +} +function foo3(f) { + f &&= (a => a); + f(42); +} +function bar1(f) { + f ??= (f.toString(), (a => a)); + f(42); +} +function bar2(f) { + f ||= (f.toString(), (a => a)); + f(42); +} +function bar3(f) { + f &&= (f.toString(), (a => a)); + f(42); +} diff --git a/tests/baselines/reference/logicalAssignment5(target=esnext).symbols b/tests/baselines/reference/logicalAssignment5(target=esnext).symbols new file mode 100644 index 0000000000000..5862d6b68d406 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=esnext).symbols @@ -0,0 +1,90 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts === +function foo1 (f?: (a: number) => void) { +>foo1 : Symbol(foo1, Decl(logicalAssignment5.ts, 0, 0)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 0, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 0, 20)) + + f ??= (a => a) +>f : Symbol(f, Decl(logicalAssignment5.ts, 0, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 1, 11)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 1, 11)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 0, 15)) +} + +function foo2 (f?: (a: number) => void) { +>foo2 : Symbol(foo2, Decl(logicalAssignment5.ts, 3, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 5, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 5, 20)) + + f ||= (a => a) +>f : Symbol(f, Decl(logicalAssignment5.ts, 5, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 6, 11)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 6, 11)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 5, 15)) +} + +function foo3 (f?: (a: number) => void) { +>foo3 : Symbol(foo3, Decl(logicalAssignment5.ts, 8, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 10, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 10, 20)) + + f &&= (a => a) +>f : Symbol(f, Decl(logicalAssignment5.ts, 10, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 11, 11)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 11, 11)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 10, 15)) +} + +function bar1 (f?: (a: number) => void) { +>bar1 : Symbol(bar1, Decl(logicalAssignment5.ts, 13, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 15, 20)) + + f ??= (f.toString(), (a => a)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 16, 26)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 16, 26)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 15, 15)) +} + +function bar2 (f?: (a: number) => void) { +>bar2 : Symbol(bar2, Decl(logicalAssignment5.ts, 18, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 20, 20)) + + f ||= (f.toString(), (a => a)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 21, 26)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 21, 26)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 20, 15)) +} + +function bar3 (f?: (a: number) => void) { +>bar3 : Symbol(bar3, Decl(logicalAssignment5.ts, 23, 1)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 25, 20)) + + f &&= (f.toString(), (a => a)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +>f.toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --)) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +>toString : Symbol(Function.toString, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 26, 26)) +>a : Symbol(a, Decl(logicalAssignment5.ts, 26, 26)) + + f(42) +>f : Symbol(f, Decl(logicalAssignment5.ts, 25, 15)) +} + diff --git a/tests/baselines/reference/logicalAssignment5(target=esnext).types b/tests/baselines/reference/logicalAssignment5(target=esnext).types new file mode 100644 index 0000000000000..694c3db90a50c --- /dev/null +++ b/tests/baselines/reference/logicalAssignment5(target=esnext).types @@ -0,0 +1,133 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts === +function foo1 (f?: (a: number) => void) { +>foo1 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ??= (a => a) +>f ??= (a => a) : (a: number) => void +>f : ((a: number) => void) | undefined +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function foo2 (f?: (a: number) => void) { +>foo2 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ||= (a => a) +>f ||= (a => a) : (a: number) => void +>f : ((a: number) => void) | undefined +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function foo3 (f?: (a: number) => void) { +>foo3 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f &&= (a => a) +>f &&= (a => a) : ((a: any) => any) | undefined +>f : ((a: number) => void) | undefined +>(a => a) : (a: any) => any +>a => a : (a: any) => any +>a : any +>a : any + + f(42) +>f(42) : any +>f : undefined +>42 : 42 +} + +function bar1 (f?: (a: number) => void) { +>bar1 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ??= (f.toString(), (a => a)) +>f ??= (f.toString(), (a => a)) : (a: number) => void +>f : ((a: number) => void) | undefined +>(f.toString(), (a => a)) : (a: number) => number +>f.toString(), (a => a) : (a: number) => number +>f.toString() : any +>f.toString : any +>f : undefined +>toString : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function bar2 (f?: (a: number) => void) { +>bar2 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f ||= (f.toString(), (a => a)) +>f ||= (f.toString(), (a => a)) : (a: number) => void +>f : ((a: number) => void) | undefined +>(f.toString(), (a => a)) : (a: number) => number +>f.toString(), (a => a) : (a: number) => number +>f.toString() : any +>f.toString : any +>f : undefined +>toString : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number + + f(42) +>f(42) : void +>f : (a: number) => void +>42 : 42 +} + +function bar3 (f?: (a: number) => void) { +>bar3 : (f?: ((a: number) => void) | undefined) => void +>f : ((a: number) => void) | undefined +>a : number + + f &&= (f.toString(), (a => a)) +>f &&= (f.toString(), (a => a)) : ((a: any) => any) | undefined +>f : ((a: number) => void) | undefined +>(f.toString(), (a => a)) : (a: any) => any +>f.toString(), (a => a) : (a: any) => any +>f.toString() : string +>f.toString : () => string +>f : (a: number) => void +>toString : () => string +>(a => a) : (a: any) => any +>a => a : (a: any) => any +>a : any +>a : any + + f(42) +>f(42) : any +>f : undefined +>42 : 42 +} + diff --git a/tests/baselines/reference/logicalAssignment6(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment6(target=es2015).errors.txt new file mode 100644 index 0000000000000..0af71a2ba4eaa --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=es2015).errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts(10,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts(10,42): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts (2 errors) ==== + function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= (results1 ||= [])).push(100); + } + + function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= (results1 ??= [])).push(100); + } + + function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= (results1 &&= [])).push(100); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~ +!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment6(target=es2015).js b/tests/baselines/reference/logicalAssignment6(target=es2015).js new file mode 100644 index 0000000000000..a0424da1778c2 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=es2015).js @@ -0,0 +1,24 @@ +//// [logicalAssignment6.ts] +function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= (results1 ||= [])).push(100); +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= (results1 ??= [])).push(100); +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= (results1 &&= [])).push(100); +} + +//// [logicalAssignment6.js] +"use strict"; +function foo1(results, results1) { + (results || (results = (results1 || (results1 = [])))).push(100); +} +function foo2(results, results1) { + (results !== null && results !== void 0 ? results : (results = (results1 !== null && results1 !== void 0 ? results1 : (results1 = [])))).push(100); +} +function foo3(results, results1) { + (results && (results = (results1 && (results1 = [])))).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment6(target=es2015).symbols b/tests/baselines/reference/logicalAssignment6(target=es2015).symbols new file mode 100644 index 0000000000000..d91ebbaa4508d --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=es2015).symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment6.ts, 0, 0)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 0, 44)) + + (results ||= (results1 ||= [])).push(100); +>(results ||= (results1 ||= [])).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 0, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment6.ts, 2, 1)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 4, 44)) + + (results ??= (results1 ??= [])).push(100); +>(results ??= (results1 ??= [])).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 4, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment6.ts, 6, 1)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 8, 44)) + + (results &&= (results1 &&= [])).push(100); +>(results &&= (results1 &&= [])).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 8, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment6(target=es2015).types b/tests/baselines/reference/logicalAssignment6(target=es2015).types new file mode 100644 index 0000000000000..3cf295045a6d9 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=es2015).types @@ -0,0 +1,57 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ||= (results1 ||= [])).push(100); +>(results ||= (results1 ||= [])).push(100) : number +>(results ||= (results1 ||= [])).push : (...items: number[]) => number +>(results ||= (results1 ||= [])) : number[] +>results ||= (results1 ||= []) : number[] +>results : number[] | undefined +>(results1 ||= []) : number[] +>results1 ||= [] : number[] +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ??= (results1 ??= [])).push(100); +>(results ??= (results1 ??= [])).push(100) : number +>(results ??= (results1 ??= [])).push : (...items: number[]) => number +>(results ??= (results1 ??= [])) : number[] +>results ??= (results1 ??= []) : number[] +>results : number[] | undefined +>(results1 ??= []) : number[] +>results1 ??= [] : number[] +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results &&= (results1 &&= [])).push(100); +>(results &&= (results1 &&= [])).push(100) : number +>(results &&= (results1 &&= [])).push : (...items: never[]) => number +>(results &&= (results1 &&= [])) : never[] | undefined +>results &&= (results1 &&= []) : never[] | undefined +>results : number[] | undefined +>(results1 &&= []) : never[] | undefined +>results1 &&= [] : never[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: never[]) => number +>100 : 100 +} diff --git a/tests/baselines/reference/logicalAssignment6(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment6(target=es2020).errors.txt new file mode 100644 index 0000000000000..0af71a2ba4eaa --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=es2020).errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts(10,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts(10,42): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts (2 errors) ==== + function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= (results1 ||= [])).push(100); + } + + function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= (results1 ??= [])).push(100); + } + + function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= (results1 &&= [])).push(100); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~ +!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment6(target=es2020).js b/tests/baselines/reference/logicalAssignment6(target=es2020).js new file mode 100644 index 0000000000000..66852828beebe --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=es2020).js @@ -0,0 +1,24 @@ +//// [logicalAssignment6.ts] +function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= (results1 ||= [])).push(100); +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= (results1 ??= [])).push(100); +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= (results1 &&= [])).push(100); +} + +//// [logicalAssignment6.js] +"use strict"; +function foo1(results, results1) { + (results || (results = (results1 || (results1 = [])))).push(100); +} +function foo2(results, results1) { + (results ?? (results = (results1 ?? (results1 = [])))).push(100); +} +function foo3(results, results1) { + (results && (results = (results1 && (results1 = [])))).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment6(target=es2020).symbols b/tests/baselines/reference/logicalAssignment6(target=es2020).symbols new file mode 100644 index 0000000000000..d91ebbaa4508d --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=es2020).symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment6.ts, 0, 0)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 0, 44)) + + (results ||= (results1 ||= [])).push(100); +>(results ||= (results1 ||= [])).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 0, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment6.ts, 2, 1)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 4, 44)) + + (results ??= (results1 ??= [])).push(100); +>(results ??= (results1 ??= [])).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 4, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment6.ts, 6, 1)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 8, 44)) + + (results &&= (results1 &&= [])).push(100); +>(results &&= (results1 &&= [])).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 8, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment6(target=es2020).types b/tests/baselines/reference/logicalAssignment6(target=es2020).types new file mode 100644 index 0000000000000..3cf295045a6d9 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=es2020).types @@ -0,0 +1,57 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ||= (results1 ||= [])).push(100); +>(results ||= (results1 ||= [])).push(100) : number +>(results ||= (results1 ||= [])).push : (...items: number[]) => number +>(results ||= (results1 ||= [])) : number[] +>results ||= (results1 ||= []) : number[] +>results : number[] | undefined +>(results1 ||= []) : number[] +>results1 ||= [] : number[] +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ??= (results1 ??= [])).push(100); +>(results ??= (results1 ??= [])).push(100) : number +>(results ??= (results1 ??= [])).push : (...items: number[]) => number +>(results ??= (results1 ??= [])) : number[] +>results ??= (results1 ??= []) : number[] +>results : number[] | undefined +>(results1 ??= []) : number[] +>results1 ??= [] : number[] +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results &&= (results1 &&= [])).push(100); +>(results &&= (results1 &&= [])).push(100) : number +>(results &&= (results1 &&= [])).push : (...items: never[]) => number +>(results &&= (results1 &&= [])) : never[] | undefined +>results &&= (results1 &&= []) : never[] | undefined +>results : number[] | undefined +>(results1 &&= []) : never[] | undefined +>results1 &&= [] : never[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: never[]) => number +>100 : 100 +} diff --git a/tests/baselines/reference/logicalAssignment6(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment6(target=esnext).errors.txt new file mode 100644 index 0000000000000..0af71a2ba4eaa --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=esnext).errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts(10,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts(10,42): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts (2 errors) ==== + function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= (results1 ||= [])).push(100); + } + + function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= (results1 ??= [])).push(100); + } + + function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= (results1 &&= [])).push(100); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~ +!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment6(target=esnext).js b/tests/baselines/reference/logicalAssignment6(target=esnext).js new file mode 100644 index 0000000000000..9d209c9e30159 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=esnext).js @@ -0,0 +1,24 @@ +//// [logicalAssignment6.ts] +function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= (results1 ||= [])).push(100); +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= (results1 ??= [])).push(100); +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= (results1 &&= [])).push(100); +} + +//// [logicalAssignment6.js] +"use strict"; +function foo1(results, results1) { + (results ||= (results1 ||= [])).push(100); +} +function foo2(results, results1) { + (results ??= (results1 ??= [])).push(100); +} +function foo3(results, results1) { + (results &&= (results1 &&= [])).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment6(target=esnext).symbols b/tests/baselines/reference/logicalAssignment6(target=esnext).symbols new file mode 100644 index 0000000000000..d91ebbaa4508d --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=esnext).symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment6.ts, 0, 0)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 0, 44)) + + (results ||= (results1 ||= [])).push(100); +>(results ||= (results1 ||= [])).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 0, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment6.ts, 2, 1)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 4, 44)) + + (results ??= (results1 ??= [])).push(100); +>(results ??= (results1 ??= [])).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 4, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment6.ts, 6, 1)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 8, 44)) + + (results &&= (results1 &&= [])).push(100); +>(results &&= (results1 &&= [])).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment6.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment6.ts, 8, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment6(target=esnext).types b/tests/baselines/reference/logicalAssignment6(target=esnext).types new file mode 100644 index 0000000000000..3cf295045a6d9 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment6(target=esnext).types @@ -0,0 +1,57 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ||= (results1 ||= [])).push(100); +>(results ||= (results1 ||= [])).push(100) : number +>(results ||= (results1 ||= [])).push : (...items: number[]) => number +>(results ||= (results1 ||= [])) : number[] +>results ||= (results1 ||= []) : number[] +>results : number[] | undefined +>(results1 ||= []) : number[] +>results1 ||= [] : number[] +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ??= (results1 ??= [])).push(100); +>(results ??= (results1 ??= [])).push(100) : number +>(results ??= (results1 ??= [])).push : (...items: number[]) => number +>(results ??= (results1 ??= [])) : number[] +>results ??= (results1 ??= []) : number[] +>results : number[] | undefined +>(results1 ??= []) : number[] +>results1 ??= [] : number[] +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results &&= (results1 &&= [])).push(100); +>(results &&= (results1 &&= [])).push(100) : number +>(results &&= (results1 &&= [])).push : (...items: never[]) => number +>(results &&= (results1 &&= [])) : never[] | undefined +>results &&= (results1 &&= []) : never[] | undefined +>results : number[] | undefined +>(results1 &&= []) : never[] | undefined +>results1 &&= [] : never[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: never[]) => number +>100 : 100 +} diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt new file mode 100644 index 0000000000000..4eec0ce2d1128 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt @@ -0,0 +1,29 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ==== + function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= results1 ||= []).push(100); + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + } + + function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= results1 ??= []).push(100); + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + } + + function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= results1 &&= []).push(100); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + ~~~ +!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).js b/tests/baselines/reference/logicalAssignment7(target=es2015).js new file mode 100644 index 0000000000000..4ac2a4159b763 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).js @@ -0,0 +1,25 @@ +//// [logicalAssignment7.ts] +function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= results1 ||= []).push(100); +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= results1 ??= []).push(100); +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= results1 &&= []).push(100); +} + +//// [logicalAssignment7.js] +"use strict"; +function foo1(results, results1) { + (results || (results = results1) || (results || (results = results1) = [])).push(100); +} +function foo2(results, results1) { + var _a; + ((_a = results !== null && results !== void 0 ? results : (results = results1)) !== null && _a !== void 0 ? _a : (results !== null && results !== void 0 ? results : (results = results1) = [])).push(100); +} +function foo3(results, results1) { + (results && (results = results1) && (results && (results = results1) = [])).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).symbols b/tests/baselines/reference/logicalAssignment7(target=es2015).symbols new file mode 100644 index 0000000000000..7bde5161df5a7 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment7.ts, 0, 0)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 0, 44)) + + (results ||= results1 ||= []).push(100); +>(results ||= results1 ||= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 0, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment7.ts, 2, 1)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 4, 44)) + + (results ??= results1 ??= []).push(100); +>(results ??= results1 ??= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 4, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment7.ts, 6, 1)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 8, 44)) + + (results &&= results1 &&= []).push(100); +>(results &&= results1 &&= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 8, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).types b/tests/baselines/reference/logicalAssignment7(target=es2015).types new file mode 100644 index 0000000000000..b46c67c14bb68 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).types @@ -0,0 +1,54 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ||= results1 ||= []).push(100); +>(results ||= results1 ||= []).push(100) : number +>(results ||= results1 ||= []).push : (...items: number[]) => number +>(results ||= results1 ||= []) : number[] +>results ||= results1 ||= [] : number[] +>results ||= results1 : number[] | undefined +>results : number[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ??= results1 ??= []).push(100); +>(results ??= results1 ??= []).push(100) : number +>(results ??= results1 ??= []).push : (...items: number[]) => number +>(results ??= results1 ??= []) : number[] +>results ??= results1 ??= [] : number[] +>results ??= results1 : number[] | undefined +>results : number[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results &&= results1 &&= []).push(100); +>(results &&= results1 &&= []).push(100) : number +>(results &&= results1 &&= []).push : (...items: never[]) => number +>(results &&= results1 &&= []) : never[] | undefined +>results &&= results1 &&= [] : never[] | undefined +>results &&= results1 : number[] | undefined +>results : number[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: never[]) => number +>100 : 100 +} diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt new file mode 100644 index 0000000000000..4eec0ce2d1128 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt @@ -0,0 +1,29 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ==== + function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= results1 ||= []).push(100); + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + } + + function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= results1 ??= []).push(100); + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + } + + function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= results1 &&= []).push(100); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + ~~~ +!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).js b/tests/baselines/reference/logicalAssignment7(target=es2020).js new file mode 100644 index 0000000000000..8c0438acca6d3 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).js @@ -0,0 +1,24 @@ +//// [logicalAssignment7.ts] +function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= results1 ||= []).push(100); +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= results1 ??= []).push(100); +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= results1 &&= []).push(100); +} + +//// [logicalAssignment7.js] +"use strict"; +function foo1(results, results1) { + (results || (results = results1) || (results || (results = results1) = [])).push(100); +} +function foo2(results, results1) { + (results ?? (results = results1) ?? (results ?? (results = results1) = [])).push(100); +} +function foo3(results, results1) { + (results && (results = results1) && (results && (results = results1) = [])).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).symbols b/tests/baselines/reference/logicalAssignment7(target=es2020).symbols new file mode 100644 index 0000000000000..7bde5161df5a7 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment7.ts, 0, 0)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 0, 44)) + + (results ||= results1 ||= []).push(100); +>(results ||= results1 ||= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 0, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment7.ts, 2, 1)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 4, 44)) + + (results ??= results1 ??= []).push(100); +>(results ??= results1 ??= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 4, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment7.ts, 6, 1)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 8, 44)) + + (results &&= results1 &&= []).push(100); +>(results &&= results1 &&= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 8, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).types b/tests/baselines/reference/logicalAssignment7(target=es2020).types new file mode 100644 index 0000000000000..b46c67c14bb68 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).types @@ -0,0 +1,54 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ||= results1 ||= []).push(100); +>(results ||= results1 ||= []).push(100) : number +>(results ||= results1 ||= []).push : (...items: number[]) => number +>(results ||= results1 ||= []) : number[] +>results ||= results1 ||= [] : number[] +>results ||= results1 : number[] | undefined +>results : number[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ??= results1 ??= []).push(100); +>(results ??= results1 ??= []).push(100) : number +>(results ??= results1 ??= []).push : (...items: number[]) => number +>(results ??= results1 ??= []) : number[] +>results ??= results1 ??= [] : number[] +>results ??= results1 : number[] | undefined +>results : number[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results &&= results1 &&= []).push(100); +>(results &&= results1 &&= []).push(100) : number +>(results &&= results1 &&= []).push : (...items: never[]) => number +>(results &&= results1 &&= []) : never[] | undefined +>results &&= results1 &&= [] : never[] | undefined +>results &&= results1 : number[] | undefined +>results : number[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: never[]) => number +>100 : 100 +} diff --git a/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt new file mode 100644 index 0000000000000..4eec0ce2d1128 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt @@ -0,0 +1,29 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ==== + function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= results1 ||= []).push(100); + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + } + + function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= results1 ??= []).push(100); + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + } + + function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= results1 &&= []).push(100); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. + ~~~ +!!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment7(target=esnext).js b/tests/baselines/reference/logicalAssignment7(target=esnext).js new file mode 100644 index 0000000000000..1b83f24c7affd --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=esnext).js @@ -0,0 +1,24 @@ +//// [logicalAssignment7.ts] +function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= results1 ||= []).push(100); +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= results1 ??= []).push(100); +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= results1 &&= []).push(100); +} + +//// [logicalAssignment7.js] +"use strict"; +function foo1(results, results1) { + (results ||= results1 ||= []).push(100); +} +function foo2(results, results1) { + (results ??= results1 ??= []).push(100); +} +function foo3(results, results1) { + (results &&= results1 &&= []).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment7(target=esnext).symbols b/tests/baselines/reference/logicalAssignment7(target=esnext).symbols new file mode 100644 index 0000000000000..7bde5161df5a7 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=esnext).symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment7.ts, 0, 0)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 0, 44)) + + (results ||= results1 ||= []).push(100); +>(results ||= results1 ||= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 0, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 0, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment7.ts, 2, 1)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 4, 44)) + + (results ??= results1 ??= []).push(100); +>(results ??= results1 ??= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 4, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 4, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment7.ts, 6, 1)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 8, 44)) + + (results &&= results1 &&= []).push(100); +>(results &&= results1 &&= []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment7.ts, 8, 14)) +>results1 : Symbol(results1, Decl(logicalAssignment7.ts, 8, 44)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment7(target=esnext).types b/tests/baselines/reference/logicalAssignment7(target=esnext).types new file mode 100644 index 0000000000000..b46c67c14bb68 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment7(target=esnext).types @@ -0,0 +1,54 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts === +function foo1(results: number[] | undefined, results1: number[] | undefined) { +>foo1 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ||= results1 ||= []).push(100); +>(results ||= results1 ||= []).push(100) : number +>(results ||= results1 ||= []).push : (...items: number[]) => number +>(results ||= results1 ||= []) : number[] +>results ||= results1 ||= [] : number[] +>results ||= results1 : number[] | undefined +>results : number[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { +>foo2 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results ??= results1 ??= []).push(100); +>(results ??= results1 ??= []).push(100) : number +>(results ??= results1 ??= []).push : (...items: number[]) => number +>(results ??= results1 ??= []) : number[] +>results ??= results1 ??= [] : number[] +>results ??= results1 : number[] | undefined +>results : number[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { +>foo3 : (results: number[] | undefined, results1: number[] | undefined) => void +>results : number[] | undefined +>results1 : number[] | undefined + + (results &&= results1 &&= []).push(100); +>(results &&= results1 &&= []).push(100) : number +>(results &&= results1 &&= []).push : (...items: never[]) => number +>(results &&= results1 &&= []) : never[] | undefined +>results &&= results1 &&= [] : never[] | undefined +>results &&= results1 : number[] | undefined +>results : number[] | undefined +>results1 : number[] | undefined +>[] : never[] +>push : (...items: never[]) => number +>100 : 100 +} diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts index 69cd3aad50ba0..b142f0ece1d12 100644 --- a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts @@ -7,4 +7,24 @@ function foo1(results: number[] | undefined) { function foo2(results: number[] | undefined) { (results ??= []).push(100); +} + +function foo3(results: number[] | undefined) { + results ||= []; + results.push(100); +} + +function foo4(results: number[] | undefined) { + results ||= []; + results.push(100); +} + +interface ThingWithOriginal { + name: string; + original?: ThingWithOriginal +} +function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { + if (thing &&= thing.original) { + console.log(thing.name); + } } \ No newline at end of file diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts index 08176cce75b8e..f9e4317b8ee84 100644 --- a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts @@ -1,7 +1,32 @@ // @strict: true // @target: esnext, es2020, es2015 -function foo (f: (a: number) => void | undefined) { - f ??= (a => a++) - f ||= (a => a++) +function foo1 (f?: (a: number) => void) { + f ??= (a => a) + f(42) +} + +function foo2 (f?: (a: number) => void) { + f ||= (a => a) + f(42) +} + +function foo3 (f?: (a: number) => void) { + f &&= (a => a) + f(42) +} + +function bar1 (f?: (a: number) => void) { + f ??= (f.toString(), (a => a)) + f(42) +} + +function bar2 (f?: (a: number) => void) { + f ||= (f.toString(), (a => a)) + f(42) +} + +function bar3 (f?: (a: number) => void) { + f &&= (f.toString(), (a => a)) + f(42) } diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts new file mode 100644 index 0000000000000..3fa7987f72081 --- /dev/null +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment6.ts @@ -0,0 +1,14 @@ +// @strict: true +// @target: esnext, es2020, es2015 + +function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= (results1 ||= [])).push(100); +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= (results1 ??= [])).push(100); +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= (results1 &&= [])).push(100); +} \ No newline at end of file diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts new file mode 100644 index 0000000000000..78812fa0b73f6 --- /dev/null +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts @@ -0,0 +1,14 @@ +// @strict: true +// @target: esnext, es2020, es2015 + +function foo1(results: number[] | undefined, results1: number[] | undefined) { + (results ||= results1 ||= []).push(100); +} + +function foo2(results: number[] | undefined, results1: number[] | undefined) { + (results ??= results1 ??= []).push(100); +} + +function foo3(results: number[] | undefined, results1: number[] | undefined) { + (results &&= results1 &&= []).push(100); +} \ No newline at end of file From ede6214157990584c678bbdb8c55f1b397a8f627 Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 2 Apr 2020 03:01:19 +0800 Subject: [PATCH 06/24] Add more check --- src/compiler/binder.ts | 33 ++++++++++++++----- .../logicalAssignment/logicalAssignment4.ts | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 5e57002094154..a7272d8a7e0d7 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -905,6 +905,9 @@ namespace ts { function isNarrowingBinaryExpression(expr: BinaryExpression) { switch (expr.operatorToken.kind) { case SyntaxKind.EqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return containsNarrowableReference(expr.left); case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: @@ -1052,6 +1055,15 @@ namespace ts { } } + function isTopLevelLogicalAssignmentExpression(node: Node): boolean { + while (isParenthesizedExpression(node.parent)) { + node = node.parent; + } + return !isStatementCondition(node) && + !isLogicalAssignmentExpressioin(node.parent) && + !(isOptionalChain(node.parent) && node.parent.expression === node); + } + function isTopLevelLogicalExpression(node: Node): boolean { while (isParenthesizedExpression(node.parent) || isPrefixUnaryExpression(node.parent) && node.parent.operator === SyntaxKind.ExclamationToken) { @@ -1174,23 +1186,19 @@ namespace ts { currentFlow = finishFlowLabel(postIfLabel); } - function bindLogicalAssignmentExpression(node: BinaryExpression) { + function bindLogicalAssignmentExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { const preRightLabel = createBranchLabel(); - const postExpressionLabel = createBranchLabel(); - if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) { - bindCondition(node.left, preRightLabel, postExpressionLabel); + bindCondition(node.left, preRightLabel, falseTarget); } else { - bindCondition(node.left, postExpressionLabel, preRightLabel); + bindCondition(node.left, trueTarget, preRightLabel); } currentFlow = finishFlowLabel(preRightLabel); bind(node.operatorToken); - bind(node.right); + doWithConditionalBranches(bind, node.right, trueTarget, falseTarget); bindAssignmentTargetFlow(node.left); - - currentFlow = finishFlowLabel(postExpressionLabel); } function bindReturnOrThrow(node: ReturnStatement | ThrowStatement): void { @@ -1546,7 +1554,14 @@ namespace ts { completeNode(); } else if(isLogicalAssignmentOperator(operator)) { - bindLogicalAssignmentExpression(node); + if (isTopLevelLogicalAssignmentExpression(node)) { + const postExpressionLabel = createBranchLabel(); + bindLogicalAssignmentExpression(node, postExpressionLabel, postExpressionLabel); + currentFlow = finishFlowLabel(postExpressionLabel); + } + else { + bindLogicalAssignmentExpression(node, currentTrueTarget!, currentFalseTarget!); + } completeNode(); } else { diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts index b142f0ece1d12..3c35d94b336ee 100644 --- a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts @@ -1,5 +1,6 @@ // @strict: true // @target: esnext, es2020, es2015 +// @allowUnreachableCode: false function foo1(results: number[] | undefined) { (results ||= []).push(100); From 944bcf8459efe8eb678e0fde8e6fcb78add26eeb Mon Sep 17 00:00:00 2001 From: Wenlu Wang Date: Thu, 2 Apr 2020 10:29:28 +0800 Subject: [PATCH 07/24] Update src/compiler/transformers/utilities.ts Co-Authored-By: Daniel Rosenwasser --- src/compiler/transformers/utilities.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index a54d1d05e5d73..b4d01704f612b 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -282,7 +282,8 @@ namespace ts { export 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 + // `super` cannot be captured as it's not a real variable + return !isIdentifier(expression) && expression.kind !== SyntaxKind.ThisKeyword && expression.kind !== SyntaxKind.SuperKeyword; From ff4fca527dab06e89f15c862b9e27de77a3c84ae Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 2 Apr 2020 15:33:39 +0800 Subject: [PATCH 08/24] Fix cfa --- src/compiler/binder.ts | 14 ++++--- src/compiler/utilities.ts | 2 +- .../logicalAssignment1(target=es2015).types | 10 ++--- .../logicalAssignment1(target=es2020).types | 10 ++--- .../logicalAssignment1(target=esnext).types | 10 ++--- .../logicalAssignment2(target=es2015).types | 38 +++++++++---------- .../logicalAssignment2(target=es2020).types | 38 +++++++++---------- .../logicalAssignment2(target=esnext).types | 38 +++++++++---------- .../logicalAssignment3(target=es2015).types | 22 +++++------ .../logicalAssignment3(target=es2020).types | 22 +++++------ .../logicalAssignment3(target=esnext).types | 22 +++++------ .../logicalAssignment5(target=es2015).types | 8 ++-- .../logicalAssignment5(target=es2020).types | 8 ++-- .../logicalAssignment5(target=esnext).types | 8 ++-- 14 files changed, 126 insertions(+), 124 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index a7272d8a7e0d7..599338b150543 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -932,6 +932,9 @@ namespace ts { case SyntaxKind.BinaryExpression: switch ((expr).operatorToken.kind) { case SyntaxKind.EqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return isNarrowableOperand((expr).left); case SyntaxKind.CommaToken: return isNarrowableOperand((expr).right); @@ -1047,7 +1050,7 @@ namespace ts { function isLogicalAssignmentExpressioin(node: Node) { while (true) { if (isParenthesizedExpression(node)) { - node = node.expression + node = node.expression; } else { return isBinaryExpression(node) && isLogicalAssignmentOperator(node.operatorToken.kind); @@ -1194,11 +1197,14 @@ namespace ts { else { bindCondition(node.left, trueTarget, preRightLabel); } - currentFlow = finishFlowLabel(preRightLabel); bind(node.operatorToken); + doWithConditionalBranches(bind, node.right, trueTarget, falseTarget); bindAssignmentTargetFlow(node.left); + + addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); } function bindReturnOrThrow(node: ReturnStatement | ThrowStatement): void { @@ -1488,10 +1494,6 @@ namespace ts { } function bindBinaryExpressionFlow(node: BinaryExpression) { - const flow = currentFlow - if (flow) { - - } const workStacks: { expr: BinaryExpression[], state: BindBinaryExpressionFlowState[], diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4448e0f18bb27..58a6933429f48 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2594,7 +2594,7 @@ namespace ts { switch (parent.kind) { case SyntaxKind.BinaryExpression: const binaryOperator = (parent).operatorToken.kind; - return isAssignmentOperator(binaryOperator) && (parent).left === node ? + return isAssignmentOperator(binaryOperator) && !isLogicalAssignmentOperator(binaryOperator) && (parent).left === node ? binaryOperator === SyntaxKind.EqualsToken ? AssignmentKind.Definite : AssignmentKind.Compound : AssignmentKind.None; case SyntaxKind.PrefixUnaryExpression: diff --git a/tests/baselines/reference/logicalAssignment1(target=es2015).types b/tests/baselines/reference/logicalAssignment1(target=es2015).types index 98bae7b837cfc..29a224ecef79b 100644 --- a/tests/baselines/reference/logicalAssignment1(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment1(target=es2015).types @@ -60,16 +60,16 @@ f ??= 42 g &&= 42 >g &&= 42 : 0 | 42 ->g : number +>g : 0 | 1 | 42 >42 : 42 h ||= 42 ->h ||= 42 : number ->h : number +>h ||= 42 : 1 | 42 +>h : 0 | 1 | 42 >42 : 42 i ??= 42 ->i ??= 42 : number ->i : number +>i ??= 42 : 0 | 1 | 42 +>i : 0 | 1 | 42 >42 : 42 diff --git a/tests/baselines/reference/logicalAssignment1(target=es2020).types b/tests/baselines/reference/logicalAssignment1(target=es2020).types index 98bae7b837cfc..29a224ecef79b 100644 --- a/tests/baselines/reference/logicalAssignment1(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment1(target=es2020).types @@ -60,16 +60,16 @@ f ??= 42 g &&= 42 >g &&= 42 : 0 | 42 ->g : number +>g : 0 | 1 | 42 >42 : 42 h ||= 42 ->h ||= 42 : number ->h : number +>h ||= 42 : 1 | 42 +>h : 0 | 1 | 42 >42 : 42 i ??= 42 ->i ??= 42 : number ->i : number +>i ??= 42 : 0 | 1 | 42 +>i : 0 | 1 | 42 >42 : 42 diff --git a/tests/baselines/reference/logicalAssignment1(target=esnext).types b/tests/baselines/reference/logicalAssignment1(target=esnext).types index 98bae7b837cfc..29a224ecef79b 100644 --- a/tests/baselines/reference/logicalAssignment1(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment1(target=esnext).types @@ -60,16 +60,16 @@ f ??= 42 g &&= 42 >g &&= 42 : 0 | 42 ->g : number +>g : 0 | 1 | 42 >42 : 42 h ||= 42 ->h ||= 42 : number ->h : number +>h ||= 42 : 1 | 42 +>h : 0 | 1 | 42 >42 : 42 i ??= 42 ->i ??= 42 : number ->i : number +>i ??= 42 : 0 | 1 | 42 +>i : 0 | 1 | 42 >42 : 42 diff --git a/tests/baselines/reference/logicalAssignment2(target=es2015).types b/tests/baselines/reference/logicalAssignment2(target=es2015).types index e0940ed680600..53090c51e59e9 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment2(target=es2015).types @@ -30,34 +30,34 @@ declare const c: A a.baz &&= result.baz >a.baz &&= result.baz : "" | 0 | 1 | 42 | undefined ->a.baz : string | number | undefined +>a.baz : "" | 0 | 1 | 42 | undefined >a : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined b.baz ||= result.baz ->b.baz ||= result.baz : string | number | undefined ->b.baz : string | number | undefined +>b.baz ||= result.baz : "" | 0 | 1 | 42 | undefined +>b.baz : "" | 0 | 1 | 42 | undefined >b : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined c.baz ??= result.baz ->c.baz ??= result.baz : string | number | undefined ->c.baz : string | number | undefined +>c.baz ??= result.baz : "" | 0 | 1 | 42 | undefined +>c.baz : "" | 0 | 1 | 42 | undefined >c : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined a.foo["baz"] &&= result.foo.baz >a.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined ->a.foo["baz"] : string | number | undefined +>a.foo["baz"] : "" | 0 | 1 | 42 | undefined >a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >a : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } @@ -70,7 +70,7 @@ a.foo["baz"] &&= result.foo.baz b.foo["baz"] &&= result.foo.baz >b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined ->b.foo["baz"] : string | number | undefined +>b.foo["baz"] : "" | 0 | 1 | 42 | undefined >b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >b : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } @@ -83,7 +83,7 @@ b.foo["baz"] &&= result.foo.baz c.foo["baz"] &&= result.foo.baz >c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined ->c.foo["baz"] : string | number | undefined +>c.foo["baz"] : "" | 0 | 1 | 42 | undefined >c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >c : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } @@ -96,14 +96,14 @@ c.foo["baz"] &&= result.foo.baz a.foo.bar().baz &&= result.foo.bar().baz >a.foo.bar().baz &&= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined ->a.foo.bar().baz : string | number | undefined +>a.foo.bar().baz : "" | 0 | 1 | 42 | undefined >a.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >a.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } >a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >a : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >bar : () => { baz: "" | 0 | 1 | 42 | undefined; } ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.foo.bar().baz : "" | 0 | 1 | 42 | undefined >result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } @@ -114,15 +114,15 @@ a.foo.bar().baz &&= result.foo.bar().baz >baz : "" | 0 | 1 | 42 | undefined b.foo.bar().baz ||= result.foo.bar().baz ->b.foo.bar().baz ||= result.foo.bar().baz : string | number | undefined ->b.foo.bar().baz : string | number | undefined +>b.foo.bar().baz ||= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>b.foo.bar().baz : "" | 0 | 1 | 42 | undefined >b.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >b.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } >b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >b : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >bar : () => { baz: "" | 0 | 1 | 42 | undefined; } ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.foo.bar().baz : "" | 0 | 1 | 42 | undefined >result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } @@ -133,15 +133,15 @@ b.foo.bar().baz ||= result.foo.bar().baz >baz : "" | 0 | 1 | 42 | undefined c.foo.bar().baz ??= result.foo.bar().baz ->c.foo.bar().baz ??= result.foo.bar().baz : string | number | undefined ->c.foo.bar().baz : string | number | undefined +>c.foo.bar().baz ??= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>c.foo.bar().baz : "" | 0 | 1 | 42 | undefined >c.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >c.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } >c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >c : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >bar : () => { baz: "" | 0 | 1 | 42 | undefined; } ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.foo.bar().baz : "" | 0 | 1 | 42 | undefined >result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } diff --git a/tests/baselines/reference/logicalAssignment2(target=es2020).types b/tests/baselines/reference/logicalAssignment2(target=es2020).types index e0940ed680600..53090c51e59e9 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment2(target=es2020).types @@ -30,34 +30,34 @@ declare const c: A a.baz &&= result.baz >a.baz &&= result.baz : "" | 0 | 1 | 42 | undefined ->a.baz : string | number | undefined +>a.baz : "" | 0 | 1 | 42 | undefined >a : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined b.baz ||= result.baz ->b.baz ||= result.baz : string | number | undefined ->b.baz : string | number | undefined +>b.baz ||= result.baz : "" | 0 | 1 | 42 | undefined +>b.baz : "" | 0 | 1 | 42 | undefined >b : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined c.baz ??= result.baz ->c.baz ??= result.baz : string | number | undefined ->c.baz : string | number | undefined +>c.baz ??= result.baz : "" | 0 | 1 | 42 | undefined +>c.baz : "" | 0 | 1 | 42 | undefined >c : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined a.foo["baz"] &&= result.foo.baz >a.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined ->a.foo["baz"] : string | number | undefined +>a.foo["baz"] : "" | 0 | 1 | 42 | undefined >a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >a : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } @@ -70,7 +70,7 @@ a.foo["baz"] &&= result.foo.baz b.foo["baz"] &&= result.foo.baz >b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined ->b.foo["baz"] : string | number | undefined +>b.foo["baz"] : "" | 0 | 1 | 42 | undefined >b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >b : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } @@ -83,7 +83,7 @@ b.foo["baz"] &&= result.foo.baz c.foo["baz"] &&= result.foo.baz >c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined ->c.foo["baz"] : string | number | undefined +>c.foo["baz"] : "" | 0 | 1 | 42 | undefined >c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >c : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } @@ -96,14 +96,14 @@ c.foo["baz"] &&= result.foo.baz a.foo.bar().baz &&= result.foo.bar().baz >a.foo.bar().baz &&= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined ->a.foo.bar().baz : string | number | undefined +>a.foo.bar().baz : "" | 0 | 1 | 42 | undefined >a.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >a.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } >a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >a : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >bar : () => { baz: "" | 0 | 1 | 42 | undefined; } ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.foo.bar().baz : "" | 0 | 1 | 42 | undefined >result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } @@ -114,15 +114,15 @@ a.foo.bar().baz &&= result.foo.bar().baz >baz : "" | 0 | 1 | 42 | undefined b.foo.bar().baz ||= result.foo.bar().baz ->b.foo.bar().baz ||= result.foo.bar().baz : string | number | undefined ->b.foo.bar().baz : string | number | undefined +>b.foo.bar().baz ||= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>b.foo.bar().baz : "" | 0 | 1 | 42 | undefined >b.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >b.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } >b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >b : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >bar : () => { baz: "" | 0 | 1 | 42 | undefined; } ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.foo.bar().baz : "" | 0 | 1 | 42 | undefined >result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } @@ -133,15 +133,15 @@ b.foo.bar().baz ||= result.foo.bar().baz >baz : "" | 0 | 1 | 42 | undefined c.foo.bar().baz ??= result.foo.bar().baz ->c.foo.bar().baz ??= result.foo.bar().baz : string | number | undefined ->c.foo.bar().baz : string | number | undefined +>c.foo.bar().baz ??= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>c.foo.bar().baz : "" | 0 | 1 | 42 | undefined >c.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >c.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } >c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >c : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >bar : () => { baz: "" | 0 | 1 | 42 | undefined; } ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.foo.bar().baz : "" | 0 | 1 | 42 | undefined >result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } diff --git a/tests/baselines/reference/logicalAssignment2(target=esnext).types b/tests/baselines/reference/logicalAssignment2(target=esnext).types index e0940ed680600..53090c51e59e9 100644 --- a/tests/baselines/reference/logicalAssignment2(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment2(target=esnext).types @@ -30,34 +30,34 @@ declare const c: A a.baz &&= result.baz >a.baz &&= result.baz : "" | 0 | 1 | 42 | undefined ->a.baz : string | number | undefined +>a.baz : "" | 0 | 1 | 42 | undefined >a : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined b.baz ||= result.baz ->b.baz ||= result.baz : string | number | undefined ->b.baz : string | number | undefined +>b.baz ||= result.baz : "" | 0 | 1 | 42 | undefined +>b.baz : "" | 0 | 1 | 42 | undefined >b : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined c.baz ??= result.baz ->c.baz ??= result.baz : string | number | undefined ->c.baz : string | number | undefined +>c.baz ??= result.baz : "" | 0 | 1 | 42 | undefined +>c.baz : "" | 0 | 1 | 42 | undefined >c : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined a.foo["baz"] &&= result.foo.baz >a.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined ->a.foo["baz"] : string | number | undefined +>a.foo["baz"] : "" | 0 | 1 | 42 | undefined >a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >a : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } @@ -70,7 +70,7 @@ a.foo["baz"] &&= result.foo.baz b.foo["baz"] &&= result.foo.baz >b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined ->b.foo["baz"] : string | number | undefined +>b.foo["baz"] : "" | 0 | 1 | 42 | undefined >b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >b : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } @@ -83,7 +83,7 @@ b.foo["baz"] &&= result.foo.baz c.foo["baz"] &&= result.foo.baz >c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined ->c.foo["baz"] : string | number | undefined +>c.foo["baz"] : "" | 0 | 1 | 42 | undefined >c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >c : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } @@ -96,14 +96,14 @@ c.foo["baz"] &&= result.foo.baz a.foo.bar().baz &&= result.foo.bar().baz >a.foo.bar().baz &&= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined ->a.foo.bar().baz : string | number | undefined +>a.foo.bar().baz : "" | 0 | 1 | 42 | undefined >a.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >a.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } >a.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >a : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >bar : () => { baz: "" | 0 | 1 | 42 | undefined; } ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.foo.bar().baz : "" | 0 | 1 | 42 | undefined >result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } @@ -114,15 +114,15 @@ a.foo.bar().baz &&= result.foo.bar().baz >baz : "" | 0 | 1 | 42 | undefined b.foo.bar().baz ||= result.foo.bar().baz ->b.foo.bar().baz ||= result.foo.bar().baz : string | number | undefined ->b.foo.bar().baz : string | number | undefined +>b.foo.bar().baz ||= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>b.foo.bar().baz : "" | 0 | 1 | 42 | undefined >b.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >b.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } >b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >b : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >bar : () => { baz: "" | 0 | 1 | 42 | undefined; } ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.foo.bar().baz : "" | 0 | 1 | 42 | undefined >result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } @@ -133,15 +133,15 @@ b.foo.bar().baz ||= result.foo.bar().baz >baz : "" | 0 | 1 | 42 | undefined c.foo.bar().baz ??= result.foo.bar().baz ->c.foo.bar().baz ??= result.foo.bar().baz : string | number | undefined ->c.foo.bar().baz : string | number | undefined +>c.foo.bar().baz ??= result.foo.bar().baz : "" | 0 | 1 | 42 | undefined +>c.foo.bar().baz : "" | 0 | 1 | 42 | undefined >c.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >c.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } >c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >c : A >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >bar : () => { baz: "" | 0 | 1 | 42 | undefined; } ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.foo.bar().baz : "" | 0 | 1 | 42 | undefined >result.foo.bar() : { baz: "" | 0 | 1 | 42 | undefined; } >result.foo.bar : () => { baz: "" | 0 | 1 | 42 | undefined; } diff --git a/tests/baselines/reference/logicalAssignment3(target=es2015).types b/tests/baselines/reference/logicalAssignment3(target=es2015).types index c18cad97c3377..34ee2dc390129 100644 --- a/tests/baselines/reference/logicalAssignment3(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment3(target=es2015).types @@ -18,30 +18,30 @@ declare const c: A; (a.baz) &&= result.baz; >(a.baz) &&= result.baz : "" | 0 | 1 | 42 | undefined ->(a.baz) : string | number | undefined ->a.baz : string | number | undefined +>(a.baz) : "" | 0 | 1 | 42 | undefined +>a.baz : "" | 0 | 1 | 42 | undefined >a : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined (b.baz) ||= result.baz; ->(b.baz) ||= result.baz : string | number | undefined ->(b.baz) : string | number | undefined ->b.baz : string | number | undefined +>(b.baz) ||= result.baz : "" | 0 | 1 | 42 | undefined +>(b.baz) : "" | 0 | 1 | 42 | undefined +>b.baz : "" | 0 | 1 | 42 | undefined >b : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined (c.baz) ??= result.baz; ->(c.baz) ??= result.baz : string | number | undefined ->(c.baz) : string | number | undefined ->c.baz : string | number | undefined +>(c.baz) ??= result.baz : "" | 0 | 1 | 42 | undefined +>(c.baz) : "" | 0 | 1 | 42 | undefined +>c.baz : "" | 0 | 1 | 42 | undefined >c : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined diff --git a/tests/baselines/reference/logicalAssignment3(target=es2020).types b/tests/baselines/reference/logicalAssignment3(target=es2020).types index c18cad97c3377..34ee2dc390129 100644 --- a/tests/baselines/reference/logicalAssignment3(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment3(target=es2020).types @@ -18,30 +18,30 @@ declare const c: A; (a.baz) &&= result.baz; >(a.baz) &&= result.baz : "" | 0 | 1 | 42 | undefined ->(a.baz) : string | number | undefined ->a.baz : string | number | undefined +>(a.baz) : "" | 0 | 1 | 42 | undefined +>a.baz : "" | 0 | 1 | 42 | undefined >a : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined (b.baz) ||= result.baz; ->(b.baz) ||= result.baz : string | number | undefined ->(b.baz) : string | number | undefined ->b.baz : string | number | undefined +>(b.baz) ||= result.baz : "" | 0 | 1 | 42 | undefined +>(b.baz) : "" | 0 | 1 | 42 | undefined +>b.baz : "" | 0 | 1 | 42 | undefined >b : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined (c.baz) ??= result.baz; ->(c.baz) ??= result.baz : string | number | undefined ->(c.baz) : string | number | undefined ->c.baz : string | number | undefined +>(c.baz) ??= result.baz : "" | 0 | 1 | 42 | undefined +>(c.baz) : "" | 0 | 1 | 42 | undefined +>c.baz : "" | 0 | 1 | 42 | undefined >c : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined diff --git a/tests/baselines/reference/logicalAssignment3(target=esnext).types b/tests/baselines/reference/logicalAssignment3(target=esnext).types index c18cad97c3377..34ee2dc390129 100644 --- a/tests/baselines/reference/logicalAssignment3(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment3(target=esnext).types @@ -18,30 +18,30 @@ declare const c: A; (a.baz) &&= result.baz; >(a.baz) &&= result.baz : "" | 0 | 1 | 42 | undefined ->(a.baz) : string | number | undefined ->a.baz : string | number | undefined +>(a.baz) : "" | 0 | 1 | 42 | undefined +>a.baz : "" | 0 | 1 | 42 | undefined >a : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined (b.baz) ||= result.baz; ->(b.baz) ||= result.baz : string | number | undefined ->(b.baz) : string | number | undefined ->b.baz : string | number | undefined +>(b.baz) ||= result.baz : "" | 0 | 1 | 42 | undefined +>(b.baz) : "" | 0 | 1 | 42 | undefined +>b.baz : "" | 0 | 1 | 42 | undefined >b : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined (c.baz) ??= result.baz; ->(c.baz) ??= result.baz : string | number | undefined ->(c.baz) : string | number | undefined ->c.baz : string | number | undefined +>(c.baz) ??= result.baz : "" | 0 | 1 | 42 | undefined +>(c.baz) : "" | 0 | 1 | 42 | undefined +>c.baz : "" | 0 | 1 | 42 | undefined >c : A ->baz : string | number | undefined +>baz : "" | 0 | 1 | 42 | undefined >result.baz : "" | 0 | 1 | 42 | undefined >result : A >baz : "" | 0 | 1 | 42 | undefined diff --git a/tests/baselines/reference/logicalAssignment5(target=es2015).types b/tests/baselines/reference/logicalAssignment5(target=es2015).types index 694c3db90a50c..82ed2ab2d2f43 100644 --- a/tests/baselines/reference/logicalAssignment5(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment5(target=es2015).types @@ -51,8 +51,8 @@ function foo3 (f?: (a: number) => void) { >a : any f(42) ->f(42) : any ->f : undefined +>f(42) : void +>f : ((a: number) => void) | undefined >42 : 42 } @@ -126,8 +126,8 @@ function bar3 (f?: (a: number) => void) { >a : any f(42) ->f(42) : any ->f : undefined +>f(42) : void +>f : ((a: number) => void) | undefined >42 : 42 } diff --git a/tests/baselines/reference/logicalAssignment5(target=es2020).types b/tests/baselines/reference/logicalAssignment5(target=es2020).types index 694c3db90a50c..82ed2ab2d2f43 100644 --- a/tests/baselines/reference/logicalAssignment5(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment5(target=es2020).types @@ -51,8 +51,8 @@ function foo3 (f?: (a: number) => void) { >a : any f(42) ->f(42) : any ->f : undefined +>f(42) : void +>f : ((a: number) => void) | undefined >42 : 42 } @@ -126,8 +126,8 @@ function bar3 (f?: (a: number) => void) { >a : any f(42) ->f(42) : any ->f : undefined +>f(42) : void +>f : ((a: number) => void) | undefined >42 : 42 } diff --git a/tests/baselines/reference/logicalAssignment5(target=esnext).types b/tests/baselines/reference/logicalAssignment5(target=esnext).types index 694c3db90a50c..82ed2ab2d2f43 100644 --- a/tests/baselines/reference/logicalAssignment5(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment5(target=esnext).types @@ -51,8 +51,8 @@ function foo3 (f?: (a: number) => void) { >a : any f(42) ->f(42) : any ->f : undefined +>f(42) : void +>f : ((a: number) => void) | undefined >42 : 42 } @@ -126,8 +126,8 @@ function bar3 (f?: (a: number) => void) { >a : any f(42) ->f(42) : any ->f : undefined +>f(42) : void +>f : ((a: number) => void) | undefined >42 : 42 } From fafb82b01a91b9904d4d032b9b22e10a30e38b69 Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 2 Apr 2020 16:20:50 +0800 Subject: [PATCH 09/24] make ci happy --- .../reference/logicalAssignment2(target=es2015).types | 4 ++-- .../reference/logicalAssignment2(target=es2020).types | 4 ++-- .../reference/logicalAssignment2(target=esnext).types | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/logicalAssignment2(target=es2015).types b/tests/baselines/reference/logicalAssignment2(target=es2015).types index 53090c51e59e9..82188f308d82a 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment2(target=es2015).types @@ -1,10 +1,10 @@ === tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts === interface A { foo: { ->foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>foo : { bar(): { baz: 0 | 1 | 42 | undefined | '';}; baz: 0 | 1 | 42 | undefined | ''; } bar(): { ->bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: 0 | 1 | 42 | undefined | '';} baz: 0 | 1 | 42 | undefined | '' >baz : "" | 0 | 1 | 42 | undefined diff --git a/tests/baselines/reference/logicalAssignment2(target=es2020).types b/tests/baselines/reference/logicalAssignment2(target=es2020).types index 53090c51e59e9..82188f308d82a 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment2(target=es2020).types @@ -1,10 +1,10 @@ === tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts === interface A { foo: { ->foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>foo : { bar(): { baz: 0 | 1 | 42 | undefined | '';}; baz: 0 | 1 | 42 | undefined | ''; } bar(): { ->bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: 0 | 1 | 42 | undefined | '';} baz: 0 | 1 | 42 | undefined | '' >baz : "" | 0 | 1 | 42 | undefined diff --git a/tests/baselines/reference/logicalAssignment2(target=esnext).types b/tests/baselines/reference/logicalAssignment2(target=esnext).types index 53090c51e59e9..82188f308d82a 100644 --- a/tests/baselines/reference/logicalAssignment2(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment2(target=esnext).types @@ -1,10 +1,10 @@ === tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts === interface A { foo: { ->foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } +>foo : { bar(): { baz: 0 | 1 | 42 | undefined | '';}; baz: 0 | 1 | 42 | undefined | ''; } bar(): { ->bar : () => { baz: "" | 0 | 1 | 42 | undefined; } +>bar : () => { baz: 0 | 1 | 42 | undefined | '';} baz: 0 | 1 | 42 | undefined | '' >baz : "" | 0 | 1 | 42 | undefined From cb2e71cdb9c9de5087a9acfd2a63f3775d7cb500 Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 2 Apr 2020 16:29:04 +0800 Subject: [PATCH 10/24] fix operator --- .../reference/logicalAssignment4(target=es2015).errors.txt | 2 +- .../baselines/reference/logicalAssignment4(target=es2015).js | 4 ++-- .../reference/logicalAssignment4(target=es2015).symbols | 2 +- .../reference/logicalAssignment4(target=es2015).types | 4 ++-- .../reference/logicalAssignment4(target=es2020).errors.txt | 2 +- .../baselines/reference/logicalAssignment4(target=es2020).js | 4 ++-- .../reference/logicalAssignment4(target=es2020).symbols | 2 +- .../reference/logicalAssignment4(target=es2020).types | 4 ++-- .../reference/logicalAssignment4(target=esnext).errors.txt | 2 +- .../baselines/reference/logicalAssignment4(target=esnext).js | 4 ++-- .../reference/logicalAssignment4(target=esnext).symbols | 2 +- .../reference/logicalAssignment4(target=esnext).types | 4 ++-- .../esnext/logicalAssignment/logicalAssignment4.ts | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt index 939c5699f6a9b..b8f87f62ca14f 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt @@ -16,7 +16,7 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): e } function foo4(results: number[] | undefined) { - results ||= []; + results ??= []; results.push(100); } diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).js b/tests/baselines/reference/logicalAssignment4(target=es2015).js index 1a69ceeb70a3f..187ca2ed4758e 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).js @@ -13,7 +13,7 @@ function foo3(results: number[] | undefined) { } function foo4(results: number[] | undefined) { - results ||= []; + results ??= []; results.push(100); } @@ -40,7 +40,7 @@ function foo3(results) { results.push(100); } function foo4(results) { - results || (results = []); + results !== null && results !== void 0 ? results : (results = []); results.push(100); } function doSomethingWithAlias(thing) { diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).symbols b/tests/baselines/reference/logicalAssignment4(target=es2015).symbols index 4f25669f53e1e..8c8fdae296cd4 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).symbols +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).symbols @@ -36,7 +36,7 @@ function foo4(results: number[] | undefined) { >foo4 : Symbol(foo4, Decl(logicalAssignment4.ts, 11, 1)) >results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) - results ||= []; + results ??= []; >results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) results.push(100); diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).types b/tests/baselines/reference/logicalAssignment4(target=es2015).types index a2669aa6f28ab..337f639d502b7 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).types @@ -50,8 +50,8 @@ function foo4(results: number[] | undefined) { >foo4 : (results: number[] | undefined) => void >results : number[] | undefined - results ||= []; ->results ||= [] : number[] + results ??= []; +>results ??= [] : number[] >results : number[] | undefined >[] : never[] diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt index 939c5699f6a9b..b8f87f62ca14f 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt @@ -16,7 +16,7 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): e } function foo4(results: number[] | undefined) { - results ||= []; + results ??= []; results.push(100); } diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).js b/tests/baselines/reference/logicalAssignment4(target=es2020).js index f2dfaa8e3c9c1..3285cef381a6b 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).js @@ -13,7 +13,7 @@ function foo3(results: number[] | undefined) { } function foo4(results: number[] | undefined) { - results ||= []; + results ??= []; results.push(100); } @@ -40,7 +40,7 @@ function foo3(results) { results.push(100); } function foo4(results) { - results || (results = []); + results ?? (results = []); results.push(100); } function doSomethingWithAlias(thing) { diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).symbols b/tests/baselines/reference/logicalAssignment4(target=es2020).symbols index 4f25669f53e1e..8c8fdae296cd4 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).symbols +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).symbols @@ -36,7 +36,7 @@ function foo4(results: number[] | undefined) { >foo4 : Symbol(foo4, Decl(logicalAssignment4.ts, 11, 1)) >results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) - results ||= []; + results ??= []; >results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) results.push(100); diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).types b/tests/baselines/reference/logicalAssignment4(target=es2020).types index a2669aa6f28ab..337f639d502b7 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).types @@ -50,8 +50,8 @@ function foo4(results: number[] | undefined) { >foo4 : (results: number[] | undefined) => void >results : number[] | undefined - results ||= []; ->results ||= [] : number[] + results ??= []; +>results ??= [] : number[] >results : number[] | undefined >[] : never[] diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt index 939c5699f6a9b..b8f87f62ca14f 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt @@ -16,7 +16,7 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): e } function foo4(results: number[] | undefined) { - results ||= []; + results ??= []; results.push(100); } diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).js b/tests/baselines/reference/logicalAssignment4(target=esnext).js index b9c254e977806..d9610ca60d38b 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).js +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).js @@ -13,7 +13,7 @@ function foo3(results: number[] | undefined) { } function foo4(results: number[] | undefined) { - results ||= []; + results ??= []; results.push(100); } @@ -40,7 +40,7 @@ function foo3(results) { results.push(100); } function foo4(results) { - results ||= []; + results ??= []; results.push(100); } function doSomethingWithAlias(thing) { diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).symbols b/tests/baselines/reference/logicalAssignment4(target=esnext).symbols index 4f25669f53e1e..8c8fdae296cd4 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).symbols +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).symbols @@ -36,7 +36,7 @@ function foo4(results: number[] | undefined) { >foo4 : Symbol(foo4, Decl(logicalAssignment4.ts, 11, 1)) >results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) - results ||= []; + results ??= []; >results : Symbol(results, Decl(logicalAssignment4.ts, 13, 14)) results.push(100); diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).types b/tests/baselines/reference/logicalAssignment4(target=esnext).types index a2669aa6f28ab..337f639d502b7 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).types @@ -50,8 +50,8 @@ function foo4(results: number[] | undefined) { >foo4 : (results: number[] | undefined) => void >results : number[] | undefined - results ||= []; ->results ||= [] : number[] + results ??= []; +>results ??= [] : number[] >results : number[] | undefined >[] : never[] diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts index 3c35d94b336ee..2ad97ed1fa11d 100644 --- a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts @@ -16,7 +16,7 @@ function foo3(results: number[] | undefined) { } function foo4(results: number[] | undefined) { - results ||= []; + results ??= []; results.push(100); } From 81ce254a739305a4300766a8898dc05e5e3a1f50 Mon Sep 17 00:00:00 2001 From: kingwl Date: Sat, 4 Apr 2020 22:05:24 +0800 Subject: [PATCH 11/24] Refactor logical assignment --- src/compiler/binder.ts | 78 ++++++------------- src/compiler/checker.ts | 4 +- src/compiler/transformers/esnext.ts | 4 +- src/compiler/utilities.ts | 8 +- src/services/codefixes/inferFromUsage.ts | 6 -- ...gicalAssignment7(target=es2015).errors.txt | 11 +-- .../logicalAssignment7(target=es2015).js | 7 +- .../logicalAssignment7(target=es2015).types | 6 +- ...gicalAssignment7(target=es2020).errors.txt | 11 +-- .../logicalAssignment7(target=es2020).js | 6 +- .../logicalAssignment7(target=es2020).types | 6 +- ...gicalAssignment7(target=esnext).errors.txt | 11 +-- .../logicalAssignment7(target=esnext).types | 6 +- 13 files changed, 47 insertions(+), 117 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 599338b150543..396187ba09c72 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1047,24 +1047,9 @@ namespace ts { } } - function isLogicalAssignmentExpressioin(node: Node) { - while (true) { - if (isParenthesizedExpression(node)) { - node = node.expression; - } - else { - return isBinaryExpression(node) && isLogicalAssignmentOperator(node.operatorToken.kind); - } - } - } - - function isTopLevelLogicalAssignmentExpression(node: Node): boolean { - while (isParenthesizedExpression(node.parent)) { - node = node.parent; - } - return !isStatementCondition(node) && - !isLogicalAssignmentExpressioin(node.parent) && - !(isOptionalChain(node.parent) && node.parent.expression === node); + function isLogicalAssignmentExpression(node: Node) { + node = skipParentheses(node); + return isBinaryExpression(node) && isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind); } function isTopLevelLogicalExpression(node: Node): boolean { @@ -1073,6 +1058,7 @@ namespace ts { node = node.parent; } return !isStatementCondition(node) && + !isLogicalAssignmentExpression(node.parent) && !isLogicalExpression(node.parent) && !(isOptionalChain(node.parent) && node.parent.expression === node); } @@ -1089,7 +1075,7 @@ namespace ts { function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) { doWithConditionalBranches(bind, node, trueTarget, falseTarget); - if (!node || !isLogicalAssignmentExpressioin(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) { + if (!node || !isLogicalAssignmentExpression(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) { addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); } @@ -1189,24 +1175,6 @@ namespace ts { currentFlow = finishFlowLabel(postIfLabel); } - function bindLogicalAssignmentExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { - const preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) { - bindCondition(node.left, preRightLabel, falseTarget); - } - else { - bindCondition(node.left, trueTarget, preRightLabel); - } - currentFlow = finishFlowLabel(preRightLabel); - bind(node.operatorToken); - - doWithConditionalBranches(bind, node.right, trueTarget, falseTarget); - bindAssignmentTargetFlow(node.left); - - addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); - } - function bindReturnOrThrow(node: ReturnStatement | ThrowStatement): void { bind(node.expression); if (node.kind === SyntaxKind.ReturnStatement) { @@ -1448,9 +1416,9 @@ namespace ts { } } - function bindLogicalExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { + function bindLogicalLikeExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { const preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { + if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) { bindCondition(node.left, preRightLabel, falseTarget); } else { @@ -1458,7 +1426,17 @@ namespace ts { } currentFlow = finishFlowLabel(preRightLabel); bind(node.operatorToken); - bindCondition(node.right, trueTarget, falseTarget); + + if (isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind)) { + doWithConditionalBranches(bind, node.right, trueTarget, falseTarget); + bindAssignmentTargetFlow(node.left); + + addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); + } + else { + bindCondition(node.right, trueTarget, falseTarget); + } } function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) { @@ -1544,25 +1522,15 @@ namespace ts { // TODO: bindLogicalExpression is recursive - if we want to handle deeply nested `&&` expressions // we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too // For now, though, since the common cases are chained `+`, leaving it recursive is fine - if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { + if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken || + isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { const postExpressionLabel = createBranchLabel(); - bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); - } - else { - bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!); - } - completeNode(); - } - else if(isLogicalAssignmentOperator(operator)) { - if (isTopLevelLogicalAssignmentExpression(node)) { - const postExpressionLabel = createBranchLabel(); - bindLogicalAssignmentExpression(node, postExpressionLabel, postExpressionLabel); + bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); currentFlow = finishFlowLabel(postExpressionLabel); } else { - bindLogicalAssignmentExpression(node, currentTrueTarget!, currentFalseTarget!); + bindLogicalLikeExpression(node, currentTrueTarget!, currentFalseTarget!); } completeNode(); } @@ -3656,7 +3624,7 @@ namespace ts { if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) { transformFlags |= TransformFlags.AssertES2020; } - else if (isLogicalAssignmentOperator(operatorTokenKind)) { + else if (isLogicalOrCoalescingAssignmentOperator(operatorTokenKind)) { transformFlags |= TransformFlags.AssertESNext; } else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 89ee4693ffe92..f53eb42e6a2b6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28596,7 +28596,7 @@ namespace ts { getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) : leftType; if (operator === SyntaxKind.BarBarEqualsToken) { - checkAssignmentOperator(resultType); + checkAssignmentOperator(rightType); } return resultType; } @@ -28606,7 +28606,7 @@ namespace ts { getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) : leftType; if (operator === SyntaxKind.QuestionQuestionEqualsToken) { - checkAssignmentOperator(resultType); + checkAssignmentOperator(rightType); } return resultType; } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index b9bbbffe5fed1..6edbb65bf47cb 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -18,7 +18,7 @@ namespace ts { switch (node.kind) { case SyntaxKind.BinaryExpression: const binaryExpression = node; - if (isLogicalAssignmentOperator(binaryExpression.operatorToken.kind)) { + if (isLogicalOrCoalescingAssignmentOperator(binaryExpression.operatorToken.kind)) { return transformLogicalAssignmentOperators(binaryExpression); } // falls through @@ -29,7 +29,7 @@ namespace ts { function transformLogicalAssignmentOperators(binaryExpression: BinaryExpression): VisitResult { const operator = binaryExpression.operatorToken; - if (isCompoundAssignment(operator.kind) && isLogicalAssignmentOperator(operator.kind)) { + if (isCompoundAssignment(operator.kind) && isLogicalOrCoalescingAssignmentOperator(operator.kind)) { const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); const left = visitNode(binaryExpression.left, visitor, isExpression); const right = visitNode(binaryExpression.right, visitor, isExpression); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 58a6933429f48..e0bcfebb1b48b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2594,7 +2594,7 @@ namespace ts { switch (parent.kind) { case SyntaxKind.BinaryExpression: const binaryOperator = (parent).operatorToken.kind; - return isAssignmentOperator(binaryOperator) && !isLogicalAssignmentOperator(binaryOperator) && (parent).left === node ? + return isAssignmentOperator(binaryOperator) && !isLogicalOrCoalescingAssignmentOperator(binaryOperator) && (parent).left === node ? binaryOperator === SyntaxKind.EqualsToken ? AssignmentKind.Definite : AssignmentKind.Compound : AssignmentKind.None; case SyntaxKind.PrefixUnaryExpression: @@ -3378,10 +3378,6 @@ namespace ts { return 14; case SyntaxKind.AsteriskAsteriskToken: return 15; - case SyntaxKind.BarBarEqualsToken: - case SyntaxKind.AmpersandAmpersandEqualsToken: - case SyntaxKind.QuestionQuestionEqualsToken: - return 16; } // -1 is lower than all other precedences. Returning it will cause binary expression @@ -4454,7 +4450,7 @@ namespace ts { || token === SyntaxKind.ExclamationToken; } - export function isLogicalAssignmentOperator(token: SyntaxKind): boolean { + export function isLogicalOrCoalescingAssignmentOperator(token: SyntaxKind): boolean { return token === SyntaxKind.BarBarEqualsToken || token === SyntaxKind.AmpersandAmpersandEqualsToken || token === SyntaxKind.QuestionQuestionEqualsToken; diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index ec17923d86210..bf6b918086041 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -785,12 +785,6 @@ namespace ts.codefix { } break; - case SyntaxKind.BarBarEqualsToken: - case SyntaxKind.QuestionQuestionEqualsToken: - case SyntaxKind.AmpersandAmpersandEqualsToken: - // TODO: infer here - break; - case SyntaxKind.AmpersandAmpersandToken: case SyntaxKind.CommaToken: case SyntaxKind.InstanceOfKeyword: diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt index 4eec0ce2d1128..c7f29aa3a33a1 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).errors.txt @@ -1,29 +1,20 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (2 errors) ==== function foo1(results: number[] | undefined, results1: number[] | undefined) { (results ||= results1 ||= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo2(results: number[] | undefined, results1: number[] | undefined) { (results ??= results1 ??= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo3(results: number[] | undefined, results1: number[] | undefined) { (results &&= results1 &&= []).push(100); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. ~~~ !!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).js b/tests/baselines/reference/logicalAssignment7(target=es2015).js index 4ac2a4159b763..a0f67c80e53b3 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).js @@ -14,12 +14,11 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { //// [logicalAssignment7.js] "use strict"; function foo1(results, results1) { - (results || (results = results1) || (results || (results = results1) = [])).push(100); + (results || (results = results1 || (results1 = []))).push(100); } function foo2(results, results1) { - var _a; - ((_a = results !== null && results !== void 0 ? results : (results = results1)) !== null && _a !== void 0 ? _a : (results !== null && results !== void 0 ? results : (results = results1) = [])).push(100); + (results !== null && results !== void 0 ? results : (results = results1 !== null && results1 !== void 0 ? results1 : (results1 = []))).push(100); } function foo3(results, results1) { - (results && (results = results1) && (results && (results = results1) = [])).push(100); + (results && (results = results1 && (results1 = []))).push(100); } diff --git a/tests/baselines/reference/logicalAssignment7(target=es2015).types b/tests/baselines/reference/logicalAssignment7(target=es2015).types index b46c67c14bb68..250fb4072f508 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment7(target=es2015).types @@ -9,8 +9,8 @@ function foo1(results: number[] | undefined, results1: number[] | undefined) { >(results ||= results1 ||= []).push : (...items: number[]) => number >(results ||= results1 ||= []) : number[] >results ||= results1 ||= [] : number[] ->results ||= results1 : number[] | undefined >results : number[] | undefined +>results1 ||= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -27,8 +27,8 @@ function foo2(results: number[] | undefined, results1: number[] | undefined) { >(results ??= results1 ??= []).push : (...items: number[]) => number >(results ??= results1 ??= []) : number[] >results ??= results1 ??= [] : number[] ->results ??= results1 : number[] | undefined >results : number[] | undefined +>results1 ??= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -45,8 +45,8 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { >(results &&= results1 &&= []).push : (...items: never[]) => number >(results &&= results1 &&= []) : never[] | undefined >results &&= results1 &&= [] : never[] | undefined ->results &&= results1 : number[] | undefined >results : number[] | undefined +>results1 &&= [] : never[] | undefined >results1 : number[] | undefined >[] : never[] >push : (...items: never[]) => number diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt index 4eec0ce2d1128..c7f29aa3a33a1 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).errors.txt @@ -1,29 +1,20 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (2 errors) ==== function foo1(results: number[] | undefined, results1: number[] | undefined) { (results ||= results1 ||= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo2(results: number[] | undefined, results1: number[] | undefined) { (results ??= results1 ??= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo3(results: number[] | undefined, results1: number[] | undefined) { (results &&= results1 &&= []).push(100); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. ~~~ !!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).js b/tests/baselines/reference/logicalAssignment7(target=es2020).js index 8c0438acca6d3..38a14a64191e4 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).js @@ -14,11 +14,11 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { //// [logicalAssignment7.js] "use strict"; function foo1(results, results1) { - (results || (results = results1) || (results || (results = results1) = [])).push(100); + (results || (results = results1 || (results1 = []))).push(100); } function foo2(results, results1) { - (results ?? (results = results1) ?? (results ?? (results = results1) = [])).push(100); + (results ?? (results = results1 ?? (results1 = []))).push(100); } function foo3(results, results1) { - (results && (results = results1) && (results && (results = results1) = [])).push(100); + (results && (results = results1 && (results1 = []))).push(100); } diff --git a/tests/baselines/reference/logicalAssignment7(target=es2020).types b/tests/baselines/reference/logicalAssignment7(target=es2020).types index b46c67c14bb68..250fb4072f508 100644 --- a/tests/baselines/reference/logicalAssignment7(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment7(target=es2020).types @@ -9,8 +9,8 @@ function foo1(results: number[] | undefined, results1: number[] | undefined) { >(results ||= results1 ||= []).push : (...items: number[]) => number >(results ||= results1 ||= []) : number[] >results ||= results1 ||= [] : number[] ->results ||= results1 : number[] | undefined >results : number[] | undefined +>results1 ||= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -27,8 +27,8 @@ function foo2(results: number[] | undefined, results1: number[] | undefined) { >(results ??= results1 ??= []).push : (...items: number[]) => number >(results ??= results1 ??= []) : number[] >results ??= results1 ??= [] : number[] ->results ??= results1 : number[] | undefined >results : number[] | undefined +>results1 ??= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -45,8 +45,8 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { >(results &&= results1 &&= []).push : (...items: never[]) => number >(results &&= results1 &&= []) : never[] | undefined >results &&= results1 &&= [] : never[] | undefined ->results &&= results1 : number[] | undefined >results : number[] | undefined +>results1 &&= [] : never[] | undefined >results1 : number[] | undefined >[] : never[] >push : (...items: never[]) => number diff --git a/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt index 4eec0ce2d1128..c7f29aa3a33a1 100644 --- a/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt +++ b/tests/baselines/reference/logicalAssignment7(target=esnext).errors.txt @@ -1,29 +1,20 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(2,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(6,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,5): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,6): error TS2364: The left-hand side of an assignment expression must be a variable or a property access. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts(10,40): error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (5 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment7.ts (2 errors) ==== function foo1(results: number[] | undefined, results1: number[] | undefined) { (results ||= results1 ||= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo2(results: number[] | undefined, results1: number[] | undefined) { (results ??= results1 ??= []).push(100); - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. } function foo3(results: number[] | undefined, results1: number[] | undefined) { (results &&= results1 &&= []).push(100); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2532: Object is possibly 'undefined'. - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access. ~~~ !!! error TS2345: Argument of type '100' is not assignable to parameter of type 'never'. } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment7(target=esnext).types b/tests/baselines/reference/logicalAssignment7(target=esnext).types index b46c67c14bb68..250fb4072f508 100644 --- a/tests/baselines/reference/logicalAssignment7(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment7(target=esnext).types @@ -9,8 +9,8 @@ function foo1(results: number[] | undefined, results1: number[] | undefined) { >(results ||= results1 ||= []).push : (...items: number[]) => number >(results ||= results1 ||= []) : number[] >results ||= results1 ||= [] : number[] ->results ||= results1 : number[] | undefined >results : number[] | undefined +>results1 ||= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -27,8 +27,8 @@ function foo2(results: number[] | undefined, results1: number[] | undefined) { >(results ??= results1 ??= []).push : (...items: number[]) => number >(results ??= results1 ??= []) : number[] >results ??= results1 ??= [] : number[] ->results ??= results1 : number[] | undefined >results : number[] | undefined +>results1 ??= [] : number[] >results1 : number[] | undefined >[] : never[] >push : (...items: number[]) => number @@ -45,8 +45,8 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { >(results &&= results1 &&= []).push : (...items: never[]) => number >(results &&= results1 &&= []) : never[] | undefined >results &&= results1 &&= [] : never[] | undefined ->results &&= results1 : number[] | undefined >results : number[] | undefined +>results1 &&= [] : never[] | undefined >results1 : number[] | undefined >[] : never[] >push : (...items: never[]) => number From 67a4943e1f01da13a036609adee7a2c526ac4757 Mon Sep 17 00:00:00 2001 From: kingwl Date: Sat, 4 Apr 2020 22:19:57 +0800 Subject: [PATCH 12/24] Add more case --- src/compiler/binder.ts | 6 -- ...gicalAssignment8(target=es2015).errors.txt | 19 ++++++ .../logicalAssignment8(target=es2015).js | 29 +++++++++ .../logicalAssignment8(target=es2015).symbols | 43 +++++++++++++ .../logicalAssignment8(target=es2015).types | 61 +++++++++++++++++++ ...gicalAssignment8(target=es2020).errors.txt | 19 ++++++ .../logicalAssignment8(target=es2020).js | 26 ++++++++ .../logicalAssignment8(target=es2020).symbols | 43 +++++++++++++ .../logicalAssignment8(target=es2020).types | 61 +++++++++++++++++++ ...gicalAssignment8(target=esnext).errors.txt | 19 ++++++ .../logicalAssignment8(target=esnext).js | 26 ++++++++ .../logicalAssignment8(target=esnext).symbols | 43 +++++++++++++ .../logicalAssignment8(target=esnext).types | 61 +++++++++++++++++++ .../logicalAssignment/logicalAssignment8.ts | 16 +++++ 14 files changed, 466 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/logicalAssignment8(target=es2015).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment8(target=es2015).js create mode 100644 tests/baselines/reference/logicalAssignment8(target=es2015).symbols create mode 100644 tests/baselines/reference/logicalAssignment8(target=es2015).types create mode 100644 tests/baselines/reference/logicalAssignment8(target=es2020).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment8(target=es2020).js create mode 100644 tests/baselines/reference/logicalAssignment8(target=es2020).symbols create mode 100644 tests/baselines/reference/logicalAssignment8(target=es2020).types create mode 100644 tests/baselines/reference/logicalAssignment8(target=esnext).errors.txt create mode 100644 tests/baselines/reference/logicalAssignment8(target=esnext).js create mode 100644 tests/baselines/reference/logicalAssignment8(target=esnext).symbols create mode 100644 tests/baselines/reference/logicalAssignment8(target=esnext).types create mode 100644 tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 396187ba09c72..7cf4234b4156a 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -905,9 +905,6 @@ namespace ts { function isNarrowingBinaryExpression(expr: BinaryExpression) { switch (expr.operatorToken.kind) { case SyntaxKind.EqualsToken: - case SyntaxKind.BarBarEqualsToken: - case SyntaxKind.AmpersandAmpersandEqualsToken: - case SyntaxKind.QuestionQuestionEqualsToken: return containsNarrowableReference(expr.left); case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: @@ -932,9 +929,6 @@ namespace ts { case SyntaxKind.BinaryExpression: switch ((expr).operatorToken.kind) { case SyntaxKind.EqualsToken: - case SyntaxKind.BarBarEqualsToken: - case SyntaxKind.AmpersandAmpersandEqualsToken: - case SyntaxKind.QuestionQuestionEqualsToken: return isNarrowableOperand((expr).left); case SyntaxKind.CommaToken: return isNarrowableOperand((expr).right); diff --git a/tests/baselines/reference/logicalAssignment8(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment8(target=es2015).errors.txt new file mode 100644 index 0000000000000..82b49d50c3e51 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=es2015).errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts(12,5): error TS2532: Object is possibly 'undefined'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts (1 errors) ==== + declare const bar: { value?: number[] } | undefined + + function foo1(results: number[] | undefined) { + (results ||= bar?.value ?? []).push(100); + } + + function foo2(results: number[] | undefined) { + (results ??= bar?.value ?? []).push(100); + } + + function foo3(results: number[] | undefined) { + (results &&= bar?.value ?? []).push(100); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment8(target=es2015).js b/tests/baselines/reference/logicalAssignment8(target=es2015).js new file mode 100644 index 0000000000000..3d32063651e40 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=es2015).js @@ -0,0 +1,29 @@ +//// [logicalAssignment8.ts] +declare const bar: { value?: number[] } | undefined + +function foo1(results: number[] | undefined) { + (results ||= bar?.value ?? []).push(100); +} + +function foo2(results: number[] | undefined) { + (results ??= bar?.value ?? []).push(100); +} + +function foo3(results: number[] | undefined) { + (results &&= bar?.value ?? []).push(100); +} + +//// [logicalAssignment8.js] +"use strict"; +function foo1(results) { + var _a; + (results || (results = (_a = bar === null || bar === void 0 ? void 0 : bar.value) !== null && _a !== void 0 ? _a : [])).push(100); +} +function foo2(results) { + var _a; + (results !== null && results !== void 0 ? results : (results = (_a = bar === null || bar === void 0 ? void 0 : bar.value) !== null && _a !== void 0 ? _a : [])).push(100); +} +function foo3(results) { + var _a; + (results && (results = (_a = bar === null || bar === void 0 ? void 0 : bar.value) !== null && _a !== void 0 ? _a : [])).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment8(target=es2015).symbols b/tests/baselines/reference/logicalAssignment8(target=es2015).symbols new file mode 100644 index 0000000000000..e92c95fa8915d --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=es2015).symbols @@ -0,0 +1,43 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts === +declare const bar: { value?: number[] } | undefined +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) + +function foo1(results: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment8.ts, 0, 51)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 2, 14)) + + (results ||= bar?.value ?? []).push(100); +>(results ||= bar?.value ?? []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 2, 14)) +>bar?.value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment8.ts, 4, 1)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 6, 14)) + + (results ??= bar?.value ?? []).push(100); +>(results ??= bar?.value ?? []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 6, 14)) +>bar?.value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo3(results: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment8.ts, 8, 1)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 10, 14)) + + (results &&= bar?.value ?? []).push(100); +>(results &&= bar?.value ?? []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 10, 14)) +>bar?.value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment8(target=es2015).types b/tests/baselines/reference/logicalAssignment8(target=es2015).types new file mode 100644 index 0000000000000..5c9de4aecdbcf --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=es2015).types @@ -0,0 +1,61 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts === +declare const bar: { value?: number[] } | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined + +function foo1(results: number[] | undefined) { +>foo1 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ||= bar?.value ?? []).push(100); +>(results ||= bar?.value ?? []).push(100) : number +>(results ||= bar?.value ?? []).push : (...items: number[]) => number +>(results ||= bar?.value ?? []) : number[] +>results ||= bar?.value ?? [] : number[] +>results : number[] | undefined +>bar?.value ?? [] : number[] +>bar?.value : number[] | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined) { +>foo2 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ??= bar?.value ?? []).push(100); +>(results ??= bar?.value ?? []).push(100) : number +>(results ??= bar?.value ?? []).push : (...items: number[]) => number +>(results ??= bar?.value ?? []) : number[] +>results ??= bar?.value ?? [] : number[] +>results : number[] | undefined +>bar?.value ?? [] : number[] +>bar?.value : number[] | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo3(results: number[] | undefined) { +>foo3 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results &&= bar?.value ?? []).push(100); +>(results &&= bar?.value ?? []).push(100) : number +>(results &&= bar?.value ?? []).push : (...items: number[]) => number +>(results &&= bar?.value ?? []) : number[] | undefined +>results &&= bar?.value ?? [] : number[] | undefined +>results : number[] | undefined +>bar?.value ?? [] : number[] +>bar?.value : number[] | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} diff --git a/tests/baselines/reference/logicalAssignment8(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment8(target=es2020).errors.txt new file mode 100644 index 0000000000000..82b49d50c3e51 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=es2020).errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts(12,5): error TS2532: Object is possibly 'undefined'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts (1 errors) ==== + declare const bar: { value?: number[] } | undefined + + function foo1(results: number[] | undefined) { + (results ||= bar?.value ?? []).push(100); + } + + function foo2(results: number[] | undefined) { + (results ??= bar?.value ?? []).push(100); + } + + function foo3(results: number[] | undefined) { + (results &&= bar?.value ?? []).push(100); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment8(target=es2020).js b/tests/baselines/reference/logicalAssignment8(target=es2020).js new file mode 100644 index 0000000000000..6d8a806979a7f --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=es2020).js @@ -0,0 +1,26 @@ +//// [logicalAssignment8.ts] +declare const bar: { value?: number[] } | undefined + +function foo1(results: number[] | undefined) { + (results ||= bar?.value ?? []).push(100); +} + +function foo2(results: number[] | undefined) { + (results ??= bar?.value ?? []).push(100); +} + +function foo3(results: number[] | undefined) { + (results &&= bar?.value ?? []).push(100); +} + +//// [logicalAssignment8.js] +"use strict"; +function foo1(results) { + (results || (results = bar?.value ?? [])).push(100); +} +function foo2(results) { + (results ?? (results = bar?.value ?? [])).push(100); +} +function foo3(results) { + (results && (results = bar?.value ?? [])).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment8(target=es2020).symbols b/tests/baselines/reference/logicalAssignment8(target=es2020).symbols new file mode 100644 index 0000000000000..e92c95fa8915d --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=es2020).symbols @@ -0,0 +1,43 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts === +declare const bar: { value?: number[] } | undefined +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) + +function foo1(results: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment8.ts, 0, 51)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 2, 14)) + + (results ||= bar?.value ?? []).push(100); +>(results ||= bar?.value ?? []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 2, 14)) +>bar?.value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment8.ts, 4, 1)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 6, 14)) + + (results ??= bar?.value ?? []).push(100); +>(results ??= bar?.value ?? []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 6, 14)) +>bar?.value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo3(results: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment8.ts, 8, 1)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 10, 14)) + + (results &&= bar?.value ?? []).push(100); +>(results &&= bar?.value ?? []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 10, 14)) +>bar?.value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment8(target=es2020).types b/tests/baselines/reference/logicalAssignment8(target=es2020).types new file mode 100644 index 0000000000000..5c9de4aecdbcf --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=es2020).types @@ -0,0 +1,61 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts === +declare const bar: { value?: number[] } | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined + +function foo1(results: number[] | undefined) { +>foo1 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ||= bar?.value ?? []).push(100); +>(results ||= bar?.value ?? []).push(100) : number +>(results ||= bar?.value ?? []).push : (...items: number[]) => number +>(results ||= bar?.value ?? []) : number[] +>results ||= bar?.value ?? [] : number[] +>results : number[] | undefined +>bar?.value ?? [] : number[] +>bar?.value : number[] | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined) { +>foo2 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ??= bar?.value ?? []).push(100); +>(results ??= bar?.value ?? []).push(100) : number +>(results ??= bar?.value ?? []).push : (...items: number[]) => number +>(results ??= bar?.value ?? []) : number[] +>results ??= bar?.value ?? [] : number[] +>results : number[] | undefined +>bar?.value ?? [] : number[] +>bar?.value : number[] | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo3(results: number[] | undefined) { +>foo3 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results &&= bar?.value ?? []).push(100); +>(results &&= bar?.value ?? []).push(100) : number +>(results &&= bar?.value ?? []).push : (...items: number[]) => number +>(results &&= bar?.value ?? []) : number[] | undefined +>results &&= bar?.value ?? [] : number[] | undefined +>results : number[] | undefined +>bar?.value ?? [] : number[] +>bar?.value : number[] | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} diff --git a/tests/baselines/reference/logicalAssignment8(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment8(target=esnext).errors.txt new file mode 100644 index 0000000000000..82b49d50c3e51 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=esnext).errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts(12,5): error TS2532: Object is possibly 'undefined'. + + +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts (1 errors) ==== + declare const bar: { value?: number[] } | undefined + + function foo1(results: number[] | undefined) { + (results ||= bar?.value ?? []).push(100); + } + + function foo2(results: number[] | undefined) { + (results ??= bar?.value ?? []).push(100); + } + + function foo3(results: number[] | undefined) { + (results &&= bar?.value ?? []).push(100); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment8(target=esnext).js b/tests/baselines/reference/logicalAssignment8(target=esnext).js new file mode 100644 index 0000000000000..64c9fa99337a6 --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=esnext).js @@ -0,0 +1,26 @@ +//// [logicalAssignment8.ts] +declare const bar: { value?: number[] } | undefined + +function foo1(results: number[] | undefined) { + (results ||= bar?.value ?? []).push(100); +} + +function foo2(results: number[] | undefined) { + (results ??= bar?.value ?? []).push(100); +} + +function foo3(results: number[] | undefined) { + (results &&= bar?.value ?? []).push(100); +} + +//// [logicalAssignment8.js] +"use strict"; +function foo1(results) { + (results ||= bar?.value ?? []).push(100); +} +function foo2(results) { + (results ??= bar?.value ?? []).push(100); +} +function foo3(results) { + (results &&= bar?.value ?? []).push(100); +} diff --git a/tests/baselines/reference/logicalAssignment8(target=esnext).symbols b/tests/baselines/reference/logicalAssignment8(target=esnext).symbols new file mode 100644 index 0000000000000..e92c95fa8915d --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=esnext).symbols @@ -0,0 +1,43 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts === +declare const bar: { value?: number[] } | undefined +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) + +function foo1(results: number[] | undefined) { +>foo1 : Symbol(foo1, Decl(logicalAssignment8.ts, 0, 51)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 2, 14)) + + (results ||= bar?.value ?? []).push(100); +>(results ||= bar?.value ?? []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 2, 14)) +>bar?.value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo2(results: number[] | undefined) { +>foo2 : Symbol(foo2, Decl(logicalAssignment8.ts, 4, 1)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 6, 14)) + + (results ??= bar?.value ?? []).push(100); +>(results ??= bar?.value ?? []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 6, 14)) +>bar?.value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} + +function foo3(results: number[] | undefined) { +>foo3 : Symbol(foo3, Decl(logicalAssignment8.ts, 8, 1)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 10, 14)) + + (results &&= bar?.value ?? []).push(100); +>(results &&= bar?.value ?? []).push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>results : Symbol(results, Decl(logicalAssignment8.ts, 10, 14)) +>bar?.value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>bar : Symbol(bar, Decl(logicalAssignment8.ts, 0, 13)) +>value : Symbol(value, Decl(logicalAssignment8.ts, 0, 20)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +} diff --git a/tests/baselines/reference/logicalAssignment8(target=esnext).types b/tests/baselines/reference/logicalAssignment8(target=esnext).types new file mode 100644 index 0000000000000..5c9de4aecdbcf --- /dev/null +++ b/tests/baselines/reference/logicalAssignment8(target=esnext).types @@ -0,0 +1,61 @@ +=== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts === +declare const bar: { value?: number[] } | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined + +function foo1(results: number[] | undefined) { +>foo1 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ||= bar?.value ?? []).push(100); +>(results ||= bar?.value ?? []).push(100) : number +>(results ||= bar?.value ?? []).push : (...items: number[]) => number +>(results ||= bar?.value ?? []) : number[] +>results ||= bar?.value ?? [] : number[] +>results : number[] | undefined +>bar?.value ?? [] : number[] +>bar?.value : number[] | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo2(results: number[] | undefined) { +>foo2 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results ??= bar?.value ?? []).push(100); +>(results ??= bar?.value ?? []).push(100) : number +>(results ??= bar?.value ?? []).push : (...items: number[]) => number +>(results ??= bar?.value ?? []) : number[] +>results ??= bar?.value ?? [] : number[] +>results : number[] | undefined +>bar?.value ?? [] : number[] +>bar?.value : number[] | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} + +function foo3(results: number[] | undefined) { +>foo3 : (results: number[] | undefined) => void +>results : number[] | undefined + + (results &&= bar?.value ?? []).push(100); +>(results &&= bar?.value ?? []).push(100) : number +>(results &&= bar?.value ?? []).push : (...items: number[]) => number +>(results &&= bar?.value ?? []) : number[] | undefined +>results &&= bar?.value ?? [] : number[] | undefined +>results : number[] | undefined +>bar?.value ?? [] : number[] +>bar?.value : number[] | undefined +>bar : { value?: number[] | undefined; } | undefined +>value : number[] | undefined +>[] : never[] +>push : (...items: number[]) => number +>100 : 100 +} diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts new file mode 100644 index 0000000000000..15fe3b74b5e53 --- /dev/null +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment8.ts @@ -0,0 +1,16 @@ +// @strict: true +// @target: esnext, es2020, es2015 + +declare const bar: { value?: number[] } | undefined + +function foo1(results: number[] | undefined) { + (results ||= bar?.value ?? []).push(100); +} + +function foo2(results: number[] | undefined) { + (results ??= bar?.value ?? []).push(100); +} + +function foo3(results: number[] | undefined) { + (results &&= bar?.value ?? []).push(100); +} \ No newline at end of file From d2be8900dc8feff8eeed84e4168d4f3d83955f47 Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 8 Apr 2020 12:09:56 +0800 Subject: [PATCH 13/24] Add type narrow --- src/compiler/binder.ts | 3 + src/compiler/checker.ts | 4 + ...gicalAssignment4(target=es2015).errors.txt | 36 +++++++-- .../logicalAssignment4(target=es2015).js | 53 ++++++++++-- .../logicalAssignment4(target=es2015).symbols | 80 +++++++++++++++--- .../logicalAssignment4(target=es2015).types | 81 +++++++++++++++++-- ...gicalAssignment4(target=es2020).errors.txt | 36 +++++++-- .../logicalAssignment4(target=es2020).js | 53 ++++++++++-- .../logicalAssignment4(target=es2020).symbols | 80 +++++++++++++++--- .../logicalAssignment4(target=es2020).types | 81 +++++++++++++++++-- ...gicalAssignment4(target=esnext).errors.txt | 36 +++++++-- .../logicalAssignment4(target=esnext).js | 53 ++++++++++-- .../logicalAssignment4(target=esnext).symbols | 80 +++++++++++++++--- .../logicalAssignment4(target=esnext).types | 81 +++++++++++++++++-- .../logicalAssignment/logicalAssignment4.ts | 27 ++++++- 15 files changed, 688 insertions(+), 96 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7cf4234b4156a..958129b3b1cf5 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -905,6 +905,9 @@ namespace ts { function isNarrowingBinaryExpression(expr: BinaryExpression) { switch (expr.operatorToken.kind) { case SyntaxKind.EqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return containsNarrowableReference(expr.left); case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f53eb42e6a2b6..c08d2a2348bd3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20701,7 +20701,11 @@ namespace ts { function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { switch (expr.operatorToken.kind) { case SyntaxKind.EqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return narrowTypeByTruthiness(narrowType(type, expr.right, assumeTrue), expr.left, assumeTrue); + case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt index b8f87f62ca14f..ee34fac607c33 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).errors.txt @@ -1,7 +1,8 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(39,13): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(45,13): error TS2532: Object is possibly 'undefined'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts (1 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts (2 errors) ==== function foo1(results: number[] | undefined) { (results ||= []).push(100); } @@ -24,10 +25,33 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): e name: string; original?: ThingWithOriginal } - function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { - if (thing &&= thing.original) { - console.log(thing.name); - ~~~~~ + declare const v: number + function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { + if (v === 1) { + if (thing &&= thing.original) { + thing.name; + } + } + else if (v === 2) { + if (thing &&= defaultValue) { + thing.name; + defaultValue.name + } + } + else if (v === 3) { + if (thing ||= defaultValue) { + thing.name; + defaultValue.name; + ~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + } + else { + if (thing ??= defaultValue) { + thing.name; + defaultValue.name; + ~~~~~~~~~~~~ !!! error TS2532: Object is possibly 'undefined'. + } } } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).js b/tests/baselines/reference/logicalAssignment4(target=es2015).js index 187ca2ed4758e..b54bfb6d48796 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).js @@ -21,9 +21,30 @@ interface ThingWithOriginal { name: string; original?: ThingWithOriginal } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { - if (thing &&= thing.original) { - console.log(thing.name); +declare const v: number +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { + if (v === 1) { + if (thing &&= thing.original) { + thing.name; + } + } + else if (v === 2) { + if (thing &&= defaultValue) { + thing.name; + defaultValue.name + } + } + else if (v === 3) { + if (thing ||= defaultValue) { + thing.name; + defaultValue.name; + } + } + else { + if (thing ??= defaultValue) { + thing.name; + defaultValue.name; + } } } @@ -43,8 +64,28 @@ function foo4(results) { results !== null && results !== void 0 ? results : (results = []); results.push(100); } -function doSomethingWithAlias(thing) { - if (thing && (thing = thing.original)) { - console.log(thing.name); +function doSomethingWithAlias(thing, defaultValue) { + if (v === 1) { + if (thing && (thing = thing.original)) { + thing.name; + } + } + else if (v === 2) { + if (thing && (thing = defaultValue)) { + thing.name; + defaultValue.name; + } + } + else if (v === 3) { + if (thing || (thing = defaultValue)) { + thing.name; + defaultValue.name; + } + } + else { + if (thing !== null && thing !== void 0 ? thing : (thing = defaultValue)) { + thing.name; + defaultValue.name; + } } } diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).symbols b/tests/baselines/reference/logicalAssignment4(target=es2015).symbols index 8c8fdae296cd4..46a02a4811074 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).symbols +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).symbols @@ -55,23 +55,81 @@ interface ThingWithOriginal { >original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) >ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { ->doSomethingWithAlias : Symbol(doSomethingWithAlias, Decl(logicalAssignment4.ts, 21, 1)) ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +declare const v: number +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { +>doSomethingWithAlias : Symbol(doSomethingWithAlias, Decl(logicalAssignment4.ts, 22, 23)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) >ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) - if (thing &&= thing.original) { ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) + if (v === 1) { +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + + if (thing &&= thing.original) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) >thing.original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) >original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) - console.log(thing.name); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + thing.name; +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } + } + else if (v === 2) { +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + + if (thing &&= defaultValue) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) + + thing.name; >thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + defaultValue.name +>defaultValue.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } + } + else if (v === 3) { +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + + if (thing ||= defaultValue) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) + + thing.name; +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + defaultValue.name; +>defaultValue.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } + } + else { + if (thing ??= defaultValue) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) + + thing.name; +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + defaultValue.name; +>defaultValue.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) >name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } } } diff --git a/tests/baselines/reference/logicalAssignment4(target=es2015).types b/tests/baselines/reference/logicalAssignment4(target=es2015).types index 337f639d502b7..6a044ae0e1bf2 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment4(target=es2015).types @@ -70,24 +70,89 @@ interface ThingWithOriginal { original?: ThingWithOriginal >original : ThingWithOriginal | undefined } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { ->doSomethingWithAlias : (thing?: ThingWithOriginal | undefined) => void +declare const v: number +>v : number + +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { +>doSomethingWithAlias : (thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) => void >thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + if (v === 1) { +>v === 1 : boolean +>v : number +>1 : 1 - if (thing &&= thing.original) { + if (thing &&= thing.original) { >thing &&= thing.original : ThingWithOriginal | undefined >thing : ThingWithOriginal | undefined >thing.original : ThingWithOriginal | undefined >thing : ThingWithOriginal >original : ThingWithOriginal | undefined - console.log(thing.name); ->console.log(thing.name) : void ->console.log : (...data: any[]) => void ->console : Console ->log : (...data: any[]) => void + thing.name; +>thing.name : string +>thing : ThingWithOriginal +>name : string + } + } + else if (v === 2) { +>v === 2 : boolean +>v : number +>2 : 2 + + if (thing &&= defaultValue) { +>thing &&= defaultValue : ThingWithOriginal | undefined +>thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + thing.name; +>thing.name : string +>thing : ThingWithOriginal +>name : string + + defaultValue.name +>defaultValue.name : string +>defaultValue : ThingWithOriginal +>name : string + } + } + else if (v === 3) { +>v === 3 : boolean +>v : number +>3 : 3 + + if (thing ||= defaultValue) { +>thing ||= defaultValue : ThingWithOriginal | undefined +>thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + thing.name; >thing.name : string +>thing : ThingWithOriginal +>name : string + + defaultValue.name; +>defaultValue.name : string +>defaultValue : ThingWithOriginal | undefined +>name : string + } + } + else { + if (thing ??= defaultValue) { +>thing ??= defaultValue : ThingWithOriginal | undefined >thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + thing.name; +>thing.name : string +>thing : ThingWithOriginal +>name : string + + defaultValue.name; +>defaultValue.name : string +>defaultValue : ThingWithOriginal | undefined >name : string + } } } diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt index b8f87f62ca14f..ee34fac607c33 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).errors.txt @@ -1,7 +1,8 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(39,13): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(45,13): error TS2532: Object is possibly 'undefined'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts (1 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts (2 errors) ==== function foo1(results: number[] | undefined) { (results ||= []).push(100); } @@ -24,10 +25,33 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): e name: string; original?: ThingWithOriginal } - function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { - if (thing &&= thing.original) { - console.log(thing.name); - ~~~~~ + declare const v: number + function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { + if (v === 1) { + if (thing &&= thing.original) { + thing.name; + } + } + else if (v === 2) { + if (thing &&= defaultValue) { + thing.name; + defaultValue.name + } + } + else if (v === 3) { + if (thing ||= defaultValue) { + thing.name; + defaultValue.name; + ~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + } + else { + if (thing ??= defaultValue) { + thing.name; + defaultValue.name; + ~~~~~~~~~~~~ !!! error TS2532: Object is possibly 'undefined'. + } } } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).js b/tests/baselines/reference/logicalAssignment4(target=es2020).js index 3285cef381a6b..b2dc9ae3ce941 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).js @@ -21,9 +21,30 @@ interface ThingWithOriginal { name: string; original?: ThingWithOriginal } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { - if (thing &&= thing.original) { - console.log(thing.name); +declare const v: number +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { + if (v === 1) { + if (thing &&= thing.original) { + thing.name; + } + } + else if (v === 2) { + if (thing &&= defaultValue) { + thing.name; + defaultValue.name + } + } + else if (v === 3) { + if (thing ||= defaultValue) { + thing.name; + defaultValue.name; + } + } + else { + if (thing ??= defaultValue) { + thing.name; + defaultValue.name; + } } } @@ -43,8 +64,28 @@ function foo4(results) { results ?? (results = []); results.push(100); } -function doSomethingWithAlias(thing) { - if (thing && (thing = thing.original)) { - console.log(thing.name); +function doSomethingWithAlias(thing, defaultValue) { + if (v === 1) { + if (thing && (thing = thing.original)) { + thing.name; + } + } + else if (v === 2) { + if (thing && (thing = defaultValue)) { + thing.name; + defaultValue.name; + } + } + else if (v === 3) { + if (thing || (thing = defaultValue)) { + thing.name; + defaultValue.name; + } + } + else { + if (thing ?? (thing = defaultValue)) { + thing.name; + defaultValue.name; + } } } diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).symbols b/tests/baselines/reference/logicalAssignment4(target=es2020).symbols index 8c8fdae296cd4..46a02a4811074 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).symbols +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).symbols @@ -55,23 +55,81 @@ interface ThingWithOriginal { >original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) >ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { ->doSomethingWithAlias : Symbol(doSomethingWithAlias, Decl(logicalAssignment4.ts, 21, 1)) ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +declare const v: number +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { +>doSomethingWithAlias : Symbol(doSomethingWithAlias, Decl(logicalAssignment4.ts, 22, 23)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) >ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) - if (thing &&= thing.original) { ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) + if (v === 1) { +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + + if (thing &&= thing.original) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) >thing.original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) >original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) - console.log(thing.name); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + thing.name; +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } + } + else if (v === 2) { +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + + if (thing &&= defaultValue) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) + + thing.name; >thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + defaultValue.name +>defaultValue.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } + } + else if (v === 3) { +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + + if (thing ||= defaultValue) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) + + thing.name; +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + defaultValue.name; +>defaultValue.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } + } + else { + if (thing ??= defaultValue) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) + + thing.name; +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + defaultValue.name; +>defaultValue.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) >name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } } } diff --git a/tests/baselines/reference/logicalAssignment4(target=es2020).types b/tests/baselines/reference/logicalAssignment4(target=es2020).types index 337f639d502b7..6a044ae0e1bf2 100644 --- a/tests/baselines/reference/logicalAssignment4(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment4(target=es2020).types @@ -70,24 +70,89 @@ interface ThingWithOriginal { original?: ThingWithOriginal >original : ThingWithOriginal | undefined } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { ->doSomethingWithAlias : (thing?: ThingWithOriginal | undefined) => void +declare const v: number +>v : number + +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { +>doSomethingWithAlias : (thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) => void >thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + if (v === 1) { +>v === 1 : boolean +>v : number +>1 : 1 - if (thing &&= thing.original) { + if (thing &&= thing.original) { >thing &&= thing.original : ThingWithOriginal | undefined >thing : ThingWithOriginal | undefined >thing.original : ThingWithOriginal | undefined >thing : ThingWithOriginal >original : ThingWithOriginal | undefined - console.log(thing.name); ->console.log(thing.name) : void ->console.log : (...data: any[]) => void ->console : Console ->log : (...data: any[]) => void + thing.name; +>thing.name : string +>thing : ThingWithOriginal +>name : string + } + } + else if (v === 2) { +>v === 2 : boolean +>v : number +>2 : 2 + + if (thing &&= defaultValue) { +>thing &&= defaultValue : ThingWithOriginal | undefined +>thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + thing.name; +>thing.name : string +>thing : ThingWithOriginal +>name : string + + defaultValue.name +>defaultValue.name : string +>defaultValue : ThingWithOriginal +>name : string + } + } + else if (v === 3) { +>v === 3 : boolean +>v : number +>3 : 3 + + if (thing ||= defaultValue) { +>thing ||= defaultValue : ThingWithOriginal | undefined +>thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + thing.name; >thing.name : string +>thing : ThingWithOriginal +>name : string + + defaultValue.name; +>defaultValue.name : string +>defaultValue : ThingWithOriginal | undefined +>name : string + } + } + else { + if (thing ??= defaultValue) { +>thing ??= defaultValue : ThingWithOriginal | undefined >thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + thing.name; +>thing.name : string +>thing : ThingWithOriginal +>name : string + + defaultValue.name; +>defaultValue.name : string +>defaultValue : ThingWithOriginal | undefined >name : string + } } } diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt index b8f87f62ca14f..ee34fac607c33 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).errors.txt @@ -1,7 +1,8 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(39,13): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(45,13): error TS2532: Object is possibly 'undefined'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts (1 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts (2 errors) ==== function foo1(results: number[] | undefined) { (results ||= []).push(100); } @@ -24,10 +25,33 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts(25,21): e name: string; original?: ThingWithOriginal } - function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { - if (thing &&= thing.original) { - console.log(thing.name); - ~~~~~ + declare const v: number + function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { + if (v === 1) { + if (thing &&= thing.original) { + thing.name; + } + } + else if (v === 2) { + if (thing &&= defaultValue) { + thing.name; + defaultValue.name + } + } + else if (v === 3) { + if (thing ||= defaultValue) { + thing.name; + defaultValue.name; + ~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + } + else { + if (thing ??= defaultValue) { + thing.name; + defaultValue.name; + ~~~~~~~~~~~~ !!! error TS2532: Object is possibly 'undefined'. + } } } \ No newline at end of file diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).js b/tests/baselines/reference/logicalAssignment4(target=esnext).js index d9610ca60d38b..5724bcaa58b1d 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).js +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).js @@ -21,9 +21,30 @@ interface ThingWithOriginal { name: string; original?: ThingWithOriginal } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { - if (thing &&= thing.original) { - console.log(thing.name); +declare const v: number +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { + if (v === 1) { + if (thing &&= thing.original) { + thing.name; + } + } + else if (v === 2) { + if (thing &&= defaultValue) { + thing.name; + defaultValue.name + } + } + else if (v === 3) { + if (thing ||= defaultValue) { + thing.name; + defaultValue.name; + } + } + else { + if (thing ??= defaultValue) { + thing.name; + defaultValue.name; + } } } @@ -43,8 +64,28 @@ function foo4(results) { results ??= []; results.push(100); } -function doSomethingWithAlias(thing) { - if (thing &&= thing.original) { - console.log(thing.name); +function doSomethingWithAlias(thing, defaultValue) { + if (v === 1) { + if (thing &&= thing.original) { + thing.name; + } + } + else if (v === 2) { + if (thing &&= defaultValue) { + thing.name; + defaultValue.name; + } + } + else if (v === 3) { + if (thing ||= defaultValue) { + thing.name; + defaultValue.name; + } + } + else { + if (thing ??= defaultValue) { + thing.name; + defaultValue.name; + } } } diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).symbols b/tests/baselines/reference/logicalAssignment4(target=esnext).symbols index 8c8fdae296cd4..46a02a4811074 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).symbols +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).symbols @@ -55,23 +55,81 @@ interface ThingWithOriginal { >original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) >ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { ->doSomethingWithAlias : Symbol(doSomethingWithAlias, Decl(logicalAssignment4.ts, 21, 1)) ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +declare const v: number +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { +>doSomethingWithAlias : Symbol(doSomethingWithAlias, Decl(logicalAssignment4.ts, 22, 23)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) >ThingWithOriginal : Symbol(ThingWithOriginal, Decl(logicalAssignment4.ts, 16, 1)) - if (thing &&= thing.original) { ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) + if (v === 1) { +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + + if (thing &&= thing.original) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) >thing.original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) >original : Symbol(ThingWithOriginal.original, Decl(logicalAssignment4.ts, 19, 17)) - console.log(thing.name); ->console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) ->console : Symbol(console, Decl(lib.dom.d.ts, --, --)) ->log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + thing.name; +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } + } + else if (v === 2) { +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + + if (thing &&= defaultValue) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) + + thing.name; >thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) ->thing : Symbol(thing, Decl(logicalAssignment4.ts, 22, 30)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + defaultValue.name +>defaultValue.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } + } + else if (v === 3) { +>v : Symbol(v, Decl(logicalAssignment4.ts, 22, 13)) + + if (thing ||= defaultValue) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) + + thing.name; +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + defaultValue.name; +>defaultValue.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } + } + else { + if (thing ??= defaultValue) { +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) + + thing.name; +>thing.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>thing : Symbol(thing, Decl(logicalAssignment4.ts, 23, 30)) +>name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + + defaultValue.name; +>defaultValue.name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) +>defaultValue : Symbol(defaultValue, Decl(logicalAssignment4.ts, 23, 67)) >name : Symbol(ThingWithOriginal.name, Decl(logicalAssignment4.ts, 18, 29)) + } } } diff --git a/tests/baselines/reference/logicalAssignment4(target=esnext).types b/tests/baselines/reference/logicalAssignment4(target=esnext).types index 337f639d502b7..6a044ae0e1bf2 100644 --- a/tests/baselines/reference/logicalAssignment4(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment4(target=esnext).types @@ -70,24 +70,89 @@ interface ThingWithOriginal { original?: ThingWithOriginal >original : ThingWithOriginal | undefined } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { ->doSomethingWithAlias : (thing?: ThingWithOriginal | undefined) => void +declare const v: number +>v : number + +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { +>doSomethingWithAlias : (thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) => void >thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + if (v === 1) { +>v === 1 : boolean +>v : number +>1 : 1 - if (thing &&= thing.original) { + if (thing &&= thing.original) { >thing &&= thing.original : ThingWithOriginal | undefined >thing : ThingWithOriginal | undefined >thing.original : ThingWithOriginal | undefined >thing : ThingWithOriginal >original : ThingWithOriginal | undefined - console.log(thing.name); ->console.log(thing.name) : void ->console.log : (...data: any[]) => void ->console : Console ->log : (...data: any[]) => void + thing.name; +>thing.name : string +>thing : ThingWithOriginal +>name : string + } + } + else if (v === 2) { +>v === 2 : boolean +>v : number +>2 : 2 + + if (thing &&= defaultValue) { +>thing &&= defaultValue : ThingWithOriginal | undefined +>thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + thing.name; +>thing.name : string +>thing : ThingWithOriginal +>name : string + + defaultValue.name +>defaultValue.name : string +>defaultValue : ThingWithOriginal +>name : string + } + } + else if (v === 3) { +>v === 3 : boolean +>v : number +>3 : 3 + + if (thing ||= defaultValue) { +>thing ||= defaultValue : ThingWithOriginal | undefined +>thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + thing.name; >thing.name : string +>thing : ThingWithOriginal +>name : string + + defaultValue.name; +>defaultValue.name : string +>defaultValue : ThingWithOriginal | undefined +>name : string + } + } + else { + if (thing ??= defaultValue) { +>thing ??= defaultValue : ThingWithOriginal | undefined >thing : ThingWithOriginal | undefined +>defaultValue : ThingWithOriginal | undefined + + thing.name; +>thing.name : string +>thing : ThingWithOriginal +>name : string + + defaultValue.name; +>defaultValue.name : string +>defaultValue : ThingWithOriginal | undefined >name : string + } } } diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts index 2ad97ed1fa11d..bb13be7db6bb5 100644 --- a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment4.ts @@ -24,8 +24,29 @@ interface ThingWithOriginal { name: string; original?: ThingWithOriginal } -function doSomethingWithAlias(thing?: ThingWithOriginal | undefined) { - if (thing &&= thing.original) { - console.log(thing.name); +declare const v: number +function doSomethingWithAlias(thing: ThingWithOriginal | undefined, defaultValue: ThingWithOriginal | undefined) { + if (v === 1) { + if (thing &&= thing.original) { + thing.name; + } + } + else if (v === 2) { + if (thing &&= defaultValue) { + thing.name; + defaultValue.name + } + } + else if (v === 3) { + if (thing ||= defaultValue) { + thing.name; + defaultValue.name; + } + } + else { + if (thing ??= defaultValue) { + thing.name; + defaultValue.name; + } } } \ No newline at end of file From be708bbb0a0e4350636e4ecc3b84d16fe26f5f86 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 10 Apr 2020 14:19:59 +0800 Subject: [PATCH 14/24] fix assignment check of logical assignment --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c08d2a2348bd3..80f535d180b6b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19772,6 +19772,9 @@ namespace ts { case SyntaxKind.BinaryExpression: switch ((node).operatorToken.kind) { case SyntaxKind.EqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return getReferenceCandidate((node).left); case SyntaxKind.CommaToken: return getReferenceCandidate((node).right); @@ -28590,7 +28593,7 @@ namespace ts { getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) : leftType; if (operator === SyntaxKind.AmpersandAmpersandEqualsToken) { - checkAssignmentOperator(resultType); + checkAssignmentOperator(rightType); } return resultType; } From 9681c1611cf9662efd3ae20b3648685eabe4e098 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 27 Apr 2020 12:31:25 -0700 Subject: [PATCH 15/24] Remove newline --- src/compiler/transformers/utilities.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index b4d01704f612b..53052ba2d4098 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -283,7 +283,6 @@ namespace ts { export function shouldCaptureInTempVariable(expression: Expression): boolean { // don't capture identifiers and `this` in a temporary variable // `super` cannot be captured as it's not a real variable - return !isIdentifier(expression) && expression.kind !== SyntaxKind.ThisKeyword && expression.kind !== SyntaxKind.SuperKeyword; From 11bed4456bb2f050e32ae11999bc75f8a30cafb7 Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 6 May 2020 11:12:33 +0800 Subject: [PATCH 16/24] avoid shouldCaptureInTempVariable --- src/compiler/transformers/es2020.ts | 8 ++++---- src/compiler/transformers/utilities.ts | 8 -------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/compiler/transformers/es2020.ts b/src/compiler/transformers/es2020.ts index 8cf3169752094..f745e7bc2c52e 100644 --- a/src/compiler/transformers/es2020.ts +++ b/src/compiler/transformers/es2020.ts @@ -73,7 +73,7 @@ namespace ts { let thisArg: Expression | undefined; if (captureThisArg) { - if (shouldCaptureInTempVariable(expression)) { + if (!isSimpleCopiableExpression(expression)) { thisArg = createTempVariable(hoistVariableDeclaration); expression = createAssignment(thisArg, expression); // if (inParameterInitializer) tempVariableInParameter = true; @@ -113,7 +113,7 @@ namespace ts { const leftThisArg = isSyntheticReference(left) ? left.thisArg : undefined; let leftExpression = isSyntheticReference(left) ? left.expression : left; let capturedLeft: Expression = leftExpression; - if (shouldCaptureInTempVariable(leftExpression)) { + if (!isSimpleCopiableExpression(leftExpression)) { capturedLeft = createTempVariable(hoistVariableDeclaration); leftExpression = createAssignment(capturedLeft, leftExpression); // if (inParameterInitializer) tempVariableInParameter = true; @@ -126,7 +126,7 @@ namespace ts { case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: if (i === chain.length - 1 && captureThisArg) { - if (shouldCaptureInTempVariable(rightExpression)) { + if (!isSimpleCopiableExpression(rightExpression)) { thisArg = createTempVariable(hoistVariableDeclaration); rightExpression = createAssignment(thisArg, rightExpression); // if (inParameterInitializer) tempVariableInParameter = true; @@ -184,7 +184,7 @@ namespace ts { function transformNullishCoalescingExpression(node: BinaryExpression) { let left = visitNode(node.left, visitor, isExpression); let right = left; - if (shouldCaptureInTempVariable(left)) { + if (!isSimpleCopiableExpression(left)) { right = createTempVariable(hoistVariableDeclaration); left = createAssignment(right, left); // if (inParameterInitializer) tempVariableInParameter = true; diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 53052ba2d4098..94c734d12ae2c 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -280,14 +280,6 @@ namespace ts { } } - export function shouldCaptureInTempVariable(expression: Expression): boolean { - // don't capture identifiers and `this` in a temporary variable - // `super` cannot be captured as it's not a real variable - return !isIdentifier(expression) && - expression.kind !== SyntaxKind.ThisKeyword && - expression.kind !== SyntaxKind.SuperKeyword; - } - /** * Adds super call and preceding prologue directives into the list of statements. * From c0c60015c498ec0ec7764e10566a48389f26755e Mon Sep 17 00:00:00 2001 From: kingwl Date: Wed, 6 May 2020 20:50:41 +0800 Subject: [PATCH 17/24] fix mission baseline --- tests/baselines/reference/nullishCoalescingOperator1.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/baselines/reference/nullishCoalescingOperator1.js b/tests/baselines/reference/nullishCoalescingOperator1.js index c138222970cce..e02ce7490a40e 100644 --- a/tests/baselines/reference/nullishCoalescingOperator1.js +++ b/tests/baselines/reference/nullishCoalescingOperator1.js @@ -67,7 +67,6 @@ else { //// [nullishCoalescingOperator1.js] "use strict"; -var _a; var aa1 = a1 !== null && a1 !== void 0 ? a1 : 'whatever'; var aa2 = a2 !== null && a2 !== void 0 ? a2 : 'whatever'; var aa3 = a3 !== null && a3 !== void 0 ? a3 : 'whatever'; @@ -94,7 +93,7 @@ if (maybeBool !== null && maybeBool !== void 0 ? maybeBool : true) { else { foo(); } -if ((_a = false) !== null && _a !== void 0 ? _a : true) { +if (false !== null && false !== void 0 ? false : true) { foo(); } else { From f78a408ab53665b28d6917a9604c3d1ba87fad79 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 15 May 2020 11:33:54 +0800 Subject: [PATCH 18/24] Add more check --- src/compiler/transformers/esnext.ts | 39 +++++++++++++-- .../reference/api/tsserverlibrary.d.ts | 49 ++++++++++--------- tests/baselines/reference/api/typescript.d.ts | 49 ++++++++++--------- .../logicalAssignment2(target=es2015).js | 19 +++---- .../logicalAssignment2(target=es2020).js | 19 +++---- .../logicalAssignment3(target=es2015).js | 7 +-- .../logicalAssignment3(target=es2020).js | 7 +-- .../logicalAssignment5(target=es2015).js | 6 +-- .../logicalAssignment5(target=es2020).js | 6 +-- .../logicalAssignment6(target=es2015).js | 6 +-- .../logicalAssignment6(target=es2020).js | 6 +-- 11 files changed, 126 insertions(+), 87 deletions(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 6edbb65bf47cb..df42ff4eb8b43 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -1,6 +1,9 @@ /*@internal*/ namespace ts { export function transformESNext(context: TransformationContext) { + const { + hoistVariableDeclaration + } = context; return chainBundle(transformSourceFile); function transformSourceFile(node: SourceFile) { @@ -31,15 +34,45 @@ namespace ts { const operator = binaryExpression.operatorToken; if (isCompoundAssignment(operator.kind) && isLogicalOrCoalescingAssignmentOperator(operator.kind)) { const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); - const left = visitNode(binaryExpression.left, visitor, isExpression); - const right = visitNode(binaryExpression.right, visitor, isExpression); + let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression)); + let assignmentTarget = left + const right = skipParentheses(visitNode(binaryExpression.right, visitor, isExpression)); + if (isPropertyAccessExpression(left) || isElementAccessExpression(left)) { + const tempVariable = createTempVariable(hoistVariableDeclaration) + if (isPropertyAccessExpression(left)) { + assignmentTarget = createPropertyAccess( + tempVariable, + left.name + ); + left = createPropertyAccess( + createAssignment( + tempVariable, + left.expression + ), + left.name + ); + } + else { + assignmentTarget = createElementAccess( + tempVariable, + left.argumentExpression + ); + left = createElementAccess( + createAssignment( + tempVariable, + left.expression + ), + left.argumentExpression + ); + } + } return createBinary( left, nonAssignmentOperator, createParen( createAssignment( - left, + assignmentTarget, right ) ) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index efd6c9afd522c..6f5180e70a5e6 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -388,28 +388,29 @@ declare namespace ts { JSDocAugmentsTag = 310, JSDocImplementsTag = 311, JSDocAuthorTag = 312, - JSDocClassTag = 313, - JSDocPublicTag = 314, - JSDocPrivateTag = 315, - JSDocProtectedTag = 316, - JSDocReadonlyTag = 317, - JSDocCallbackTag = 318, - JSDocEnumTag = 319, - JSDocParameterTag = 320, - JSDocReturnTag = 321, - JSDocThisTag = 322, - JSDocTypeTag = 323, - JSDocTemplateTag = 324, - JSDocTypedefTag = 325, - JSDocPropertyTag = 326, - SyntaxList = 327, - NotEmittedStatement = 328, - PartiallyEmittedExpression = 329, - CommaListExpression = 330, - MergeDeclarationMarker = 331, - EndOfDeclarationMarker = 332, - SyntheticReferenceExpression = 333, - Count = 334, + JSDocDeprecatedTag = 313, + JSDocClassTag = 314, + JSDocPublicTag = 315, + JSDocPrivateTag = 316, + JSDocProtectedTag = 317, + JSDocReadonlyTag = 318, + JSDocCallbackTag = 319, + JSDocEnumTag = 320, + JSDocParameterTag = 321, + JSDocReturnTag = 322, + JSDocThisTag = 323, + JSDocTypeTag = 324, + JSDocTemplateTag = 325, + JSDocTypedefTag = 326, + JSDocPropertyTag = 327, + SyntaxList = 328, + NotEmittedStatement = 329, + PartiallyEmittedExpression = 330, + CommaListExpression = 331, + MergeDeclarationMarker = 332, + EndOfDeclarationMarker = 333, + SyntheticReferenceExpression = 334, + Count = 335, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -438,9 +439,9 @@ declare namespace ts { LastStatement = 244, FirstNode = 156, FirstJSDocNode = 297, - LastJSDocNode = 326, + LastJSDocNode = 327, FirstJSDocTagNode = 309, - LastJSDocTagNode = 326, + LastJSDocTagNode = 327, } export enum NodeFlags { None = 0, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1efec605a9e13..4570f408c16ea 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -388,28 +388,29 @@ declare namespace ts { JSDocAugmentsTag = 310, JSDocImplementsTag = 311, JSDocAuthorTag = 312, - JSDocClassTag = 313, - JSDocPublicTag = 314, - JSDocPrivateTag = 315, - JSDocProtectedTag = 316, - JSDocReadonlyTag = 317, - JSDocCallbackTag = 318, - JSDocEnumTag = 319, - JSDocParameterTag = 320, - JSDocReturnTag = 321, - JSDocThisTag = 322, - JSDocTypeTag = 323, - JSDocTemplateTag = 324, - JSDocTypedefTag = 325, - JSDocPropertyTag = 326, - SyntaxList = 327, - NotEmittedStatement = 328, - PartiallyEmittedExpression = 329, - CommaListExpression = 330, - MergeDeclarationMarker = 331, - EndOfDeclarationMarker = 332, - SyntheticReferenceExpression = 333, - Count = 334, + JSDocDeprecatedTag = 313, + JSDocClassTag = 314, + JSDocPublicTag = 315, + JSDocPrivateTag = 316, + JSDocProtectedTag = 317, + JSDocReadonlyTag = 318, + JSDocCallbackTag = 319, + JSDocEnumTag = 320, + JSDocParameterTag = 321, + JSDocReturnTag = 322, + JSDocThisTag = 323, + JSDocTypeTag = 324, + JSDocTemplateTag = 325, + JSDocTypedefTag = 326, + JSDocPropertyTag = 327, + SyntaxList = 328, + NotEmittedStatement = 329, + PartiallyEmittedExpression = 330, + CommaListExpression = 331, + MergeDeclarationMarker = 332, + EndOfDeclarationMarker = 333, + SyntheticReferenceExpression = 334, + Count = 335, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -438,9 +439,9 @@ declare namespace ts { LastStatement = 244, FirstNode = 156, FirstJSDocNode = 297, - LastJSDocNode = 326, + LastJSDocNode = 327, FirstJSDocTagNode = 309, - LastJSDocTagNode = 326, + LastJSDocTagNode = 327, } export enum NodeFlags { None = 0, diff --git a/tests/baselines/reference/logicalAssignment2(target=es2015).js b/tests/baselines/reference/logicalAssignment2(target=es2015).js index f07da1575f23c..efeafc045b6d9 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment2(target=es2015).js @@ -31,12 +31,13 @@ c.foo.bar().baz ??= result.foo.bar().baz //// [logicalAssignment2.js] "use strict"; var _a, _b; -a.baz && (a.baz = result.baz); -b.baz || (b.baz = result.baz); -(_a = c.baz) !== null && _a !== void 0 ? _a : (c.baz = result.baz); -a.foo["baz"] && (a.foo["baz"] = result.foo.baz); -b.foo["baz"] && (b.foo["baz"] = result.foo.baz); -c.foo["baz"] && (c.foo["baz"] = result.foo.baz); -a.foo.bar().baz && (a.foo.bar().baz = result.foo.bar().baz); -b.foo.bar().baz || (b.foo.bar().baz = result.foo.bar().baz); -(_b = c.foo.bar().baz) !== null && _b !== void 0 ? _b : (c.foo.bar().baz = result.foo.bar().baz); +var _c, _d, _e, _f, _g, _h, _j, _k, _l; +(_c = a).baz && (_c.baz = result.baz); +(_d = b).baz || (_d.baz = result.baz); +(_a = (_e = c).baz) !== null && _a !== void 0 ? _a : (_e.baz = result.baz); +(_f = a.foo)["baz"] && (_f["baz"] = result.foo.baz); +(_g = b.foo)["baz"] && (_g["baz"] = result.foo.baz); +(_h = c.foo)["baz"] && (_h["baz"] = result.foo.baz); +(_j = a.foo.bar()).baz && (_j.baz = result.foo.bar().baz); +(_k = b.foo.bar()).baz || (_k.baz = result.foo.bar().baz); +(_b = (_l = c.foo.bar()).baz) !== null && _b !== void 0 ? _b : (_l.baz = result.foo.bar().baz); diff --git a/tests/baselines/reference/logicalAssignment2(target=es2020).js b/tests/baselines/reference/logicalAssignment2(target=es2020).js index 258de5d01e379..7d4a1c1de64c5 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment2(target=es2020).js @@ -30,12 +30,13 @@ c.foo.bar().baz ??= result.foo.bar().baz //// [logicalAssignment2.js] "use strict"; -a.baz && (a.baz = result.baz); -b.baz || (b.baz = result.baz); -c.baz ?? (c.baz = result.baz); -a.foo["baz"] && (a.foo["baz"] = result.foo.baz); -b.foo["baz"] && (b.foo["baz"] = result.foo.baz); -c.foo["baz"] && (c.foo["baz"] = result.foo.baz); -a.foo.bar().baz && (a.foo.bar().baz = result.foo.bar().baz); -b.foo.bar().baz || (b.foo.bar().baz = result.foo.bar().baz); -c.foo.bar().baz ?? (c.foo.bar().baz = result.foo.bar().baz); +var _a, _b, _c, _d, _e, _f, _g, _h, _j; +(_a = a).baz && (_a.baz = result.baz); +(_b = b).baz || (_b.baz = result.baz); +(_c = c).baz ?? (_c.baz = result.baz); +(_d = a.foo)["baz"] && (_d["baz"] = result.foo.baz); +(_e = b.foo)["baz"] && (_e["baz"] = result.foo.baz); +(_f = c.foo)["baz"] && (_f["baz"] = result.foo.baz); +(_g = a.foo.bar()).baz && (_g.baz = result.foo.bar().baz); +(_h = b.foo.bar()).baz || (_h.baz = result.foo.bar().baz); +(_j = c.foo.bar()).baz ?? (_j.baz = result.foo.bar().baz); diff --git a/tests/baselines/reference/logicalAssignment3(target=es2015).js b/tests/baselines/reference/logicalAssignment3(target=es2015).js index 24012130a538a..47f0a210412e1 100644 --- a/tests/baselines/reference/logicalAssignment3(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment3(target=es2015).js @@ -17,6 +17,7 @@ declare const c: A; //// [logicalAssignment3.js] "use strict"; var _a; -(a.baz) && ((a.baz) = result.baz); -(b.baz) || ((b.baz) = result.baz); -(_a = (c.baz)) !== null && _a !== void 0 ? _a : ((c.baz) = result.baz); +var _b, _c, _d; +(_b = a).baz && (_b.baz = result.baz); +(_c = b).baz || (_c.baz = result.baz); +(_a = (_d = c).baz) !== null && _a !== void 0 ? _a : (_d.baz = result.baz); diff --git a/tests/baselines/reference/logicalAssignment3(target=es2020).js b/tests/baselines/reference/logicalAssignment3(target=es2020).js index 854fa1567137b..57060aea11685 100644 --- a/tests/baselines/reference/logicalAssignment3(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment3(target=es2020).js @@ -16,6 +16,7 @@ declare const c: A; //// [logicalAssignment3.js] "use strict"; -(a.baz) && ((a.baz) = result.baz); -(b.baz) || ((b.baz) = result.baz); -(c.baz) ?? ((c.baz) = result.baz); +var _a, _b, _c; +(_a = a).baz && (_a.baz = result.baz); +(_b = b).baz || (_b.baz = result.baz); +(_c = c).baz ?? (_c.baz = result.baz); diff --git a/tests/baselines/reference/logicalAssignment5(target=es2015).js b/tests/baselines/reference/logicalAssignment5(target=es2015).js index f42fd755c1ddf..06fe4df0fe4e0 100644 --- a/tests/baselines/reference/logicalAssignment5(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment5(target=es2015).js @@ -33,15 +33,15 @@ function bar3 (f?: (a: number) => void) { //// [logicalAssignment5.js] "use strict"; function foo1(f) { - f !== null && f !== void 0 ? f : (f = (a => a)); + f !== null && f !== void 0 ? f : (f = a => a); f(42); } function foo2(f) { - f || (f = (a => a)); + f || (f = a => a); f(42); } function foo3(f) { - f && (f = (a => a)); + f && (f = a => a); f(42); } function bar1(f) { diff --git a/tests/baselines/reference/logicalAssignment5(target=es2020).js b/tests/baselines/reference/logicalAssignment5(target=es2020).js index 58f3a4553dd70..4403e390b8eb9 100644 --- a/tests/baselines/reference/logicalAssignment5(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment5(target=es2020).js @@ -33,15 +33,15 @@ function bar3 (f?: (a: number) => void) { //// [logicalAssignment5.js] "use strict"; function foo1(f) { - f ?? (f = (a => a)); + f ?? (f = a => a); f(42); } function foo2(f) { - f || (f = (a => a)); + f || (f = a => a); f(42); } function foo3(f) { - f && (f = (a => a)); + f && (f = a => a); f(42); } function bar1(f) { diff --git a/tests/baselines/reference/logicalAssignment6(target=es2015).js b/tests/baselines/reference/logicalAssignment6(target=es2015).js index a0424da1778c2..5b002760a2ebc 100644 --- a/tests/baselines/reference/logicalAssignment6(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment6(target=es2015).js @@ -14,11 +14,11 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { //// [logicalAssignment6.js] "use strict"; function foo1(results, results1) { - (results || (results = (results1 || (results1 = [])))).push(100); + (results || (results = results1 || (results1 = []))).push(100); } function foo2(results, results1) { - (results !== null && results !== void 0 ? results : (results = (results1 !== null && results1 !== void 0 ? results1 : (results1 = [])))).push(100); + (results !== null && results !== void 0 ? results : (results = results1 !== null && results1 !== void 0 ? results1 : (results1 = []))).push(100); } function foo3(results, results1) { - (results && (results = (results1 && (results1 = [])))).push(100); + (results && (results = results1 && (results1 = []))).push(100); } diff --git a/tests/baselines/reference/logicalAssignment6(target=es2020).js b/tests/baselines/reference/logicalAssignment6(target=es2020).js index 66852828beebe..4d8032ddb8e2e 100644 --- a/tests/baselines/reference/logicalAssignment6(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment6(target=es2020).js @@ -14,11 +14,11 @@ function foo3(results: number[] | undefined, results1: number[] | undefined) { //// [logicalAssignment6.js] "use strict"; function foo1(results, results1) { - (results || (results = (results1 || (results1 = [])))).push(100); + (results || (results = results1 || (results1 = []))).push(100); } function foo2(results, results1) { - (results ?? (results = (results1 ?? (results1 = [])))).push(100); + (results ?? (results = results1 ?? (results1 = []))).push(100); } function foo3(results, results1) { - (results && (results = (results1 && (results1 = [])))).push(100); + (results && (results = results1 && (results1 = []))).push(100); } From 39ae072a1c1cff100dca823e390fd6f120187839 Mon Sep 17 00:00:00 2001 From: kingwl Date: Fri, 15 May 2020 14:04:30 +0800 Subject: [PATCH 19/24] add missing semi --- src/compiler/transformers/esnext.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index df42ff4eb8b43..1e3d211d33f1f 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -35,10 +35,10 @@ namespace ts { if (isCompoundAssignment(operator.kind) && isLogicalOrCoalescingAssignmentOperator(operator.kind)) { const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression)); - let assignmentTarget = left + let assignmentTarget = left; const right = skipParentheses(visitNode(binaryExpression.right, visitor, isExpression)); if (isPropertyAccessExpression(left) || isElementAccessExpression(left)) { - const tempVariable = createTempVariable(hoistVariableDeclaration) + const tempVariable = createTempVariable(hoistVariableDeclaration); if (isPropertyAccessExpression(left)) { assignmentTarget = createPropertyAccess( tempVariable, From acc167dfc473aa01fd7609105a3820d29c0c3d9e Mon Sep 17 00:00:00 2001 From: kingwl Date: Sat, 16 May 2020 08:13:12 +0800 Subject: [PATCH 20/24] fix rebase conflict --- src/compiler/transformers/es2020.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/compiler/transformers/es2020.ts b/src/compiler/transformers/es2020.ts index f745e7bc2c52e..8e45fb38f60c8 100644 --- a/src/compiler/transformers/es2020.ts +++ b/src/compiler/transformers/es2020.ts @@ -196,14 +196,6 @@ namespace ts { ); } - 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) From 6f393e9196d6df56024a0a6e5f53b8e0c6ab2f52 Mon Sep 17 00:00:00 2001 From: kingwl Date: Sat, 16 May 2020 08:16:45 +0800 Subject: [PATCH 21/24] accept new baseline --- .../reference/api/tsserverlibrary.d.ts | 49 +++++++++---------- tests/baselines/reference/api/typescript.d.ts | 49 +++++++++---------- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 6f5180e70a5e6..efd6c9afd522c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -388,29 +388,28 @@ declare namespace ts { JSDocAugmentsTag = 310, JSDocImplementsTag = 311, JSDocAuthorTag = 312, - JSDocDeprecatedTag = 313, - JSDocClassTag = 314, - JSDocPublicTag = 315, - JSDocPrivateTag = 316, - JSDocProtectedTag = 317, - JSDocReadonlyTag = 318, - JSDocCallbackTag = 319, - JSDocEnumTag = 320, - JSDocParameterTag = 321, - JSDocReturnTag = 322, - JSDocThisTag = 323, - JSDocTypeTag = 324, - JSDocTemplateTag = 325, - JSDocTypedefTag = 326, - JSDocPropertyTag = 327, - SyntaxList = 328, - NotEmittedStatement = 329, - PartiallyEmittedExpression = 330, - CommaListExpression = 331, - MergeDeclarationMarker = 332, - EndOfDeclarationMarker = 333, - SyntheticReferenceExpression = 334, - Count = 335, + JSDocClassTag = 313, + JSDocPublicTag = 314, + JSDocPrivateTag = 315, + JSDocProtectedTag = 316, + JSDocReadonlyTag = 317, + JSDocCallbackTag = 318, + JSDocEnumTag = 319, + JSDocParameterTag = 320, + JSDocReturnTag = 321, + JSDocThisTag = 322, + JSDocTypeTag = 323, + JSDocTemplateTag = 324, + JSDocTypedefTag = 325, + JSDocPropertyTag = 326, + SyntaxList = 327, + NotEmittedStatement = 328, + PartiallyEmittedExpression = 329, + CommaListExpression = 330, + MergeDeclarationMarker = 331, + EndOfDeclarationMarker = 332, + SyntheticReferenceExpression = 333, + Count = 334, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -439,9 +438,9 @@ declare namespace ts { LastStatement = 244, FirstNode = 156, FirstJSDocNode = 297, - LastJSDocNode = 327, + LastJSDocNode = 326, FirstJSDocTagNode = 309, - LastJSDocTagNode = 327, + LastJSDocTagNode = 326, } export enum NodeFlags { None = 0, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 4570f408c16ea..1efec605a9e13 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -388,29 +388,28 @@ declare namespace ts { JSDocAugmentsTag = 310, JSDocImplementsTag = 311, JSDocAuthorTag = 312, - JSDocDeprecatedTag = 313, - JSDocClassTag = 314, - JSDocPublicTag = 315, - JSDocPrivateTag = 316, - JSDocProtectedTag = 317, - JSDocReadonlyTag = 318, - JSDocCallbackTag = 319, - JSDocEnumTag = 320, - JSDocParameterTag = 321, - JSDocReturnTag = 322, - JSDocThisTag = 323, - JSDocTypeTag = 324, - JSDocTemplateTag = 325, - JSDocTypedefTag = 326, - JSDocPropertyTag = 327, - SyntaxList = 328, - NotEmittedStatement = 329, - PartiallyEmittedExpression = 330, - CommaListExpression = 331, - MergeDeclarationMarker = 332, - EndOfDeclarationMarker = 333, - SyntheticReferenceExpression = 334, - Count = 335, + JSDocClassTag = 313, + JSDocPublicTag = 314, + JSDocPrivateTag = 315, + JSDocProtectedTag = 316, + JSDocReadonlyTag = 317, + JSDocCallbackTag = 318, + JSDocEnumTag = 319, + JSDocParameterTag = 320, + JSDocReturnTag = 321, + JSDocThisTag = 322, + JSDocTypeTag = 323, + JSDocTemplateTag = 324, + JSDocTypedefTag = 325, + JSDocPropertyTag = 326, + SyntaxList = 327, + NotEmittedStatement = 328, + PartiallyEmittedExpression = 329, + CommaListExpression = 330, + MergeDeclarationMarker = 331, + EndOfDeclarationMarker = 332, + SyntheticReferenceExpression = 333, + Count = 334, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -439,9 +438,9 @@ declare namespace ts { LastStatement = 244, FirstNode = 156, FirstJSDocNode = 297, - LastJSDocNode = 327, + LastJSDocNode = 326, FirstJSDocTagNode = 309, - LastJSDocTagNode = 327, + LastJSDocTagNode = 326, } export enum NodeFlags { None = 0, From b73411c985be1406de882af076e07b829b458eb8 Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 21 May 2020 10:19:36 +0800 Subject: [PATCH 22/24] Fix type and simplify code --- src/compiler/checker.ts | 6 +- src/compiler/transformers/esnext.ts | 88 +++++++++---------- src/compiler/types.ts | 6 ++ src/compiler/utilities.ts | 6 +- .../logicalAssignment2(target=es2015).js | 26 +++--- .../logicalAssignment2(target=es2015).symbols | 4 +- .../logicalAssignment2(target=es2015).types | 8 +- .../logicalAssignment2(target=es2020).js | 8 +- .../logicalAssignment2(target=es2020).symbols | 4 +- .../logicalAssignment2(target=es2020).types | 8 +- .../logicalAssignment2(target=esnext).js | 8 +- .../logicalAssignment2(target=esnext).symbols | 4 +- .../logicalAssignment2(target=esnext).types | 8 +- ...gicalAssignment5(target=es2015).errors.txt | 8 +- .../logicalAssignment5(target=es2015).types | 24 ++--- ...gicalAssignment5(target=es2020).errors.txt | 8 +- .../logicalAssignment5(target=es2020).types | 24 ++--- ...gicalAssignment5(target=esnext).errors.txt | 8 +- .../logicalAssignment5(target=esnext).types | 24 ++--- .../logicalAssignment/logicalAssignment2.ts | 4 +- 20 files changed, 136 insertions(+), 148 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d89182e3f51ab..a09a8a6a611f5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20813,7 +20813,6 @@ namespace ts { case SyntaxKind.AmpersandAmpersandEqualsToken: case SyntaxKind.QuestionQuestionEqualsToken: return narrowTypeByTruthiness(narrowType(type, expr.right, assumeTrue), expr.left, assumeTrue); - case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: @@ -22437,6 +22436,9 @@ namespace ts { const { left, operatorToken, right } = binaryExpression; switch (operatorToken.kind) { case SyntaxKind.EqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: if (node !== right) { return undefined; } @@ -22447,8 +22449,6 @@ namespace ts { return contextSensitive === true ? getTypeOfExpression(left) : contextSensitive; case SyntaxKind.BarBarToken: case SyntaxKind.QuestionQuestionToken: - case SyntaxKind.BarBarEqualsToken: - case SyntaxKind.QuestionQuestionEqualsToken: // When an || expression has a contextual type, the operands are contextually typed by that type, except // when that type originates in a binding pattern, the right operand is contextually typed by the type of // the left operand. When an || expression has no contextual type, the right operand is contextually typed diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 1e3d211d33f1f..9f7dea83c971b 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -21,8 +21,8 @@ namespace ts { switch (node.kind) { case SyntaxKind.BinaryExpression: const binaryExpression = node; - if (isLogicalOrCoalescingAssignmentOperator(binaryExpression.operatorToken.kind)) { - return transformLogicalAssignmentOperators(binaryExpression); + if (isLogicalOrCoalescingAssignmentExpression(binaryExpression)) { + return transformLogicalAssignmentOperator(binaryExpression); } // falls through default: @@ -30,56 +30,52 @@ namespace ts { } } - function transformLogicalAssignmentOperators(binaryExpression: BinaryExpression): VisitResult { + function transformLogicalAssignmentOperator(binaryExpression: AssignmentExpression>): VisitResult { const operator = binaryExpression.operatorToken; - if (isCompoundAssignment(operator.kind) && isLogicalOrCoalescingAssignmentOperator(operator.kind)) { - const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); - let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression)); - let assignmentTarget = left; - const right = skipParentheses(visitNode(binaryExpression.right, visitor, isExpression)); - if (isPropertyAccessExpression(left) || isElementAccessExpression(left)) { - const tempVariable = createTempVariable(hoistVariableDeclaration); - if (isPropertyAccessExpression(left)) { - assignmentTarget = createPropertyAccess( + const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); + let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression)); + let assignmentTarget = left; + const right = skipParentheses(visitNode(binaryExpression.right, visitor, isExpression)); + if (isAccessExpression(left)) { + const tempVariable = createTempVariable(hoistVariableDeclaration); + if (isPropertyAccessExpression(left)) { + assignmentTarget = createPropertyAccess( + tempVariable, + left.name + ); + left = createPropertyAccess( + createAssignment( tempVariable, - left.name - ); - left = createPropertyAccess( - createAssignment( - tempVariable, - left.expression - ), - left.name - ); - } - else { - assignmentTarget = createElementAccess( + left.expression + ), + left.name + ); + } + else { + assignmentTarget = createElementAccess( + tempVariable, + left.argumentExpression + ); + left = createElementAccess( + createAssignment( tempVariable, - left.argumentExpression - ); - left = createElementAccess( - createAssignment( - tempVariable, - left.expression - ), - left.argumentExpression - ); - } + left.expression + ), + left.argumentExpression + ); } + } - return createBinary( - left, - nonAssignmentOperator, - createParen( - createAssignment( - assignmentTarget, - right - ) + return createBinary( + left, + nonAssignmentOperator, + createParen( + createAssignment( + assignmentTarget, + right ) - ); - - } - Debug.fail("unexpected operator: " + operator.kind); + ) + ); } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0d6cf52c59e1e..5845f8ff6538b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1635,6 +1635,12 @@ namespace ts { | SyntaxKind.CommaToken ; + export type LogicalOrCoalescingAssignmentOperator + = SyntaxKind.AmpersandAmpersandEqualsToken + | SyntaxKind.BarBarEqualsToken + | SyntaxKind.QuestionQuestionEqualsToken + ; + export type BinaryOperatorToken = Token; export interface BinaryExpression extends Expression, Declaration { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e0bcfebb1b48b..014cd58d1b353 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4450,12 +4450,16 @@ namespace ts { || token === SyntaxKind.ExclamationToken; } - export function isLogicalOrCoalescingAssignmentOperator(token: SyntaxKind): boolean { + export function isLogicalOrCoalescingAssignmentOperator(token: SyntaxKind): token is LogicalOrCoalescingAssignmentOperator { return token === SyntaxKind.BarBarEqualsToken || token === SyntaxKind.AmpersandAmpersandEqualsToken || token === SyntaxKind.QuestionQuestionEqualsToken; } + export function isLogicalOrCoalescingAssignmentExpression(expr: BinaryExpression): expr is AssignmentExpression> { + return isLogicalOrCoalescingAssignmentOperator(expr.operatorToken.kind); + } + export function isAssignmentOperator(token: SyntaxKind): boolean { return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment; } diff --git a/tests/baselines/reference/logicalAssignment2(target=es2015).js b/tests/baselines/reference/logicalAssignment2(target=es2015).js index efeafc045b6d9..c5dbfbac49f05 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2015).js +++ b/tests/baselines/reference/logicalAssignment2(target=es2015).js @@ -19,8 +19,8 @@ b.baz ||= result.baz c.baz ??= result.baz a.foo["baz"] &&= result.foo.baz -b.foo["baz"] &&= result.foo.baz -c.foo["baz"] &&= result.foo.baz +b.foo["baz"] ||= result.foo.baz +c.foo["baz"] ??= result.foo.baz a.foo.bar().baz &&= result.foo.bar().baz b.foo.bar().baz ||= result.foo.bar().baz @@ -30,14 +30,14 @@ c.foo.bar().baz ??= result.foo.bar().baz //// [logicalAssignment2.js] "use strict"; -var _a, _b; -var _c, _d, _e, _f, _g, _h, _j, _k, _l; -(_c = a).baz && (_c.baz = result.baz); -(_d = b).baz || (_d.baz = result.baz); -(_a = (_e = c).baz) !== null && _a !== void 0 ? _a : (_e.baz = result.baz); -(_f = a.foo)["baz"] && (_f["baz"] = result.foo.baz); -(_g = b.foo)["baz"] && (_g["baz"] = result.foo.baz); -(_h = c.foo)["baz"] && (_h["baz"] = result.foo.baz); -(_j = a.foo.bar()).baz && (_j.baz = result.foo.bar().baz); -(_k = b.foo.bar()).baz || (_k.baz = result.foo.bar().baz); -(_b = (_l = c.foo.bar()).baz) !== null && _b !== void 0 ? _b : (_l.baz = result.foo.bar().baz); +var _a, _b, _c; +var _d, _e, _f, _g, _h, _j, _k, _l, _m; +(_d = a).baz && (_d.baz = result.baz); +(_e = b).baz || (_e.baz = result.baz); +(_a = (_f = c).baz) !== null && _a !== void 0 ? _a : (_f.baz = result.baz); +(_g = a.foo)["baz"] && (_g["baz"] = result.foo.baz); +(_h = b.foo)["baz"] || (_h["baz"] = result.foo.baz); +(_b = (_j = c.foo)["baz"]) !== null && _b !== void 0 ? _b : (_j["baz"] = result.foo.baz); +(_k = a.foo.bar()).baz && (_k.baz = result.foo.bar().baz); +(_l = b.foo.bar()).baz || (_l.baz = result.foo.bar().baz); +(_c = (_m = c.foo.bar()).baz) !== null && _c !== void 0 ? _c : (_m.baz = result.foo.bar().baz); diff --git a/tests/baselines/reference/logicalAssignment2(target=es2015).symbols b/tests/baselines/reference/logicalAssignment2(target=es2015).symbols index 7fe47ddad4009..503996af38772 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2015).symbols +++ b/tests/baselines/reference/logicalAssignment2(target=es2015).symbols @@ -69,7 +69,7 @@ a.foo["baz"] &&= result.foo.baz >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) -b.foo["baz"] &&= result.foo.baz +b.foo["baz"] ||= result.foo.baz >b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) @@ -80,7 +80,7 @@ b.foo["baz"] &&= result.foo.baz >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) -c.foo["baz"] &&= result.foo.baz +c.foo["baz"] ??= result.foo.baz >c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) diff --git a/tests/baselines/reference/logicalAssignment2(target=es2015).types b/tests/baselines/reference/logicalAssignment2(target=es2015).types index 82188f308d82a..7f1a58aa3222e 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment2(target=es2015).types @@ -68,8 +68,8 @@ a.foo["baz"] &&= result.foo.baz >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >baz : "" | 0 | 1 | 42 | undefined -b.foo["baz"] &&= result.foo.baz ->b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +b.foo["baz"] ||= result.foo.baz +>b.foo["baz"] ||= result.foo.baz : "" | 0 | 1 | 42 | undefined >b.foo["baz"] : "" | 0 | 1 | 42 | undefined >b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >b : A @@ -81,8 +81,8 @@ b.foo["baz"] &&= result.foo.baz >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >baz : "" | 0 | 1 | 42 | undefined -c.foo["baz"] &&= result.foo.baz ->c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +c.foo["baz"] ??= result.foo.baz +>c.foo["baz"] ??= result.foo.baz : "" | 0 | 1 | 42 | undefined >c.foo["baz"] : "" | 0 | 1 | 42 | undefined >c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >c : A diff --git a/tests/baselines/reference/logicalAssignment2(target=es2020).js b/tests/baselines/reference/logicalAssignment2(target=es2020).js index 7d4a1c1de64c5..fd285b64ad7c6 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2020).js +++ b/tests/baselines/reference/logicalAssignment2(target=es2020).js @@ -19,8 +19,8 @@ b.baz ||= result.baz c.baz ??= result.baz a.foo["baz"] &&= result.foo.baz -b.foo["baz"] &&= result.foo.baz -c.foo["baz"] &&= result.foo.baz +b.foo["baz"] ||= result.foo.baz +c.foo["baz"] ??= result.foo.baz a.foo.bar().baz &&= result.foo.bar().baz b.foo.bar().baz ||= result.foo.bar().baz @@ -35,8 +35,8 @@ var _a, _b, _c, _d, _e, _f, _g, _h, _j; (_b = b).baz || (_b.baz = result.baz); (_c = c).baz ?? (_c.baz = result.baz); (_d = a.foo)["baz"] && (_d["baz"] = result.foo.baz); -(_e = b.foo)["baz"] && (_e["baz"] = result.foo.baz); -(_f = c.foo)["baz"] && (_f["baz"] = result.foo.baz); +(_e = b.foo)["baz"] || (_e["baz"] = result.foo.baz); +(_f = c.foo)["baz"] ?? (_f["baz"] = result.foo.baz); (_g = a.foo.bar()).baz && (_g.baz = result.foo.bar().baz); (_h = b.foo.bar()).baz || (_h.baz = result.foo.bar().baz); (_j = c.foo.bar()).baz ?? (_j.baz = result.foo.bar().baz); diff --git a/tests/baselines/reference/logicalAssignment2(target=es2020).symbols b/tests/baselines/reference/logicalAssignment2(target=es2020).symbols index 7fe47ddad4009..503996af38772 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2020).symbols +++ b/tests/baselines/reference/logicalAssignment2(target=es2020).symbols @@ -69,7 +69,7 @@ a.foo["baz"] &&= result.foo.baz >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) -b.foo["baz"] &&= result.foo.baz +b.foo["baz"] ||= result.foo.baz >b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) @@ -80,7 +80,7 @@ b.foo["baz"] &&= result.foo.baz >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) -c.foo["baz"] &&= result.foo.baz +c.foo["baz"] ??= result.foo.baz >c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) diff --git a/tests/baselines/reference/logicalAssignment2(target=es2020).types b/tests/baselines/reference/logicalAssignment2(target=es2020).types index 82188f308d82a..7f1a58aa3222e 100644 --- a/tests/baselines/reference/logicalAssignment2(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment2(target=es2020).types @@ -68,8 +68,8 @@ a.foo["baz"] &&= result.foo.baz >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >baz : "" | 0 | 1 | 42 | undefined -b.foo["baz"] &&= result.foo.baz ->b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +b.foo["baz"] ||= result.foo.baz +>b.foo["baz"] ||= result.foo.baz : "" | 0 | 1 | 42 | undefined >b.foo["baz"] : "" | 0 | 1 | 42 | undefined >b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >b : A @@ -81,8 +81,8 @@ b.foo["baz"] &&= result.foo.baz >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >baz : "" | 0 | 1 | 42 | undefined -c.foo["baz"] &&= result.foo.baz ->c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +c.foo["baz"] ??= result.foo.baz +>c.foo["baz"] ??= result.foo.baz : "" | 0 | 1 | 42 | undefined >c.foo["baz"] : "" | 0 | 1 | 42 | undefined >c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >c : A diff --git a/tests/baselines/reference/logicalAssignment2(target=esnext).js b/tests/baselines/reference/logicalAssignment2(target=esnext).js index 69b06e5a01dc2..028fd724bc151 100644 --- a/tests/baselines/reference/logicalAssignment2(target=esnext).js +++ b/tests/baselines/reference/logicalAssignment2(target=esnext).js @@ -19,8 +19,8 @@ b.baz ||= result.baz c.baz ??= result.baz a.foo["baz"] &&= result.foo.baz -b.foo["baz"] &&= result.foo.baz -c.foo["baz"] &&= result.foo.baz +b.foo["baz"] ||= result.foo.baz +c.foo["baz"] ??= result.foo.baz a.foo.bar().baz &&= result.foo.bar().baz b.foo.bar().baz ||= result.foo.bar().baz @@ -34,8 +34,8 @@ a.baz &&= result.baz; b.baz ||= result.baz; c.baz ??= result.baz; a.foo["baz"] &&= result.foo.baz; -b.foo["baz"] &&= result.foo.baz; -c.foo["baz"] &&= result.foo.baz; +b.foo["baz"] ||= result.foo.baz; +c.foo["baz"] ??= result.foo.baz; a.foo.bar().baz &&= result.foo.bar().baz; b.foo.bar().baz ||= result.foo.bar().baz; c.foo.bar().baz ??= result.foo.bar().baz; diff --git a/tests/baselines/reference/logicalAssignment2(target=esnext).symbols b/tests/baselines/reference/logicalAssignment2(target=esnext).symbols index 7fe47ddad4009..503996af38772 100644 --- a/tests/baselines/reference/logicalAssignment2(target=esnext).symbols +++ b/tests/baselines/reference/logicalAssignment2(target=esnext).symbols @@ -69,7 +69,7 @@ a.foo["baz"] &&= result.foo.baz >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) -b.foo["baz"] &&= result.foo.baz +b.foo["baz"] ||= result.foo.baz >b.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >b : Symbol(b, Decl(logicalAssignment2.ts, 12, 13)) >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) @@ -80,7 +80,7 @@ b.foo["baz"] &&= result.foo.baz >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >baz : Symbol(baz, Decl(logicalAssignment2.ts, 4, 9)) -c.foo["baz"] &&= result.foo.baz +c.foo["baz"] ??= result.foo.baz >c.foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) >c : Symbol(c, Decl(logicalAssignment2.ts, 13, 13)) >foo : Symbol(A.foo, Decl(logicalAssignment2.ts, 0, 13)) diff --git a/tests/baselines/reference/logicalAssignment2(target=esnext).types b/tests/baselines/reference/logicalAssignment2(target=esnext).types index 82188f308d82a..7f1a58aa3222e 100644 --- a/tests/baselines/reference/logicalAssignment2(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment2(target=esnext).types @@ -68,8 +68,8 @@ a.foo["baz"] &&= result.foo.baz >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >baz : "" | 0 | 1 | 42 | undefined -b.foo["baz"] &&= result.foo.baz ->b.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +b.foo["baz"] ||= result.foo.baz +>b.foo["baz"] ||= result.foo.baz : "" | 0 | 1 | 42 | undefined >b.foo["baz"] : "" | 0 | 1 | 42 | undefined >b.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >b : A @@ -81,8 +81,8 @@ b.foo["baz"] &&= result.foo.baz >foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >baz : "" | 0 | 1 | 42 | undefined -c.foo["baz"] &&= result.foo.baz ->c.foo["baz"] &&= result.foo.baz : "" | 0 | 1 | 42 | undefined +c.foo["baz"] ??= result.foo.baz +>c.foo["baz"] ??= result.foo.baz : "" | 0 | 1 | 42 | undefined >c.foo["baz"] : "" | 0 | 1 | 42 | undefined >c.foo : { bar(): { baz: "" | 0 | 1 | 42 | undefined; }; baz: "" | 0 | 1 | 42 | undefined; } >c : A diff --git a/tests/baselines/reference/logicalAssignment5(target=es2015).errors.txt b/tests/baselines/reference/logicalAssignment5(target=es2015).errors.txt index 663162e916547..8e9760990b033 100644 --- a/tests/baselines/reference/logicalAssignment5(target=es2015).errors.txt +++ b/tests/baselines/reference/logicalAssignment5(target=es2015).errors.txt @@ -1,12 +1,10 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(12,12): error TS7006: Parameter 'a' implicitly has an 'any' type. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(13,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(17,12): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(22,12): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(27,27): error TS7006: Parameter 'a' implicitly has an 'any' type. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts (6 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts (4 errors) ==== function foo1 (f?: (a: number) => void) { f ??= (a => a) f(42) @@ -19,8 +17,6 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): er function foo3 (f?: (a: number) => void) { f &&= (a => a) - ~ -!!! error TS7006: Parameter 'a' implicitly has an 'any' type. f(42) ~ !!! error TS2722: Cannot invoke an object which is possibly 'undefined'. @@ -42,8 +38,6 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): er function bar3 (f?: (a: number) => void) { f &&= (f.toString(), (a => a)) - ~ -!!! error TS7006: Parameter 'a' implicitly has an 'any' type. f(42) ~ !!! error TS2722: Cannot invoke an object which is possibly 'undefined'. diff --git a/tests/baselines/reference/logicalAssignment5(target=es2015).types b/tests/baselines/reference/logicalAssignment5(target=es2015).types index 82ed2ab2d2f43..6ffb9b65a123e 100644 --- a/tests/baselines/reference/logicalAssignment5(target=es2015).types +++ b/tests/baselines/reference/logicalAssignment5(target=es2015).types @@ -43,12 +43,12 @@ function foo3 (f?: (a: number) => void) { >a : number f &&= (a => a) ->f &&= (a => a) : ((a: any) => any) | undefined +>f &&= (a => a) : ((a: number) => number) | undefined >f : ((a: number) => void) | undefined ->(a => a) : (a: any) => any ->a => a : (a: any) => any ->a : any ->a : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number f(42) >f(42) : void @@ -112,18 +112,18 @@ function bar3 (f?: (a: number) => void) { >a : number f &&= (f.toString(), (a => a)) ->f &&= (f.toString(), (a => a)) : ((a: any) => any) | undefined +>f &&= (f.toString(), (a => a)) : ((a: number) => number) | undefined >f : ((a: number) => void) | undefined ->(f.toString(), (a => a)) : (a: any) => any ->f.toString(), (a => a) : (a: any) => any +>(f.toString(), (a => a)) : (a: number) => number +>f.toString(), (a => a) : (a: number) => number >f.toString() : string >f.toString : () => string >f : (a: number) => void >toString : () => string ->(a => a) : (a: any) => any ->a => a : (a: any) => any ->a : any ->a : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number f(42) >f(42) : void diff --git a/tests/baselines/reference/logicalAssignment5(target=es2020).errors.txt b/tests/baselines/reference/logicalAssignment5(target=es2020).errors.txt index 663162e916547..8e9760990b033 100644 --- a/tests/baselines/reference/logicalAssignment5(target=es2020).errors.txt +++ b/tests/baselines/reference/logicalAssignment5(target=es2020).errors.txt @@ -1,12 +1,10 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(12,12): error TS7006: Parameter 'a' implicitly has an 'any' type. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(13,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(17,12): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(22,12): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(27,27): error TS7006: Parameter 'a' implicitly has an 'any' type. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts (6 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts (4 errors) ==== function foo1 (f?: (a: number) => void) { f ??= (a => a) f(42) @@ -19,8 +17,6 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): er function foo3 (f?: (a: number) => void) { f &&= (a => a) - ~ -!!! error TS7006: Parameter 'a' implicitly has an 'any' type. f(42) ~ !!! error TS2722: Cannot invoke an object which is possibly 'undefined'. @@ -42,8 +38,6 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): er function bar3 (f?: (a: number) => void) { f &&= (f.toString(), (a => a)) - ~ -!!! error TS7006: Parameter 'a' implicitly has an 'any' type. f(42) ~ !!! error TS2722: Cannot invoke an object which is possibly 'undefined'. diff --git a/tests/baselines/reference/logicalAssignment5(target=es2020).types b/tests/baselines/reference/logicalAssignment5(target=es2020).types index 82ed2ab2d2f43..6ffb9b65a123e 100644 --- a/tests/baselines/reference/logicalAssignment5(target=es2020).types +++ b/tests/baselines/reference/logicalAssignment5(target=es2020).types @@ -43,12 +43,12 @@ function foo3 (f?: (a: number) => void) { >a : number f &&= (a => a) ->f &&= (a => a) : ((a: any) => any) | undefined +>f &&= (a => a) : ((a: number) => number) | undefined >f : ((a: number) => void) | undefined ->(a => a) : (a: any) => any ->a => a : (a: any) => any ->a : any ->a : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number f(42) >f(42) : void @@ -112,18 +112,18 @@ function bar3 (f?: (a: number) => void) { >a : number f &&= (f.toString(), (a => a)) ->f &&= (f.toString(), (a => a)) : ((a: any) => any) | undefined +>f &&= (f.toString(), (a => a)) : ((a: number) => number) | undefined >f : ((a: number) => void) | undefined ->(f.toString(), (a => a)) : (a: any) => any ->f.toString(), (a => a) : (a: any) => any +>(f.toString(), (a => a)) : (a: number) => number +>f.toString(), (a => a) : (a: number) => number >f.toString() : string >f.toString : () => string >f : (a: number) => void >toString : () => string ->(a => a) : (a: any) => any ->a => a : (a: any) => any ->a : any ->a : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number f(42) >f(42) : void diff --git a/tests/baselines/reference/logicalAssignment5(target=esnext).errors.txt b/tests/baselines/reference/logicalAssignment5(target=esnext).errors.txt index 663162e916547..8e9760990b033 100644 --- a/tests/baselines/reference/logicalAssignment5(target=esnext).errors.txt +++ b/tests/baselines/reference/logicalAssignment5(target=esnext).errors.txt @@ -1,12 +1,10 @@ -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(12,12): error TS7006: Parameter 'a' implicitly has an 'any' type. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(13,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(17,12): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(22,12): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(27,27): error TS7006: Parameter 'a' implicitly has an 'any' type. tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. -==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts (6 errors) ==== +==== tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts (4 errors) ==== function foo1 (f?: (a: number) => void) { f ??= (a => a) f(42) @@ -19,8 +17,6 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): er function foo3 (f?: (a: number) => void) { f &&= (a => a) - ~ -!!! error TS7006: Parameter 'a' implicitly has an 'any' type. f(42) ~ !!! error TS2722: Cannot invoke an object which is possibly 'undefined'. @@ -42,8 +38,6 @@ tests/cases/conformance/esnext/logicalAssignment/logicalAssignment5.ts(28,5): er function bar3 (f?: (a: number) => void) { f &&= (f.toString(), (a => a)) - ~ -!!! error TS7006: Parameter 'a' implicitly has an 'any' type. f(42) ~ !!! error TS2722: Cannot invoke an object which is possibly 'undefined'. diff --git a/tests/baselines/reference/logicalAssignment5(target=esnext).types b/tests/baselines/reference/logicalAssignment5(target=esnext).types index 82ed2ab2d2f43..6ffb9b65a123e 100644 --- a/tests/baselines/reference/logicalAssignment5(target=esnext).types +++ b/tests/baselines/reference/logicalAssignment5(target=esnext).types @@ -43,12 +43,12 @@ function foo3 (f?: (a: number) => void) { >a : number f &&= (a => a) ->f &&= (a => a) : ((a: any) => any) | undefined +>f &&= (a => a) : ((a: number) => number) | undefined >f : ((a: number) => void) | undefined ->(a => a) : (a: any) => any ->a => a : (a: any) => any ->a : any ->a : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number f(42) >f(42) : void @@ -112,18 +112,18 @@ function bar3 (f?: (a: number) => void) { >a : number f &&= (f.toString(), (a => a)) ->f &&= (f.toString(), (a => a)) : ((a: any) => any) | undefined +>f &&= (f.toString(), (a => a)) : ((a: number) => number) | undefined >f : ((a: number) => void) | undefined ->(f.toString(), (a => a)) : (a: any) => any ->f.toString(), (a => a) : (a: any) => any +>(f.toString(), (a => a)) : (a: number) => number +>f.toString(), (a => a) : (a: number) => number >f.toString() : string >f.toString : () => string >f : (a: number) => void >toString : () => string ->(a => a) : (a: any) => any ->a => a : (a: any) => any ->a : any ->a : any +>(a => a) : (a: number) => number +>a => a : (a: number) => number +>a : number +>a : number f(42) >f(42) : void diff --git a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts index 4bf3dd3581a11..30bd5b9254df5 100644 --- a/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts +++ b/tests/cases/conformance/esnext/logicalAssignment/logicalAssignment2.ts @@ -20,8 +20,8 @@ b.baz ||= result.baz c.baz ??= result.baz a.foo["baz"] &&= result.foo.baz -b.foo["baz"] &&= result.foo.baz -c.foo["baz"] &&= result.foo.baz +b.foo["baz"] ||= result.foo.baz +c.foo["baz"] ??= result.foo.baz a.foo.bar().baz &&= result.foo.bar().baz b.foo.bar().baz ||= result.foo.bar().baz From 2997860c2e475bd2a9950f55c5ac8b386639301a Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 21 May 2020 10:23:00 +0800 Subject: [PATCH 23/24] fix names --- src/compiler/transformers/esnext.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 9f7dea83c971b..65bb1c1713743 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -22,7 +22,7 @@ namespace ts { case SyntaxKind.BinaryExpression: const binaryExpression = node; if (isLogicalOrCoalescingAssignmentExpression(binaryExpression)) { - return transformLogicalAssignmentOperator(binaryExpression); + return transformLogicalAssignment(binaryExpression); } // falls through default: @@ -30,7 +30,7 @@ namespace ts { } } - function transformLogicalAssignmentOperator(binaryExpression: AssignmentExpression>): VisitResult { + function transformLogicalAssignment(binaryExpression: AssignmentExpression>): VisitResult { const operator = binaryExpression.operatorToken; const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression)); From fed922a5cbe0d50c491e009c488f7303a15e5b95 Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 21 May 2020 10:53:24 +0800 Subject: [PATCH 24/24] Accept baseline --- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 80295d04001d9..4bec3534e9bae 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -979,6 +979,7 @@ declare namespace ts { export type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; export type AssignmentOperatorOrHigher = SyntaxKind.QuestionQuestionToken | LogicalOperatorOrHigher | AssignmentOperator; export type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; + export type LogicalOrCoalescingAssignmentOperator = SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; export type BinaryOperatorToken = Token; export interface BinaryExpression extends Expression, Declaration { kind: SyntaxKind.BinaryExpression; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 309cd7088c2d2..f163a5f4ee395 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -979,6 +979,7 @@ declare namespace ts { export type AssignmentOperator = SyntaxKind.EqualsToken | CompoundAssignmentOperator; export type AssignmentOperatorOrHigher = SyntaxKind.QuestionQuestionToken | LogicalOperatorOrHigher | AssignmentOperator; export type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; + export type LogicalOrCoalescingAssignmentOperator = SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; export type BinaryOperatorToken = Token; export interface BinaryExpression extends Expression, Declaration { kind: SyntaxKind.BinaryExpression;