From c0ded048e0e83709704c808fadbf5c14a29b8153 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 22 Jul 2024 13:43:53 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#58771=20(Allow=20re?= =?UTF-8?q?ferences=20to=20the=20global=20Symb...)=20into=20release-5.5=20?= =?UTF-8?q?(#59378)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Wesley Wigham --- src/compiler/checker.ts | 15 +++ src/compiler/emitter.ts | 1 + src/compiler/expressionToTypeNode.ts | 2 +- src/compiler/transformers/declarations.ts | 24 ++--- src/compiler/types.ts | 2 + .../declarationComputedPropertyNames.d.ts | 94 +++++++++++++++---- .../declarationComputedPropertyNames.ts | 14 +++ 7 files changed, 120 insertions(+), 32 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e631e75d9cd9d..c5cd771cfff19 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1511,6 +1511,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { Debug.assert(isExpressionNode(node)); return getSymbolAtLocation(node) === undefinedSymbol; }, + isDefinitelyReferenceToGlobalSymbolObject, }); var evaluate = createEvaluator({ evaluateElementAccessExpression, @@ -2351,6 +2352,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return checker; + function isDefinitelyReferenceToGlobalSymbolObject(node: Node): boolean { + if (!isPropertyAccessExpression(node)) return false; + if (!isIdentifier(node.name)) return false; + if (!isPropertyAccessExpression(node.expression) && !isIdentifier(node.expression)) return false; + if (isIdentifier(node.expression)) { + // Exactly `Symbol.something` and `Symbol` either does not resolve or definitely resolves to the global Symbol + return idText(node.expression) === "Symbol" && getResolvedSymbol(node.expression) === (getGlobalSymbol("Symbol" as __String, SymbolFlags.Value | SymbolFlags.ExportValue, /*diagnostic*/ undefined) || unknownSymbol); + } + if (!isIdentifier(node.expression.expression)) return false; + // Exactly `globalThis.Symbol.something` and `globalThis` resolves to the global `globalThis` + return idText(node.expression.name) === "Symbol" && idText(node.expression.expression) === "globalThis" && getResolvedSymbol(node.expression.expression) === globalThisSymbol; + } + function getCachedType(key: string | undefined) { return key ? cachedTypes.get(key) : undefined; } @@ -49763,6 +49777,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, tracker); }, isImportRequiredByAugmentation, + isDefinitelyReferenceToGlobalSymbolObject, }; function isImportRequiredByAugmentation(node: ImportDeclaration) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index f9a2afdc08c81..e5e035c93becc 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1150,6 +1150,7 @@ export const notImplementedResolver: EmitResolver = { isBindingCapturedByNode: notImplemented, getDeclarationStatementsForSourceFile: notImplemented, isImportRequiredByAugmentation: notImplemented, + isDefinitelyReferenceToGlobalSymbolObject: notImplemented, }; const enum PipelinePhase { diff --git a/src/compiler/expressionToTypeNode.ts b/src/compiler/expressionToTypeNode.ts index e1a9c0548a77e..48f8434137bc9 100644 --- a/src/compiler/expressionToTypeNode.ts +++ b/src/compiler/expressionToTypeNode.ts @@ -350,7 +350,7 @@ export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolve } else if (prop.name.kind === SyntaxKind.ComputedPropertyName) { const expression = prop.name.expression; - if (!isPrimitiveLiteralValue(expression, /*includeBigInt*/ false)) { + if (!isPrimitiveLiteralValue(expression, /*includeBigInt*/ false) && !resolver.isDefinitelyReferenceToGlobalSymbolObject(expression)) { context.tracker.reportInferenceFallback(prop.name); result = false; } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 705da712613fa..ffc80652d3632 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1001,17 +1001,19 @@ export function transformDeclarations(context: TransformationContext) { if (isolatedDeclarations) { // Classes and object literals usually elide properties with computed names that are not of a literal type // In isolated declarations TSC needs to error on these as we don't know the type in a DTE. - if (isClassDeclaration(input.parent) || isObjectLiteralExpression(input.parent)) { - context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations)); - return; - } - else if ( - // Type declarations just need to double-check that the input computed name is an entity name expression - (isInterfaceDeclaration(input.parent) || isTypeLiteralNode(input.parent)) - && !isEntityNameExpression(input.name.expression) - ) { - context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations)); - return; + if (!resolver.isDefinitelyReferenceToGlobalSymbolObject(input.name.expression)) { + if (isClassDeclaration(input.parent) || isObjectLiteralExpression(input.parent)) { + context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations)); + return; + } + else if ( + // Type declarations just need to double-check that the input computed name is an entity name expression + (isInterfaceDeclaration(input.parent) || isTypeLiteralNode(input.parent)) + && !isEntityNameExpression(input.name.expression) + ) { + context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations)); + return; + } } } else if (!resolver.isLateBound(getParseTreeNode(input) as Declaration) || !isEntityNameExpression(input.name.expression)) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bdf793a65486f..d422f3ab0c6b2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5744,6 +5744,7 @@ export interface EmitResolver { isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean; getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, tracker: SymbolTracker): Statement[] | undefined; isImportRequiredByAugmentation(decl: ImportDeclaration): boolean; + isDefinitelyReferenceToGlobalSymbolObject(node: Node): boolean; } // dprint-ignore @@ -10270,4 +10271,5 @@ export interface SyntacticTypeNodeBuilderResolver { getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations; isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node, shouldComputeAliasToMakeVisible?: boolean): SymbolVisibilityResult; requiresAddingImplicitUndefined(parameter: ParameterDeclaration | JSDocParameterTag): boolean; + isDefinitelyReferenceToGlobalSymbolObject(node: Node): boolean; } diff --git a/tests/baselines/reference/transpile/declarationComputedPropertyNames.d.ts b/tests/baselines/reference/transpile/declarationComputedPropertyNames.d.ts index 4ede31ab9e960..16e79cea6cedc 100644 --- a/tests/baselines/reference/transpile/declarationComputedPropertyNames.d.ts +++ b/tests/baselines/reference/transpile/declarationComputedPropertyNames.d.ts @@ -3,11 +3,16 @@ export namespace presentNs { export const a = Symbol(); } +const aliasing = Symbol; + export type A = { [missing]: number, [ns.missing]: number, [presentNs.a]: number, [Symbol.iterator]: number, + [globalThis.Symbol.toStringTag]: number, + [(globalThis.Symbol).unscopables]: number, + [aliasing.isConcatSpreadable]: number, [1]: number, ["2"]: number, [(missing2)]: number, @@ -19,6 +24,9 @@ export interface B { [ns.missing]: number, [presentNs.a]: number, [Symbol.iterator]: number, + [globalThis.Symbol.toStringTag]: number, + [(globalThis.Symbol).unscopables]: number, + [aliasing.isConcatSpreadable]: number, [1]: number, ["2"]: number, [(missing2)]: number, @@ -30,6 +38,9 @@ export class C { [ns.missing]: number = 1; [presentNs.a]: number = 1; [Symbol.iterator]: number = 1; + [globalThis.Symbol.toStringTag]: number = 1; + [(globalThis.Symbol).unscopables]: number = 1; + [aliasing.isConcatSpreadable]: number = 1; [1]: number = 1; ["2"]: number = 1; [(missing2)]: number = 1; @@ -41,6 +52,9 @@ export const D = { [ns.missing]: 1, [presentNs.a]: 1, [Symbol.iterator]: 1, + [globalThis.Symbol.toStringTag]: 1, + [(globalThis.Symbol).unscopables]: 1, + [aliasing.isConcatSpreadable]: 1, [1]: 1, ["2"]: 1, [(missing2)]: 1, @@ -50,11 +64,14 @@ export const D = { export declare namespace presentNs { const a: unique symbol; } +declare const aliasing: SymbolConstructor; export type A = { [missing]: number; [ns.missing]: number; [presentNs.a]: number; [Symbol.iterator]: number; + [globalThis.Symbol.toStringTag]: number; + [aliasing.isConcatSpreadable]: number; [1]: number; ["2"]: number; }; @@ -63,10 +80,14 @@ export interface B { [ns.missing]: number; [presentNs.a]: number; [Symbol.iterator]: number; + [globalThis.Symbol.toStringTag]: number; + [aliasing.isConcatSpreadable]: number; [1]: number; ["2"]: number; } export declare class C { + [Symbol.iterator]: number; + [globalThis.Symbol.toStringTag]: number; [1]: number; ["2"]: number; } @@ -74,32 +95,39 @@ export declare const D: { [x: string]: number; [x: number]: number; [presentNs.a]: number; + [aliasing.toStringTag]: number; 1: number; "2": number; }; +export {}; //// [Diagnostics reported] declarationComputedPropertyNames.ts(2,18): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. -declarationComputedPropertyNames.ts(12,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. +declarationComputedPropertyNames.ts(5,7): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. declarationComputedPropertyNames.ts(13,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. -declarationComputedPropertyNames.ts(23,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. -declarationComputedPropertyNames.ts(24,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. -declarationComputedPropertyNames.ts(28,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -declarationComputedPropertyNames.ts(29,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -declarationComputedPropertyNames.ts(30,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -declarationComputedPropertyNames.ts(31,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -declarationComputedPropertyNames.ts(34,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -declarationComputedPropertyNames.ts(35,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -declarationComputedPropertyNames.ts(39,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -declarationComputedPropertyNames.ts(40,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(17,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. +declarationComputedPropertyNames.ts(18,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. +declarationComputedPropertyNames.ts(27,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. +declarationComputedPropertyNames.ts(31,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. +declarationComputedPropertyNames.ts(32,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. +declarationComputedPropertyNames.ts(36,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(37,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(38,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. declarationComputedPropertyNames.ts(41,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. declarationComputedPropertyNames.ts(42,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. declarationComputedPropertyNames.ts(45,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. declarationComputedPropertyNames.ts(46,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(50,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(51,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(52,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(55,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(56,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(59,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +declarationComputedPropertyNames.ts(60,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -==== declarationComputedPropertyNames.ts (17 errors) ==== +==== declarationComputedPropertyNames.ts (22 errors) ==== export namespace presentNs { export const a = Symbol(); ~ @@ -107,11 +135,21 @@ declarationComputedPropertyNames.ts(46,5): error TS9038: Computed property names !!! related TS9027 declarationComputedPropertyNames.ts:2:18: Add a type annotation to the variable a. } + const aliasing = Symbol; + ~~~~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 declarationComputedPropertyNames.ts:5:7: Add a type annotation to the variable aliasing. + export type A = { [missing]: number, [ns.missing]: number, [presentNs.a]: number, [Symbol.iterator]: number, + [globalThis.Symbol.toStringTag]: number, + [(globalThis.Symbol).unscopables]: number, + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. + [aliasing.isConcatSpreadable]: number, [1]: number, ["2"]: number, [(missing2)]: number, @@ -127,6 +165,11 @@ declarationComputedPropertyNames.ts(46,5): error TS9038: Computed property names [ns.missing]: number, [presentNs.a]: number, [Symbol.iterator]: number, + [globalThis.Symbol.toStringTag]: number, + [(globalThis.Symbol).unscopables]: number, + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations. + [aliasing.isConcatSpreadable]: number, [1]: number, ["2"]: number, [(missing2)]: number, @@ -148,7 +191,12 @@ declarationComputedPropertyNames.ts(46,5): error TS9038: Computed property names ~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. [Symbol.iterator]: number = 1; - ~~~~~~~~~~~~~~~~~ + [globalThis.Symbol.toStringTag]: number = 1; + [(globalThis.Symbol).unscopables]: number = 1; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. + [aliasing.isConcatSpreadable]: number = 1; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. [1]: number = 1; ["2"]: number = 1; @@ -164,28 +212,34 @@ declarationComputedPropertyNames.ts(46,5): error TS9038: Computed property names [missing]: 1, ~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -!!! related TS9027 declarationComputedPropertyNames.ts:38:14: Add a type annotation to the variable D. +!!! related TS9027 declarationComputedPropertyNames.ts:49:14: Add a type annotation to the variable D. [ns.missing]: 1, ~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -!!! related TS9027 declarationComputedPropertyNames.ts:38:14: Add a type annotation to the variable D. +!!! related TS9027 declarationComputedPropertyNames.ts:49:14: Add a type annotation to the variable D. [presentNs.a]: 1, ~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -!!! related TS9027 declarationComputedPropertyNames.ts:38:14: Add a type annotation to the variable D. +!!! related TS9027 declarationComputedPropertyNames.ts:49:14: Add a type annotation to the variable D. [Symbol.iterator]: 1, - ~~~~~~~~~~~~~~~~~ + [globalThis.Symbol.toStringTag]: 1, + [(globalThis.Symbol).unscopables]: 1, + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. +!!! related TS9027 declarationComputedPropertyNames.ts:49:14: Add a type annotation to the variable D. + [aliasing.isConcatSpreadable]: 1, + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -!!! related TS9027 declarationComputedPropertyNames.ts:38:14: Add a type annotation to the variable D. +!!! related TS9027 declarationComputedPropertyNames.ts:49:14: Add a type annotation to the variable D. [1]: 1, ["2"]: 1, [(missing2)]: 1, ~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -!!! related TS9027 declarationComputedPropertyNames.ts:38:14: Add a type annotation to the variable D. +!!! related TS9027 declarationComputedPropertyNames.ts:49:14: Add a type annotation to the variable D. [Math.random() > 0.5 ? "f1" : "f2"]: 1, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations. -!!! related TS9027 declarationComputedPropertyNames.ts:38:14: Add a type annotation to the variable D. +!!! related TS9027 declarationComputedPropertyNames.ts:49:14: Add a type annotation to the variable D. }; diff --git a/tests/cases/transpile/declarationComputedPropertyNames.ts b/tests/cases/transpile/declarationComputedPropertyNames.ts index 11ca207a31bd6..3fa9aa041a189 100644 --- a/tests/cases/transpile/declarationComputedPropertyNames.ts +++ b/tests/cases/transpile/declarationComputedPropertyNames.ts @@ -6,11 +6,16 @@ export namespace presentNs { export const a = Symbol(); } +const aliasing = Symbol; + export type A = { [missing]: number, [ns.missing]: number, [presentNs.a]: number, [Symbol.iterator]: number, + [globalThis.Symbol.toStringTag]: number, + [(globalThis.Symbol).unscopables]: number, + [aliasing.isConcatSpreadable]: number, [1]: number, ["2"]: number, [(missing2)]: number, @@ -22,6 +27,9 @@ export interface B { [ns.missing]: number, [presentNs.a]: number, [Symbol.iterator]: number, + [globalThis.Symbol.toStringTag]: number, + [(globalThis.Symbol).unscopables]: number, + [aliasing.isConcatSpreadable]: number, [1]: number, ["2"]: number, [(missing2)]: number, @@ -33,6 +41,9 @@ export class C { [ns.missing]: number = 1; [presentNs.a]: number = 1; [Symbol.iterator]: number = 1; + [globalThis.Symbol.toStringTag]: number = 1; + [(globalThis.Symbol).unscopables]: number = 1; + [aliasing.isConcatSpreadable]: number = 1; [1]: number = 1; ["2"]: number = 1; [(missing2)]: number = 1; @@ -44,6 +55,9 @@ export const D = { [ns.missing]: 1, [presentNs.a]: 1, [Symbol.iterator]: 1, + [globalThis.Symbol.toStringTag]: 1, + [(globalThis.Symbol).unscopables]: 1, + [aliasing.isConcatSpreadable]: 1, [1]: 1, ["2"]: 1, [(missing2)]: 1,