From 8b4d19151b10b349577d6cc13c152f77a677aa1d Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 30 Jan 2026 21:37:36 -0800 Subject: [PATCH 1/3] Remove ES5 references --- src/compiler/checker.ts | 2 +- src/compiler/emitter.ts | 2 +- src/compiler/transformers/ts.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 04abe7d1b45ce..50a9f6bfe7e31 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -46772,7 +46772,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function checkClassNameCollisionWithObject(name: Identifier): void { if ( - languageVersion >= ScriptTarget.ES5 && name.escapedText === "Object" + name.escapedText === "Object" && host.getEmitModuleFormatOfFile(getSourceFileOfNode(name)) < ModuleKind.ES2015 ) { error(name, Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_and_above_with_module_0, ModuleKind[moduleKind]); // https://github.com/Microsoft/TypeScript/issues/17494 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 9ba1afcae27ea..5a4858b572dc1 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2625,7 +2625,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri } const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; - const allowTrailingComma = currentSourceFile && currentSourceFile.languageVersion >= ScriptTarget.ES5 && !isJsonSourceFile(currentSourceFile) ? ListFormat.AllowTrailingComma : ListFormat.None; + const allowTrailingComma = currentSourceFile && !isJsonSourceFile(currentSourceFile) ? ListFormat.AllowTrailingComma : ListFormat.None; emitList(node, node.properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); if (indentedFlag) { diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 2219f2b1211a1..5a927a0496ce8 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -879,7 +879,7 @@ export function transformTypeScript(context: TransformationContext): Transformer function visitClassDeclaration(node: ClassDeclaration): VisitResult { const facts = getClassFacts(node); - const promoteToIIFE = languageVersion <= ScriptTarget.ES5 && + const promoteToIIFE = languageVersion < ScriptTarget.ES2015 && !!(facts & ClassFacts.MayNeedImmediatelyInvokedFunctionExpression); if ( From ed75ee1cb8c612588dde6ea69faca664748de150 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 30 Jan 2026 21:52:37 -0800 Subject: [PATCH 2/3] Add test for enum unicode case --- .../reference/enumMemberNameNonIdentifier.js | 40 +++++++++ .../enumMemberNameNonIdentifier.symbols | 50 +++++++++++ .../enumMemberNameNonIdentifier.types | 89 +++++++++++++++++++ .../compiler/enumMemberNameNonIdentifier.ts | 16 ++++ 4 files changed, 195 insertions(+) create mode 100644 tests/baselines/reference/enumMemberNameNonIdentifier.js create mode 100644 tests/baselines/reference/enumMemberNameNonIdentifier.symbols create mode 100644 tests/baselines/reference/enumMemberNameNonIdentifier.types create mode 100644 tests/cases/compiler/enumMemberNameNonIdentifier.ts diff --git a/tests/baselines/reference/enumMemberNameNonIdentifier.js b/tests/baselines/reference/enumMemberNameNonIdentifier.js new file mode 100644 index 0000000000000..d5a9c2266e29a --- /dev/null +++ b/tests/baselines/reference/enumMemberNameNonIdentifier.js @@ -0,0 +1,40 @@ +//// [tests/cases/compiler/enumMemberNameNonIdentifier.ts] //// + +//// [enumMemberNameNonIdentifier.ts] +export const enum E { + regular = 0, + "hyphen-member" = 1, + "123startsWithNumber" = 2, + "has space" = 3, + // Greek Capital Yot (U+037F) - valid identifier in ES2015+ but NOT in ES5 + Ϳ = 4, +} + +export const a = E["hyphen-member"]; +export const b = E["123startsWithNumber"]; +export const c = E["has space"]; +export const d = E.regular; +export const e = E.Ϳ; + + +//// [enumMemberNameNonIdentifier.js] +export const a = 1 /* E["hyphen-member"] */; +export const b = 2 /* E["123startsWithNumber"] */; +export const c = 3 /* E["has space"] */; +export const d = 0 /* E.regular */; +export const e = 4 /* E.Ϳ */; + + +//// [enumMemberNameNonIdentifier.d.ts] +export declare const enum E { + regular = 0, + "hyphen-member" = 1, + "123startsWithNumber" = 2, + "has space" = 3, + Ϳ = 4 +} +export declare const a = E["hyphen-member"]; +export declare const b = E["123startsWithNumber"]; +export declare const c = E["has space"]; +export declare const d = E.regular; +export declare const e = E.Ϳ; diff --git a/tests/baselines/reference/enumMemberNameNonIdentifier.symbols b/tests/baselines/reference/enumMemberNameNonIdentifier.symbols new file mode 100644 index 0000000000000..0c3029032c598 --- /dev/null +++ b/tests/baselines/reference/enumMemberNameNonIdentifier.symbols @@ -0,0 +1,50 @@ +//// [tests/cases/compiler/enumMemberNameNonIdentifier.ts] //// + +=== enumMemberNameNonIdentifier.ts === +export const enum E { +>E : Symbol(E, Decl(enumMemberNameNonIdentifier.ts, 0, 0)) + + regular = 0, +>regular : Symbol(E.regular, Decl(enumMemberNameNonIdentifier.ts, 0, 21)) + + "hyphen-member" = 1, +>"hyphen-member" : Symbol(E["hyphen-member"], Decl(enumMemberNameNonIdentifier.ts, 1, 16)) + + "123startsWithNumber" = 2, +>"123startsWithNumber" : Symbol(E["123startsWithNumber"], Decl(enumMemberNameNonIdentifier.ts, 2, 24)) + + "has space" = 3, +>"has space" : Symbol(E["has space"], Decl(enumMemberNameNonIdentifier.ts, 3, 30)) + + // Greek Capital Yot (U+037F) - valid identifier in ES2015+ but NOT in ES5 + Ϳ = 4, +>Ϳ : Symbol(E.Ϳ, Decl(enumMemberNameNonIdentifier.ts, 4, 20)) +} + +export const a = E["hyphen-member"]; +>a : Symbol(a, Decl(enumMemberNameNonIdentifier.ts, 9, 12)) +>E : Symbol(E, Decl(enumMemberNameNonIdentifier.ts, 0, 0)) +>"hyphen-member" : Symbol(E["hyphen-member"], Decl(enumMemberNameNonIdentifier.ts, 1, 16)) + +export const b = E["123startsWithNumber"]; +>b : Symbol(b, Decl(enumMemberNameNonIdentifier.ts, 10, 12)) +>E : Symbol(E, Decl(enumMemberNameNonIdentifier.ts, 0, 0)) +>"123startsWithNumber" : Symbol(E["123startsWithNumber"], Decl(enumMemberNameNonIdentifier.ts, 2, 24)) + +export const c = E["has space"]; +>c : Symbol(c, Decl(enumMemberNameNonIdentifier.ts, 11, 12)) +>E : Symbol(E, Decl(enumMemberNameNonIdentifier.ts, 0, 0)) +>"has space" : Symbol(E["has space"], Decl(enumMemberNameNonIdentifier.ts, 3, 30)) + +export const d = E.regular; +>d : Symbol(d, Decl(enumMemberNameNonIdentifier.ts, 12, 12)) +>E.regular : Symbol(E.regular, Decl(enumMemberNameNonIdentifier.ts, 0, 21)) +>E : Symbol(E, Decl(enumMemberNameNonIdentifier.ts, 0, 0)) +>regular : Symbol(E.regular, Decl(enumMemberNameNonIdentifier.ts, 0, 21)) + +export const e = E.Ϳ; +>e : Symbol(e, Decl(enumMemberNameNonIdentifier.ts, 13, 12)) +>E.Ϳ : Symbol(E.Ϳ, Decl(enumMemberNameNonIdentifier.ts, 4, 20)) +>E : Symbol(E, Decl(enumMemberNameNonIdentifier.ts, 0, 0)) +>Ϳ : Symbol(E.Ϳ, Decl(enumMemberNameNonIdentifier.ts, 4, 20)) + diff --git a/tests/baselines/reference/enumMemberNameNonIdentifier.types b/tests/baselines/reference/enumMemberNameNonIdentifier.types new file mode 100644 index 0000000000000..71eec1283ba5c --- /dev/null +++ b/tests/baselines/reference/enumMemberNameNonIdentifier.types @@ -0,0 +1,89 @@ +//// [tests/cases/compiler/enumMemberNameNonIdentifier.ts] //// + +=== enumMemberNameNonIdentifier.ts === +export const enum E { +>E : E +> : ^ + + regular = 0, +>regular : E.regular +> : ^^^^^^^^^ +>0 : 0 +> : ^ + + "hyphen-member" = 1, +>"hyphen-member" : (typeof E)["hyphen-member"] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ + + "123startsWithNumber" = 2, +>"123startsWithNumber" : (typeof E)["123startsWithNumber"] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>2 : 2 +> : ^ + + "has space" = 3, +>"has space" : (typeof E)["has space"] +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>3 : 3 +> : ^ + + // Greek Capital Yot (U+037F) - valid identifier in ES2015+ but NOT in ES5 + Ϳ = 4, +>Ϳ : (typeof E)["\u037F"] +> : ^^^^^^^^^^^^^^^^^^^^ +>4 : 4 +> : ^ +} + +export const a = E["hyphen-member"]; +>a : (typeof E)["hyphen-member"] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>E["hyphen-member"] : (typeof E)["hyphen-member"] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>E : typeof E +> : ^^^^^^^^ +>"hyphen-member" : "hyphen-member" +> : ^^^^^^^^^^^^^^^ + +export const b = E["123startsWithNumber"]; +>b : (typeof E)["123startsWithNumber"] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>E["123startsWithNumber"] : (typeof E)["123startsWithNumber"] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>E : typeof E +> : ^^^^^^^^ +>"123startsWithNumber" : "123startsWithNumber" +> : ^^^^^^^^^^^^^^^^^^^^^ + +export const c = E["has space"]; +>c : (typeof E)["has space"] +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>E["has space"] : (typeof E)["has space"] +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>E : typeof E +> : ^^^^^^^^ +>"has space" : "has space" +> : ^^^^^^^^^^^ + +export const d = E.regular; +>d : E.regular +> : ^^^^^^^^^ +>E.regular : E.regular +> : ^^^^^^^^^ +>E : typeof E +> : ^^^^^^^^ +>regular : E.regular +> : ^^^^^^^^^ + +export const e = E.Ϳ; +>e : (typeof E)["\u037F"] +> : ^^^^^^^^^^^^^^^^^^^^ +>E.Ϳ : (typeof E)["\u037F"] +> : ^^^^^^^^^^^^^^^^^^^^ +>E : typeof E +> : ^^^^^^^^ +>Ϳ : (typeof E)["\u037F"] +> : ^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/cases/compiler/enumMemberNameNonIdentifier.ts b/tests/cases/compiler/enumMemberNameNonIdentifier.ts new file mode 100644 index 0000000000000..8e09aa9f8d0ba --- /dev/null +++ b/tests/cases/compiler/enumMemberNameNonIdentifier.ts @@ -0,0 +1,16 @@ +// @declaration: true + +export const enum E { + regular = 0, + "hyphen-member" = 1, + "123startsWithNumber" = 2, + "has space" = 3, + // Greek Capital Yot (U+037F) - valid identifier in ES2015+ but NOT in ES5 + Ϳ = 4, +} + +export const a = E["hyphen-member"]; +export const b = E["123startsWithNumber"]; +export const c = E["has space"]; +export const d = E.regular; +export const e = E.Ϳ; From 2894fcc1aad4cdbae450dc31cfe168a8e9f1ab09 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 30 Jan 2026 21:53:27 -0800 Subject: [PATCH 3/3] Use ESNext for printing enums; no effect on declaration emit due to node reuse --- src/compiler/checker.ts | 2 +- .../reference/enumMemberNameNonIdentifier.types | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 50a9f6bfe7e31..9e27607b6cd78 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6774,7 +6774,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return parentName; } const memberName = symbolName(type.symbol); - if (isIdentifierText(memberName, ScriptTarget.ES5)) { + if (isIdentifierText(memberName, ScriptTarget.ESNext)) { return appendReferenceToType( parentName as TypeReferenceNode | ImportTypeNode, factory.createTypeReferenceNode(memberName, /*typeArguments*/ undefined), diff --git a/tests/baselines/reference/enumMemberNameNonIdentifier.types b/tests/baselines/reference/enumMemberNameNonIdentifier.types index 71eec1283ba5c..4199dba7f6eb9 100644 --- a/tests/baselines/reference/enumMemberNameNonIdentifier.types +++ b/tests/baselines/reference/enumMemberNameNonIdentifier.types @@ -31,8 +31,8 @@ export const enum E { // Greek Capital Yot (U+037F) - valid identifier in ES2015+ but NOT in ES5 Ϳ = 4, ->Ϳ : (typeof E)["\u037F"] -> : ^^^^^^^^^^^^^^^^^^^^ +>Ϳ : E.Ϳ +> : ^^^ >4 : 4 > : ^ } @@ -78,12 +78,12 @@ export const d = E.regular; > : ^^^^^^^^^ export const e = E.Ϳ; ->e : (typeof E)["\u037F"] -> : ^^^^^^^^^^^^^^^^^^^^ ->E.Ϳ : (typeof E)["\u037F"] -> : ^^^^^^^^^^^^^^^^^^^^ +>e : E.Ϳ +> : ^^^ +>E.Ϳ : E.Ϳ +> : ^^^ >E : typeof E > : ^^^^^^^^ ->Ϳ : (typeof E)["\u037F"] -> : ^^^^^^^^^^^^^^^^^^^^ +>Ϳ : E.Ϳ +> : ^^^