diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1f379c30468..00b93021d4f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -216,6 +216,7 @@ namespace ts { const neverType = createIntrinsicType(TypeFlags.Never, "never"); const silentNeverType = createIntrinsicType(TypeFlags.Never, "never"); const nonPrimitiveType = createIntrinsicType(TypeFlags.NonPrimitive, "object"); + const nilType = strictNullChecks ? createIntrinsicType(TypeFlags.Nil | TypeFlags.ContainsWideningType, "nil") : neverType; const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -326,49 +327,54 @@ namespace ts { TypeofNEHostObject = 1 << 13, // typeof x !== "xxx" EQUndefined = 1 << 14, // x === undefined EQNull = 1 << 15, // x === null - EQUndefinedOrNull = 1 << 16, // x == undefined / x == null - NEUndefined = 1 << 17, // x !== undefined - NENull = 1 << 18, // x !== null - NEUndefinedOrNull = 1 << 19, // x != undefined / x != null - Truthy = 1 << 20, // x - Falsy = 1 << 21, // !x - Discriminatable = 1 << 22, // May have discriminant property - All = (1 << 23) - 1, + EQNil = 1 << 16, // Null propagating type + EQUndefinedOrNull = 1 << 17, // x == undefined / x == null + EQUndefinedOrNullOrNil = 1 << 18, + NEUndefined = 1 << 19, // x !== undefined + NENull = 1 << 20, // x !== null + NENil = 1 << 21, // Not null propagating type + NEUndefinedOrNull = 1 << 22, // x != undefined / x != null + NEUndefinedOrNullOrNil = 1 << 23, + Truthy = 1 << 24, // x + Falsy = 1 << 25, // !x + Discriminatable = 1 << 26, // May have discriminant property + All = (1 << 27) - 1, // The following members encode facts about particular kinds of types for use in the getTypeFacts function. // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. - BaseStringStrictFacts = TypeofEQString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, - BaseStringFacts = BaseStringStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, + BaseStringStrictFacts = TypeofEQString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NENil | NEUndefinedOrNull | NEUndefinedOrNullOrNil, + BaseStringFacts = BaseStringStrictFacts | EQUndefined | EQNull | EQNil | EQUndefinedOrNull | EQUndefinedOrNullOrNil | Falsy, StringStrictFacts = BaseStringStrictFacts | Truthy | Falsy, StringFacts = BaseStringFacts | Truthy, EmptyStringStrictFacts = BaseStringStrictFacts | Falsy, EmptyStringFacts = BaseStringFacts, NonEmptyStringStrictFacts = BaseStringStrictFacts | Truthy, NonEmptyStringFacts = BaseStringFacts | Truthy, - BaseNumberStrictFacts = TypeofEQNumber | TypeofNEString | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, - BaseNumberFacts = BaseNumberStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, + BaseNumberStrictFacts = TypeofEQNumber | TypeofNEString | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NENil | NEUndefinedOrNull | NEUndefinedOrNullOrNil, + BaseNumberFacts = BaseNumberStrictFacts | EQUndefined | EQNull | EQNil | EQUndefinedOrNull | EQUndefinedOrNullOrNil | Falsy, NumberStrictFacts = BaseNumberStrictFacts | Truthy | Falsy, NumberFacts = BaseNumberFacts | Truthy, ZeroStrictFacts = BaseNumberStrictFacts | Falsy, ZeroFacts = BaseNumberFacts, NonZeroStrictFacts = BaseNumberStrictFacts | Truthy, NonZeroFacts = BaseNumberFacts | Truthy, - BaseBooleanStrictFacts = TypeofEQBoolean | TypeofNEString | TypeofNENumber | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, - BaseBooleanFacts = BaseBooleanStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, + BaseBooleanStrictFacts = TypeofEQBoolean | TypeofNEString | TypeofNENumber | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NENil | NEUndefinedOrNull | NEUndefinedOrNullOrNil, + BaseBooleanFacts = BaseBooleanStrictFacts | EQUndefined | EQNull | EQNil | EQUndefinedOrNull | EQUndefinedOrNullOrNil | Falsy, BooleanStrictFacts = BaseBooleanStrictFacts | Truthy | Falsy, BooleanFacts = BaseBooleanFacts | Truthy, FalseStrictFacts = BaseBooleanStrictFacts | Falsy, FalseFacts = BaseBooleanFacts, TrueStrictFacts = BaseBooleanStrictFacts | Truthy, TrueFacts = BaseBooleanFacts | Truthy, - SymbolStrictFacts = TypeofEQSymbol | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, - SymbolFacts = SymbolStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, - ObjectStrictFacts = TypeofEQObject | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | NEUndefined | NENull | NEUndefinedOrNull | Truthy | Discriminatable, - ObjectFacts = ObjectStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, - FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy | Discriminatable, - FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, - UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy, - NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy, + SymbolStrictFacts = TypeofEQSymbol | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NENil | NEUndefinedOrNull | NEUndefinedOrNullOrNil | Truthy, + SymbolFacts = SymbolStrictFacts | EQUndefined | EQNull | EQNil | EQUndefinedOrNull | EQUndefinedOrNullOrNil | Falsy, + ObjectStrictFacts = TypeofEQObject | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | NEUndefined | NENull | NENil | NEUndefinedOrNull | NEUndefinedOrNullOrNil | Truthy | Discriminatable, + ObjectFacts = ObjectStrictFacts | EQUndefined | EQNull | EQNil | EQUndefinedOrNull | EQUndefinedOrNullOrNil | Falsy, + FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NENil | NEUndefinedOrNull | NEUndefinedOrNullOrNil | Truthy | Discriminatable, + FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQNil | EQUndefinedOrNull | EQUndefinedOrNullOrNil | Falsy, + UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNullOrNil | EQUndefinedOrNull | NENull | NENil | Falsy, + NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNullOrNil | EQUndefinedOrNull | NEUndefined | NENil | Falsy, + NilFacts = TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQNil | EQUndefinedOrNullOrNil | NEUndefinedOrNull | NEUndefined | NENull | Falsy, } const typeofEQFacts = createMapFromTemplate({ @@ -2201,7 +2207,7 @@ namespace ts { } } if (flags & TypeFlags.Null) result.push(nullType); - if (flags & TypeFlags.Undefined) result.push(undefinedType); + if (flags & TypeFlags.UndefinedLike) result.push(undefinedType); return result || types; } @@ -8904,6 +8910,7 @@ namespace ts { if (flags & TypeFlags.Void) types.push(voidType); if (flags & TypeFlags.Undefined) types.push(undefinedType); if (flags & TypeFlags.Null) types.push(nullType); + if (flags & TypeFlags.Nil) types.push(nilType); return getUnionType(types); } @@ -8913,33 +8920,31 @@ namespace ts { type; } - function getNonNullableType(type: Type): Type { - return strictNullChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; + function getNonNullableType(type: Type, propagateNil?: boolean): Type { + return strictNullChecks ? getTypeWithFacts(type, propagateNil ? TypeFacts.NEUndefinedOrNull : TypeFacts.NEUndefinedOrNullOrNil) : type; } - function getNullPropagatingType(type: Type) { - return strictNullChecks && (getTypeFacts(type) & TypeFacts.EQUndefinedOrNull) === 0 - ? neverType - : undefinedType; - } - - function propagateNullType(type: Type, propagatingType: Type) { - return propagatingType === neverType ? type : getUnionType([type, propagatingType]); - } - - function propagateNullReturnType(signature: Signature, propagatingType: Type) { - if (propagatingType === neverType) { - return signature; + function checkNullPropagation(node: Node) { + if (node.flags & NodeFlags.PropagateNull) { + if (!compilerOptions.experimentalNullPropagation) { + error(node, Diagnostics.Experimental_support_for_null_propagation_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalNullPropagation_option_to_remove_this_warning); + }; + return strictNullChecks; } + return false; + } - const returnType = getReturnTypeOfSignature(signature); - const propagatingReturnType = propagateNullType(returnType, propagatingType); - if (returnType === propagatingReturnType) { - return signature; + function propagateNil(type: Type, sourceType: Type) { + return strictNullChecks && getTypeFacts(sourceType) & TypeFacts.EQUndefinedOrNullOrNil + ? getUnionType([type, nilType]) + : type; + } + + function propagateNilSignature(signature: Signature, sourceType: Type) { + if (strictNullChecks && getTypeFacts(sourceType) & TypeFacts.EQUndefinedOrNullOrNil) { + signature = cloneSignature(signature); + signature.resolvedReturnType = getUnionType([getReturnTypeOfSignature(signature), nilType]); } - - signature = cloneSignature(signature); - signature.resolvedReturnType = propagatingReturnType; return signature; } @@ -9024,6 +9029,9 @@ namespace ts { if (type.flags & TypeFlags.Nullable) { return anyType; } + if (type.flags & TypeFlags.Nil) { + return strictNullChecks ? undefinedType : anyType; + } if (getObjectFlags(type) & ObjectFlags.ObjectLiteral) { return getWidenedTypeOfObjectLiteral(type); } @@ -9825,6 +9833,9 @@ namespace ts { if (flags & TypeFlags.Null) { return TypeFacts.NullFacts; } + if (flags & TypeFlags.Nil) { + return TypeFacts.NilFacts; + } if (flags & TypeFlags.ESSymbol) { return strictNullChecks ? TypeFacts.SymbolStrictFacts : TypeFacts.SymbolFacts; } @@ -13117,19 +13128,21 @@ namespace ts { return true; } - function checkNonNullExpression(node: Expression | QualifiedName) { - return checkNonNullType(checkExpression(node), node); + function checkNonNullExpression(node: Expression | QualifiedName, propagateNil?: boolean) { + return checkNonNullType(checkExpression(node), node, propagateNil); } - function checkNonNullType(type: Type, errorNode: Node): Type { - const kind = (strictNullChecks ? getFalsyFlags(type) : type.flags); - if (kind & TypeFlags.Nullable) { - error(errorNode, kind & TypeFlags.Undefined ? kind & TypeFlags.Null ? + function checkNonNullType(type: Type, errorNode: Node, propagatesNil?: boolean): Type { + const disallowedFlags = propagatesNil ? TypeFlags.NilPropagatingNullable : TypeFlags.Nullable; + const kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & disallowedFlags; + if (kind) { + const undefinedFlags = propagatesNil ? TypeFlags.Undefined : TypeFlags.UndefinedLike; + error(errorNode, kind & undefinedFlags ? kind & TypeFlags.Null ? Diagnostics.Object_is_possibly_null_or_undefined : Diagnostics.Object_is_possibly_undefined : Diagnostics.Object_is_possibly_null); - const t = getNonNullableType(type); - return t.flags & (TypeFlags.Nullable | TypeFlags.Never) ? unknownType : t; + const t = getNonNullableType(type, propagatesNil); + return t.flags & (disallowedFlags | TypeFlags.Never) ? unknownType : t; } return type; } @@ -13182,14 +13195,9 @@ namespace ts { } function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { - const propagateNull = node.flags & NodeFlags.PropagateNull; - if (propagateNull && !compilerOptions.experimentalNullPropagation) { - error(node, Diagnostics.Experimental_support_for_null_propagation_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalNullPropagation_option_to_remove_this_warning); - } - - const objectType = propagateNull ? checkExpression(left) : checkNonNullExpression(left); - const type = propagateNull ? getNonNullableType(objectType) : objectType; - const propagatingType = propagateNull ? getNullPropagatingType(objectType) : neverType; + const propagatesNil = checkNullPropagation(node); + const sourceType = propagatesNil ? checkExpression(left) : checkNonNullExpression(left); + const type = propagatesNil ? getNonNullableType(sourceType) : sourceType; if (isTypeAny(type) || type === silentNeverType) { return type; @@ -13239,10 +13247,12 @@ namespace ts { if (node.kind !== SyntaxKind.PropertyAccessExpression || assignmentKind === AssignmentKind.Definite || !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) && !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) { - return propagateNullType(propType, propagatingType); + return propagatesNil ? propagateNil(propType, sourceType) : propType; } + const flowType = getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined); - return propagateNullType(assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType, propagatingType); + const resultType = assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; + return propagatesNil ? propagateNil(resultType, sourceType) : resultType; } function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean { @@ -13313,14 +13323,9 @@ namespace ts { function checkIndexedAccess(node: ElementAccessExpression): Type { checkGrammarNullPropagation(node); - const propagateNull = node.flags & NodeFlags.PropagateNull; - if (propagateNull && !compilerOptions.experimentalNullPropagation) { - error(node, Diagnostics.Experimental_support_for_null_propagation_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalNullPropagation_option_to_remove_this_warning); - } - - const objectType = propagateNull ? checkExpression(node.expression) : checkNonNullExpression(node.expression); - const type = propagateNull ? getNonNullableType(objectType) : objectType; - const propagatingType = propagateNull ? getNullPropagatingType(objectType) : neverType; + const propagatesNil = checkNullPropagation(node); + const sourceType = propagatesNil ? checkExpression(node.expression) : checkNonNullExpression(node.expression); + const type = propagatesNil ? getNonNullableType(sourceType) : sourceType; const indexExpression = node.argumentExpression; if (!indexExpression) { @@ -13349,7 +13354,8 @@ namespace ts { return unknownType; } - return propagateNullType(checkIndexedAccessIndexType(getIndexedAccessType(type, indexType, node), node), propagatingType); + const resultType = checkIndexedAccessIndexType(getIndexedAccessType(type, indexType, node), node); + return propagatesNil ? propagateNil(resultType, sourceType) : resultType; } function checkThatExpressionIsProperSymbolReference(expression: Expression, expressionType: Type, reportError: boolean): boolean { @@ -14089,7 +14095,7 @@ namespace ts { } } - function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], propagatingType?: Type, headMessage?: DiagnosticMessage): Signature { + function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], headMessage?: DiagnosticMessage): Signature { const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression; const isDecorator = node.kind === SyntaxKind.Decorator; const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node); @@ -14195,7 +14201,7 @@ namespace ts { result = chooseOverload(candidates, assignableRelation, signatureHelpTrailingComma); } if (result) { - return propagateNullReturnType(result, propagatingType || neverType); + return result; } // No signatures were applicable. Now report errors based on the last applicable signature with @@ -14250,7 +14256,7 @@ namespace ts { if (candidate.typeParameters && typeArguments) { candidate = getSignatureInstantiation(candidate, map(typeArguments, getTypeFromTypeNode)); } - return propagateNullReturnType(candidate, propagatingType || neverType); + return candidate; } } } @@ -14350,19 +14356,15 @@ namespace ts { return resolveUntypedCall(node); } - - const propagateNull = node.flags & NodeFlags.PropagateNull; - if (propagateNull && !compilerOptions.experimentalNullPropagation) { - error(node, Diagnostics.Experimental_support_for_null_propagation_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalNullPropagation_option_to_remove_this_warning); - } - - const funcType = propagateNull ? checkExpression(node.expression) : checkNonNullExpression(node.expression); - const type = propagateNull ? getNonNullableType(funcType) : funcType; - if (type === silentNeverType) { + const propagatesNil = checkNullPropagation(node); + const propagatesNilOfExpression = checkNullPropagation(node.expression); + const sourceType = propagatesNil ? checkExpression(node.expression) : checkNonNullExpression(node.expression, /*propagateNil*/ true); + const funcType = propagatesNil || propagatesNilOfExpression ? getNonNullableType(sourceType) : sourceType; + if (funcType === silentNeverType) { return silentNeverSignature; } - const apparentType = getApparentType(type); + const apparentType = getApparentType(funcType); if (apparentType === unknownType) { // Another error has already been reported return resolveErrorCall(node); @@ -14378,10 +14380,10 @@ namespace ts { // TS 1.0 Spec: 4.12 // In an untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual // types are provided for the argument expressions, and the result is always of type Any. - if (isUntypedFunctionCall(type, apparentType, callSignatures.length, constructSignatures.length)) { + if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) { // The unknownType indicates that an error already occurred (and was reported). No // need to report another error in this case. - if (type !== unknownType && node.typeArguments) { + if (funcType !== unknownType && node.typeArguments) { error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments); } return resolveUntypedCall(node); @@ -14391,7 +14393,7 @@ namespace ts { // with multiple call signatures. if (!callSignatures.length) { if (constructSignatures.length) { - error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(type)); + error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); } else { error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); @@ -14399,8 +14401,8 @@ namespace ts { return resolveErrorCall(node); } - const propagatingType = propagateNull ? getNullPropagatingType(funcType) : neverType; - return resolveCall(node, callSignatures, candidatesOutArray, propagatingType); + const signature = resolveCall(node, callSignatures, candidatesOutArray); + return propagatesNil || propagatesNilOfExpression ? propagateNilSignature(signature, sourceType) : signature; } /** @@ -14434,14 +14436,10 @@ namespace ts { } } - const propagateNull = node.flags & NodeFlags.PropagateNull; - if (propagateNull && !compilerOptions.experimentalNullPropagation) { - error(node, Diagnostics.Experimental_support_for_null_propagation_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalNullPropagation_option_to_remove_this_warning); - } - - const funcType = propagateNull ? checkExpression(node.expression) : checkNonNullExpression(node.expression); - const type = propagateNull ? getNonNullableType(funcType) : funcType; - if (type === silentNeverType) { + const propagatesNil = checkNullPropagation(node); + const sourceType = propagatesNil ? checkExpression(node.expression) : checkNonNullExpression(node.expression); + const funcType = propagatesNil ? getNonNullableType(sourceType) : sourceType; + if (funcType === silentNeverType) { return silentNeverSignature; } @@ -14450,7 +14448,7 @@ namespace ts { // function call, but using the construct signatures as the initial set of candidate // signatures for overload resolution. The result type of the function call becomes // the result type of the operation. - const apparentType = getApparentType(type); + const apparentType = getApparentType(funcType); if (apparentType === unknownType) { // Another error has already been reported return resolveErrorCall(node); @@ -14486,8 +14484,8 @@ namespace ts { return resolveErrorCall(node); } - const propagatingType = propagateNull ? getNullPropagatingType(funcType) : neverType; - return resolveCall(node, constructSignatures, candidatesOutArray, propagatingType); + const signature = resolveCall(node, constructSignatures, candidatesOutArray); + return propagatesNil ? propagateNilSignature(signature, sourceType) : signature; } // If expressionType's apparent type is an object type with no construct signatures but @@ -14503,7 +14501,7 @@ namespace ts { if (getThisTypeOfSignature(signature) === voidType) { error(node, Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void); } - return signature; + return propagatesNil ? propagateNilSignature(signature, sourceType) : signature; } error(node, Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature); @@ -14624,7 +14622,7 @@ namespace ts { return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, /*propagatingType*/ undefined, headMessage); + return resolveCall(node, callSignatures, candidatesOutArray, headMessage); } /** @@ -15463,15 +15461,14 @@ namespace ts { booleanType; case SyntaxKind.PlusPlusToken: case SyntaxKind.MinusMinusToken: - const propagateNull = node.operand.flags & NodeFlags.PropagateNull; - const nonNullType = propagateNull ? getNonNullableType(operandType) : checkNonNullType(operandType, node.operand); - const propagatingType = propagateNull ? getNullPropagatingType(operandType) : neverType; - const ok = checkArithmeticOperandType(node.operand, nonNullType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); + const propagatesNil = checkNullPropagation(node.operand); + const sourceType = propagatesNil ? operandType : checkNonNullType(operandType, node.operand); + const ok = checkArithmeticOperandType(node.operand, getNonNullableType(sourceType), Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access); } - return propagateNullType(numberType, propagatingType); + return propagatesNil ? propagateNil(numberType, sourceType) : numberType; } return unknownType; } @@ -15481,15 +15478,14 @@ namespace ts { if (operandType === silentNeverType) { return silentNeverType; } - const propagateNull = node.operand.flags & NodeFlags.PropagateNull; - const nonNullType = propagateNull ? getNonNullableType(operandType) : checkNonNullType(operandType, node.operand); - const propagatingType = propagateNull ? getNullPropagatingType(operandType) : neverType; - const ok = checkArithmeticOperandType(node.operand, nonNullType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); + const propagatesNil = checkNullPropagation(node.operand); + const sourceType = propagatesNil ? operandType : checkNonNullType(operandType, node.operand); + const ok = checkArithmeticOperandType(node.operand, getNonNullableType(sourceType), Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access); } - return propagateNullType(numberType, propagatingType); + return propagatesNil ? propagateNil(numberType, sourceType) : numberType; } // Return true if type might be of the given kind. A union or intersection type might be of a given @@ -15832,14 +15828,10 @@ namespace ts { if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) { return checkDestructuringAssignment(left, checkExpression(right, contextualMapper), contextualMapper); } + const propagatesNil = operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment && (left.flags & NodeFlags.PropagateNull) !== 0; let leftType = checkExpression(left, contextualMapper); let rightType = checkExpression(right, contextualMapper); - const propagateNull = operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment && left.flags & NodeFlags.PropagateNull; - const propagatingType = propagateNull ? getNullPropagatingType(leftType) : neverType; - if (propagateNull) { - leftType = getNonNullableType(leftType); - } - + const sourceType = leftType; switch (operator) { case SyntaxKind.AsteriskToken: case SyntaxKind.AsteriskAsteriskToken: @@ -15867,7 +15859,7 @@ namespace ts { return silentNeverType; } - leftType = checkNonNullType(leftType, left); + leftType = propagatesNil ? getNonNullableType(sourceType) : checkNonNullType(sourceType, left); rightType = checkNonNullType(rightType, right); let suggestedOperator: SyntaxKind; @@ -15887,7 +15879,7 @@ namespace ts { } } - return propagateNullType(numberType, propagatingType); + return propagatesNil ? propagateNil(numberType, sourceType) : numberType; case SyntaxKind.PlusToken: case SyntaxKind.PlusEqualsToken: if (leftType === silentNeverType || rightType === silentNeverType) { @@ -15895,7 +15887,7 @@ namespace ts { } if (!isTypeOfKind(leftType, TypeFlags.Any | TypeFlags.StringLike) && !isTypeOfKind(rightType, TypeFlags.Any | TypeFlags.StringLike)) { - leftType = checkNonNullType(leftType, left); + leftType = propagatesNil ? getNonNullableType(sourceType) : checkNonNullType(sourceType, left); rightType = checkNonNullType(rightType, right); } @@ -15918,7 +15910,7 @@ namespace ts { // Symbols are not allowed at all in arithmetic expressions if (resultType && !checkForDisallowedESSymbolOperand(operator)) { - return propagateNullType(resultType, propagatingType); + return propagatesNil ? propagateNil(resultType, sourceType) : resultType; } } @@ -15930,7 +15922,7 @@ namespace ts { if (operator === SyntaxKind.PlusEqualsToken) { checkAssignmentOperator(resultType); } - return propagateNullType(resultType, propagatingType); + return propagatesNil ? propagateNil(resultType, sourceType) : resultType; case SyntaxKind.LessThanToken: case SyntaxKind.GreaterThanToken: case SyntaxKind.LessThanEqualsToken: diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index c00fff3683e..311bd1aa791 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1117,6 +1117,7 @@ namespace ts { // 1..toString is a valid property access, emit a dot after the literal // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal function needsDotDotForPropertyAccess(expression: Expression) { + expression = skipOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions); if (expression.kind === SyntaxKind.NumericLiteral) { // check if numeric literal is a decimal literal that was originally written with a dot const text = getLiteralTextOfNode(expression); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 9193856e366..912981ef283 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2585,7 +2585,7 @@ namespace ts { ); } if (reference === node && !copyNullPropagation && reference.flags & NodeFlags.PropagateNull) { - reference = setTextRange( + reference = updateNode( isPropertyAccessExpression(reference) ? createPropertyAccess( reference.expression, @@ -3249,8 +3249,7 @@ namespace ts { // const emittedExpression = skipPartiallyEmittedExpressions(expression); if (isLeftHandSideExpression(emittedExpression) - && (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression).arguments) - && emittedExpression.kind !== SyntaxKind.NumericLiteral) { + && (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression).arguments)) { return expression; } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index c6f7eba1dbe..ddb24ae1313 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -151,8 +151,8 @@ namespace ts { ? createAsyncDelegatorHelper(context, expression, expression) : createArrayLiteral( expression - ? [createLiteral("yield"), expression] - : [createLiteral("yield")] + ? [createLiteral("yield"), expression] + : [createLiteral("yield")] ) ); } @@ -516,9 +516,9 @@ namespace ts { enclosingFunctionFlags & FunctionFlags.Generator ? createArrayLiteral([ createLiteral("await"), - createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, []) + createCall(createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []) ]) - : createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, []) + : createCall(createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []) ); hoistVariableDeclaration(errorRecord); @@ -826,7 +826,7 @@ namespace ts { createToken(SyntaxKind.AsteriskToken), node.name && getGeneratedNameForNode(node.name), /*typeParameters*/ undefined, - /*parameters*/ [], + /*parameters*/[], /*type*/ undefined, updateBlock( node.body, @@ -952,6 +952,31 @@ namespace ts { const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration); return propagateNull(finishNullableCallExpression, node, visitNode(target, visitor, isExpression), visitNode(thisArg, visitor, isExpression)); } + else if (isPropertyAccessOrElementAccess(node.expression) && node.expression.flags & NodeFlags.PropagateNull) { + // x?.y() -> x == null ? void 0 : x.y(); + const expressions: Expression[] = []; + const { baseValue, reference } = createPropertyReference(node.expression, hoistVariableDeclaration, expressions, /*captureIdentifiers*/ false, /*captureArgumentExpressions*/ true); + expressions.push(setOriginalNode( + setTextRange( + createConditional( + createEquality( + visitNode(baseValue, visitor, isExpression), + createNull() + ), + createVoidZero(), + updateCall( + node, + visitNode(reference, visitor, isExpression), + /*typeArguments*/ undefined, + visitNodes(node.arguments, visitor, isExpression) + ) + ), + node + ), + node + )); + return setTextRange(inlineExpressions(expressions), node); + } return visitEachChild(node, visitor, context); } @@ -1259,7 +1284,7 @@ namespace ts { if (context.getCompilerOptions().target >= ScriptTarget.ES2015) { return createCall(createPropertyAccess(createIdentifier("Object"), "assign"), /*typeArguments*/ undefined, - attributesSegments); + attributesSegments); } context.requestEmitHelper(assignHelper); return createCall( diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 052433f4668..388ba321081 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2888,16 +2888,22 @@ NonPrimitive = 1 << 24, // intrinsic object type /* @internal */ JsxAttributes = 1 << 25, // Jsx attributes type + /* @internal */ + Nil = 1 << 26, // The null propagating type /* @internal */ - Nullable = Undefined | Null, + NilPropagatingNullable = Undefined | Null, + /* @internal */ + UndefinedLike = Undefined | Nil, + /* @internal */ + Nullable = Undefined | Null | Nil, Literal = StringLiteral | NumberLiteral | BooleanLiteral | EnumLiteral, StringOrNumberLiteral = StringLiteral | NumberLiteral, /* @internal */ - DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null, + DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null | Nil, PossiblyFalsy = DefinitelyFalsy | String | Number | Boolean, /* @internal */ - Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive, + Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Nil | Never | NonPrimitive, /* @internal */ Primitive = String | Number | Boolean | Enum | ESSymbol | Void | Undefined | Null | Literal, StringLike = String | StringLiteral | Index, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f9f537b30e8..0648c917c70 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3547,6 +3547,12 @@ namespace ts { return node.symbol && getDeclarationOfKind(node.symbol, kind) === node; } + export function isMemberExpressionOfCall(node: Node): node is PropertyAccessExpression | ElementAccessExpression { + return isPropertyAccessExpression(node) + && node.parent.kind === SyntaxKind.CallExpression + && (node.parent).expression === node; + } + // Node tests // // All node tests in the following list should *not* reference parent pointers so that diff --git a/tests/baselines/reference/castExpressionParentheses.js b/tests/baselines/reference/castExpressionParentheses.js index 94d5daafb0a..0dd49259a5c 100644 --- a/tests/baselines/reference/castExpressionParentheses.js +++ b/tests/baselines/reference/castExpressionParentheses.js @@ -75,11 +75,11 @@ a[0]; a.b["0"]; a().x; // should keep the parentheses in emit -(1).foo; -(1.).foo; -(1.0).foo; -(12e+34).foo; -(0xff).foo; +1..foo; +1..foo; +1.0.foo; +12e+34.foo; +0xff.foo; (1.0); (new A).foo; (typeof A).x; diff --git a/tests/baselines/reference/destructuringInVariableDeclarations1.js b/tests/baselines/reference/destructuringInVariableDeclarations1.js index a7645ceabe9..0cad8e5b990 100644 --- a/tests/baselines/reference/destructuringInVariableDeclarations1.js +++ b/tests/baselines/reference/destructuringInVariableDeclarations1.js @@ -8,7 +8,7 @@ export let { toString } = 1; //// [destructuringInVariableDeclarations1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.toString = (1).toString; +exports.toString = 1..toString; { let { toFixed } = 1; } diff --git a/tests/baselines/reference/destructuringInVariableDeclarations3.js b/tests/baselines/reference/destructuringInVariableDeclarations3.js index 2522a704e18..18708c92a7d 100644 --- a/tests/baselines/reference/destructuringInVariableDeclarations3.js +++ b/tests/baselines/reference/destructuringInVariableDeclarations3.js @@ -9,7 +9,7 @@ export let { toString } = 1; define(["require", "exports"], function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - exports.toString = (1).toString; + exports.toString = 1..toString; { let { toFixed } = 1; } diff --git a/tests/baselines/reference/destructuringInVariableDeclarations5.js b/tests/baselines/reference/destructuringInVariableDeclarations5.js index 20a094a0375..5aa76cc3a92 100644 --- a/tests/baselines/reference/destructuringInVariableDeclarations5.js +++ b/tests/baselines/reference/destructuringInVariableDeclarations5.js @@ -17,7 +17,7 @@ export let { toString } = 1; })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - exports.toString = (1).toString; + exports.toString = 1..toString; { let { toFixed } = 1; } diff --git a/tests/baselines/reference/destructuringInVariableDeclarations7.js b/tests/baselines/reference/destructuringInVariableDeclarations7.js index e7e4f803b77..82f28b09672 100644 --- a/tests/baselines/reference/destructuringInVariableDeclarations7.js +++ b/tests/baselines/reference/destructuringInVariableDeclarations7.js @@ -13,7 +13,7 @@ System.register([], function (exports_1, context_1) { return { setters: [], execute: function () { - exports_1("toString", toString = (1).toString); + exports_1("toString", toString = 1..toString); { let { toFixed } = 1; } diff --git a/tests/baselines/reference/destructuringInVariableDeclarations8.js b/tests/baselines/reference/destructuringInVariableDeclarations8.js index 12340433bf4..bf4be279e78 100644 --- a/tests/baselines/reference/destructuringInVariableDeclarations8.js +++ b/tests/baselines/reference/destructuringInVariableDeclarations8.js @@ -14,7 +14,7 @@ System.register([], function (exports_1, context_1) { return { setters: [], execute: function () { - toString = (1).toString; + toString = 1..toString; { let { toFixed } = 1; } diff --git a/tests/baselines/reference/destructuringTypeAssertionsES5_5.js b/tests/baselines/reference/destructuringTypeAssertionsES5_5.js index a51ac02af77..dddfaee8527 100644 --- a/tests/baselines/reference/destructuringTypeAssertionsES5_5.js +++ b/tests/baselines/reference/destructuringTypeAssertionsES5_5.js @@ -2,4 +2,4 @@ var { x } = 0; //// [destructuringTypeAssertionsES5_5.js] -var x = (0).x; +var x = 0..x; diff --git a/tests/baselines/reference/destructuringWithNumberLiteral.js b/tests/baselines/reference/destructuringWithNumberLiteral.js index 8804b850cc3..e8a5ee7d45e 100644 --- a/tests/baselines/reference/destructuringWithNumberLiteral.js +++ b/tests/baselines/reference/destructuringWithNumberLiteral.js @@ -2,4 +2,4 @@ var { toExponential } = 0; //// [destructuringWithNumberLiteral.js] -var toExponential = (0).toExponential; +var toExponential = 0..toExponential; diff --git a/tests/baselines/reference/emitter.safeNavigation.es2015.js b/tests/baselines/reference/emitter.safeNavigation.es2015.js index dec1730113f..4a88630c5da 100644 --- a/tests/baselines/reference/emitter.safeNavigation.es2015.js +++ b/tests/baselines/reference/emitter.safeNavigation.es2015.js @@ -354,13 +354,13 @@ var _a, _b, _c, _d; //// [mixedOk.js] (_a = x == null ? void 0 : x.y) == null ? void 0 : _a["z"]; (_b = x == null ? void 0 : x["y"]) == null ? void 0 : _b.z; -(x == null ? void 0 : x.y)(); +x == null ? void 0 : x.y(); (_c = x == null ? void 0 : x.y) == null ? void 0 : _c.call(x); -(o == null ? void 0 : o.y)(); +o == null ? void 0 : o.y(); (_d = o == null ? void 0 : o.y) == null ? void 0 : _d.call(o); -(x == null ? void 0 : x["z"])(); +x == null ? void 0 : x["z"](); (_e = x == null ? void 0 : x["z"]) == null ? void 0 : _e.call(x); -(o == null ? void 0 : o["y"])(); +o == null ? void 0 : o["y"](); (_f = o == null ? void 0 : o["y"]) == null ? void 0 : _f.call(o); var _a, _b, _c, _d, _e, _f; //// [mutationOk.js] @@ -661,18 +661,18 @@ x == null ? void 0 : x.y; [, x == null ? void 0 : x.y]; [...x == null ? void 0 : x.y]; // literals -((_a = 1) == null ? void 0 : _a.toString)(); // no need for `..` -((_b = 1.) == null ? void 0 : _b.toString)(); -((_c = .0) == null ? void 0 : _c.toString)(); -((_d = 4e3) == null ? void 0 : _d.toString)(); -((_e = 1.e3) == null ? void 0 : _e.toString)(); -((_f = "") == null ? void 0 : _f.toString)(); -((_g = '') == null ? void 0 : _g.toString)(); -((_h = ``) == null ? void 0 : _h.toString)(); -((_j = /./) == null ? void 0 : _j.toString)(); -((_k = /./g) == null ? void 0 : _k.toString)(); -((_l = true) == null ? void 0 : _l.toString)(); -((_m = false) == null ? void 0 : _m.toString)(); +1 == null ? void 0 : 1..toString(); // no need for `..` +1. == null ? void 0 : 1..toString(); +.0 == null ? void 0 : .0.toString(); +4e3 == null ? void 0 : 4e3.toString(); +1.e3 == null ? void 0 : 1.e3.toString(); +"" == null ? void 0 : "".toString(); +'' == null ? void 0 : ''.toString(); +`` == null ? void 0 : ``.toString(); +_a = /./, _a == null ? void 0 : (_a == null ? void 0 : _a.toString)(); +_b = /./g, _b == null ? void 0 : (_b == null ? void 0 : _b.toString)(); +true == null ? void 0 : true.toString(); +false == null ? void 0 : false.toString(); // templates `${x == null ? void 0 : x.y}`; // variables @@ -709,7 +709,7 @@ var E; (function (E) { E[E["a"] = x == null ? void 0 : x.y] = "a"; })(E || (E = {})); -var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; +var _a, _b; //// [exportsOk.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/emitter.safeNavigation.es3.js b/tests/baselines/reference/emitter.safeNavigation.es3.js index ef082cf6876..d8a0b4f65ef 100644 --- a/tests/baselines/reference/emitter.safeNavigation.es3.js +++ b/tests/baselines/reference/emitter.safeNavigation.es3.js @@ -353,13 +353,13 @@ var _a, _b, _c, _d; //// [mixedOk.js] (_a = x == null ? void 0 : x.y) == null ? void 0 : _a["z"]; (_b = x == null ? void 0 : x["y"]) == null ? void 0 : _b.z; -(x == null ? void 0 : x.y)(); +x == null ? void 0 : x.y(); (_c = x == null ? void 0 : x.y) == null ? void 0 : _c.call(x); -(o == null ? void 0 : o.y)(); +o == null ? void 0 : o.y(); (_d = o == null ? void 0 : o.y) == null ? void 0 : _d.call(o); -(x == null ? void 0 : x["z"])(); +x == null ? void 0 : x["z"](); (_e = x == null ? void 0 : x["z"]) == null ? void 0 : _e.call(x); -(o == null ? void 0 : o["y"])(); +o == null ? void 0 : o["y"](); (_f = o == null ? void 0 : o["y"]) == null ? void 0 : _f.call(o); var _a, _b, _c, _d, _e, _f; //// [mutationOk.js] @@ -815,27 +815,27 @@ x == null ? void 0 : x.y; [, x == null ? void 0 : x.y]; (x == null ? void 0 : x.y).slice(); // literals -((_e = 1) == null ? void 0 : _e.toString)(); // no need for `..` -((_f = 1.) == null ? void 0 : _f.toString)(); -((_g = .0) == null ? void 0 : _g.toString)(); -((_h = 4e3) == null ? void 0 : _h.toString)(); -((_j = 1.e3) == null ? void 0 : _j.toString)(); -((_k = "") == null ? void 0 : _k.toString)(); -((_l = '') == null ? void 0 : _l.toString)(); -((_m = "") == null ? void 0 : _m.toString)(); -((_o = /./) == null ? void 0 : _o.toString)(); -((_p = /./g) == null ? void 0 : _p.toString)(); -((_q = true) == null ? void 0 : _q.toString)(); -((_r = false) == null ? void 0 : _r.toString)(); +1 == null ? void 0 : 1..toString(); // no need for `..` +1. == null ? void 0 : 1..toString(); +.0 == null ? void 0 : .0.toString(); +4e3 == null ? void 0 : 4e3.toString(); +1.e3 == null ? void 0 : 1.e3.toString(); +"" == null ? void 0 : "".toString(); +'' == null ? void 0 : ''.toString(); +"" == null ? void 0 : "".toString(); +_e = /./, _e == null ? void 0 : (_e == null ? void 0 : _e.toString)(); +_f = /./g, _f == null ? void 0 : (_f == null ? void 0 : _f.toString)(); +true == null ? void 0 : true.toString(); +false == null ? void 0 : false.toString(); // templates "" + (x == null ? void 0 : x.y); // variables var v = x == null ? void 0 : x.y; var v = (x == null ? void 0 : x.y)[0]; -var _s = [1][0], v = _s === void 0 ? x == null ? void 0 : x.y : _s; +var _g = [1][0], v = _g === void 0 ? x == null ? void 0 : x.y : _g; var v = (x == null ? void 0 : x.y).v; -var _t = { v: 1 }.v, v = _t === void 0 ? x == null ? void 0 : x.y : _t; -var _u = x == null ? void 0 : x.y, v = null[_u]; +var _h = { v: 1 }.v, v = _h === void 0 ? x == null ? void 0 : x.y : _h; +var _j = x == null ? void 0 : x.y, v = null[_j]; // if/else if if (x == null ? void 0 : x.y) { } if (1) { } @@ -853,14 +853,14 @@ while (x == null ? void 0 : x.y) { } for (x == null ? void 0 : x.y; x == null ? void 0 : x.y; x == null ? void 0 : x.y) ; // for..in -for (var _v in {}) { - x == null ? _v : x.y = _v; +for (var _k in {}) { + x == null ? _k : x.y = _k; ; } // for..of -for (var _i = 0, _w = []; _i < _w.length; _i++) { - var _x = _w[_i]; - x == null ? _x : x.y = _x; +for (var _i = 0, _l = []; _i < _l.length; _i++) { + var _m = _l[_i]; + x == null ? _m : x.y = _m; ; } // enums @@ -868,7 +868,7 @@ var E; (function (E) { E[E["a"] = x == null ? void 0 : x.y] = "a"; })(E || (E = {})); -var _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _v, _x; +var _e, _f, _k, _m; var _a, _b, _c, _d; //// [exportsOk.js] "use strict"; diff --git a/tests/baselines/reference/emitter.safeNavigation.es5.js b/tests/baselines/reference/emitter.safeNavigation.es5.js index e2f9199f63f..967fd8e3f98 100644 --- a/tests/baselines/reference/emitter.safeNavigation.es5.js +++ b/tests/baselines/reference/emitter.safeNavigation.es5.js @@ -353,13 +353,13 @@ var _a, _b, _c, _d; //// [mixedOk.js] (_a = x == null ? void 0 : x.y) == null ? void 0 : _a["z"]; (_b = x == null ? void 0 : x["y"]) == null ? void 0 : _b.z; -(x == null ? void 0 : x.y)(); +x == null ? void 0 : x.y(); (_c = x == null ? void 0 : x.y) == null ? void 0 : _c.call(x); -(o == null ? void 0 : o.y)(); +o == null ? void 0 : o.y(); (_d = o == null ? void 0 : o.y) == null ? void 0 : _d.call(o); -(x == null ? void 0 : x["z"])(); +x == null ? void 0 : x["z"](); (_e = x == null ? void 0 : x["z"]) == null ? void 0 : _e.call(x); -(o == null ? void 0 : o["y"])(); +o == null ? void 0 : o["y"](); (_f = o == null ? void 0 : o["y"]) == null ? void 0 : _f.call(o); var _a, _b, _c, _d, _e, _f; //// [mutationOk.js] @@ -815,27 +815,27 @@ x == null ? void 0 : x.y; [, x == null ? void 0 : x.y]; (x == null ? void 0 : x.y).slice(); // literals -((_e = 1) == null ? void 0 : _e.toString)(); // no need for `..` -((_f = 1.) == null ? void 0 : _f.toString)(); -((_g = .0) == null ? void 0 : _g.toString)(); -((_h = 4e3) == null ? void 0 : _h.toString)(); -((_j = 1.e3) == null ? void 0 : _j.toString)(); -((_k = "") == null ? void 0 : _k.toString)(); -((_l = '') == null ? void 0 : _l.toString)(); -((_m = "") == null ? void 0 : _m.toString)(); -((_o = /./) == null ? void 0 : _o.toString)(); -((_p = /./g) == null ? void 0 : _p.toString)(); -((_q = true) == null ? void 0 : _q.toString)(); -((_r = false) == null ? void 0 : _r.toString)(); +1 == null ? void 0 : 1..toString(); // no need for `..` +1. == null ? void 0 : 1..toString(); +.0 == null ? void 0 : .0.toString(); +4e3 == null ? void 0 : 4e3.toString(); +1.e3 == null ? void 0 : 1.e3.toString(); +"" == null ? void 0 : "".toString(); +'' == null ? void 0 : ''.toString(); +"" == null ? void 0 : "".toString(); +_e = /./, _e == null ? void 0 : (_e == null ? void 0 : _e.toString)(); +_f = /./g, _f == null ? void 0 : (_f == null ? void 0 : _f.toString)(); +true == null ? void 0 : true.toString(); +false == null ? void 0 : false.toString(); // templates "" + (x == null ? void 0 : x.y); // variables var v = x == null ? void 0 : x.y; var v = (x == null ? void 0 : x.y)[0]; -var _s = [1][0], v = _s === void 0 ? x == null ? void 0 : x.y : _s; +var _g = [1][0], v = _g === void 0 ? x == null ? void 0 : x.y : _g; var v = (x == null ? void 0 : x.y).v; -var _t = { v: 1 }.v, v = _t === void 0 ? x == null ? void 0 : x.y : _t; -var _u = x == null ? void 0 : x.y, v = null[_u]; +var _h = { v: 1 }.v, v = _h === void 0 ? x == null ? void 0 : x.y : _h; +var _j = x == null ? void 0 : x.y, v = null[_j]; // if/else if if (x == null ? void 0 : x.y) { } if (1) { } @@ -856,9 +856,9 @@ for (x == null ? void 0 : x.y; x == null ? void 0 : x.y; x == null ? void 0 : x. for ({ set value(_a) { x == null ? _a : x.y = _a; } }.value in {}) ; // for..of -for (var _i = 0, _v = []; _i < _v.length; _i++) { - var _w = _v[_i]; - x == null ? _w : x.y = _w; +for (var _i = 0, _k = []; _i < _k.length; _i++) { + var _l = _k[_i]; + x == null ? _l : x.y = _l; ; } // enums @@ -866,7 +866,7 @@ var E; (function (E) { E[E["a"] = x == null ? void 0 : x.y] = "a"; })(E || (E = {})); -var _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _w; +var _e, _f, _l; var _a, _b, _c, _d; //// [exportsOk.js] "use strict";