From 1ed8674bba538a280c1846d628069fb9646731ab Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Jun 2025 14:29:02 -0700 Subject: [PATCH 1/3] Allow `accessor` properties in ambient contexts when targeting ES5 (#61927) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com> --- src/compiler/checker.ts | 2 +- .../accessorInAmbientContextES5.errors.txt | 32 ++++++++ .../reference/accessorInAmbientContextES5.js | 81 +++++++++++++++++++ .../accessorInAmbientContextES5.symbols | 51 ++++++++++++ .../accessorInAmbientContextES5.types | 64 +++++++++++++++ .../compiler/accessorInAmbientContextES5.ts | 29 +++++++ 6 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/accessorInAmbientContextES5.errors.txt create mode 100644 tests/baselines/reference/accessorInAmbientContextES5.js create mode 100644 tests/baselines/reference/accessorInAmbientContextES5.symbols create mode 100644 tests/baselines/reference/accessorInAmbientContextES5.types create mode 100644 tests/cases/compiler/accessorInAmbientContextES5.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ba8ec48a39e..5614da35039 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -53039,7 +53039,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) { return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); } - if (languageVersion < ScriptTarget.ES2015 && isAutoAccessorPropertyDeclaration(node)) { + if (languageVersion < ScriptTarget.ES2015 && isAutoAccessorPropertyDeclaration(node) && !(node.flags & NodeFlags.Ambient)) { return grammarErrorOnNode(node.name, Diagnostics.Properties_with_the_accessor_modifier_are_only_available_when_targeting_ECMAScript_2015_and_higher); } if (isAutoAccessorPropertyDeclaration(node) && checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_accessor_property_cannot_be_declared_optional)) { diff --git a/tests/baselines/reference/accessorInAmbientContextES5.errors.txt b/tests/baselines/reference/accessorInAmbientContextES5.errors.txt new file mode 100644 index 00000000000..c9351f69f72 --- /dev/null +++ b/tests/baselines/reference/accessorInAmbientContextES5.errors.txt @@ -0,0 +1,32 @@ +accessorInAmbientContextES5.ts(25,14): error TS18045: Properties with the 'accessor' modifier are only available when targeting ECMAScript 2015 and higher. + + +==== accessorInAmbientContextES5.ts (1 errors) ==== + // Should allow accessor in ambient contexts even when targeting ES5 + + declare class AmbientClass { + accessor prop1: string; + static accessor prop2: number; + private accessor prop3: boolean; + private static accessor prop4: symbol; + } + + declare namespace AmbientNamespace { + class C { + accessor prop: string; + } + } + + // Should also work in .d.ts files (simulated with declare) + declare module "some-module" { + export class ExportedClass { + accessor value: any; + } + } + + // Regular class should still error when targeting ES5 + class RegularClass { + accessor shouldError: string; // Should still error + ~~~~~~~~~~~ +!!! error TS18045: Properties with the 'accessor' modifier are only available when targeting ECMAScript 2015 and higher. + } \ No newline at end of file diff --git a/tests/baselines/reference/accessorInAmbientContextES5.js b/tests/baselines/reference/accessorInAmbientContextES5.js new file mode 100644 index 00000000000..caea4933da8 --- /dev/null +++ b/tests/baselines/reference/accessorInAmbientContextES5.js @@ -0,0 +1,81 @@ +//// [tests/cases/compiler/accessorInAmbientContextES5.ts] //// + +//// [accessorInAmbientContextES5.ts] +// Should allow accessor in ambient contexts even when targeting ES5 + +declare class AmbientClass { + accessor prop1: string; + static accessor prop2: number; + private accessor prop3: boolean; + private static accessor prop4: symbol; +} + +declare namespace AmbientNamespace { + class C { + accessor prop: string; + } +} + +// Should also work in .d.ts files (simulated with declare) +declare module "some-module" { + export class ExportedClass { + accessor value: any; + } +} + +// Regular class should still error when targeting ES5 +class RegularClass { + accessor shouldError: string; // Should still error +} + +//// [accessorInAmbientContextES5.js] +// Should allow accessor in ambient contexts even when targeting ES5 +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _RegularClass_shouldError_accessor_storage; +// Regular class should still error when targeting ES5 +var RegularClass = /** @class */ (function () { + function RegularClass() { + _RegularClass_shouldError_accessor_storage.set(this, void 0); + } + Object.defineProperty(RegularClass.prototype, "shouldError", { + get: function () { return __classPrivateFieldGet(this, _RegularClass_shouldError_accessor_storage, "f"); } // Should still error + , + set: function (value) { __classPrivateFieldSet(this, _RegularClass_shouldError_accessor_storage, value, "f"); }, + enumerable: false, + configurable: true + }); + return RegularClass; +}()); +_RegularClass_shouldError_accessor_storage = new WeakMap(); + + +//// [accessorInAmbientContextES5.d.ts] +declare class AmbientClass { + accessor prop1: string; + static accessor prop2: number; + private accessor prop3; + private static accessor prop4; +} +declare namespace AmbientNamespace { + class C { + accessor prop: string; + } +} +declare module "some-module" { + class ExportedClass { + accessor value: any; + } +} +declare class RegularClass { + accessor shouldError: string; +} diff --git a/tests/baselines/reference/accessorInAmbientContextES5.symbols b/tests/baselines/reference/accessorInAmbientContextES5.symbols new file mode 100644 index 00000000000..c37f91917d2 --- /dev/null +++ b/tests/baselines/reference/accessorInAmbientContextES5.symbols @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/accessorInAmbientContextES5.ts] //// + +=== accessorInAmbientContextES5.ts === +// Should allow accessor in ambient contexts even when targeting ES5 + +declare class AmbientClass { +>AmbientClass : Symbol(AmbientClass, Decl(accessorInAmbientContextES5.ts, 0, 0)) + + accessor prop1: string; +>prop1 : Symbol(AmbientClass.prop1, Decl(accessorInAmbientContextES5.ts, 2, 28)) + + static accessor prop2: number; +>prop2 : Symbol(AmbientClass.prop2, Decl(accessorInAmbientContextES5.ts, 3, 27)) + + private accessor prop3: boolean; +>prop3 : Symbol(AmbientClass.prop3, Decl(accessorInAmbientContextES5.ts, 4, 34)) + + private static accessor prop4: symbol; +>prop4 : Symbol(AmbientClass.prop4, Decl(accessorInAmbientContextES5.ts, 5, 36)) +} + +declare namespace AmbientNamespace { +>AmbientNamespace : Symbol(AmbientNamespace, Decl(accessorInAmbientContextES5.ts, 7, 1)) + + class C { +>C : Symbol(C, Decl(accessorInAmbientContextES5.ts, 9, 36)) + + accessor prop: string; +>prop : Symbol(C.prop, Decl(accessorInAmbientContextES5.ts, 10, 13)) + } +} + +// Should also work in .d.ts files (simulated with declare) +declare module "some-module" { +>"some-module" : Symbol("some-module", Decl(accessorInAmbientContextES5.ts, 13, 1)) + + export class ExportedClass { +>ExportedClass : Symbol(ExportedClass, Decl(accessorInAmbientContextES5.ts, 16, 30)) + + accessor value: any; +>value : Symbol(ExportedClass.value, Decl(accessorInAmbientContextES5.ts, 17, 32)) + } +} + +// Regular class should still error when targeting ES5 +class RegularClass { +>RegularClass : Symbol(RegularClass, Decl(accessorInAmbientContextES5.ts, 20, 1)) + + accessor shouldError: string; // Should still error +>shouldError : Symbol(RegularClass.shouldError, Decl(accessorInAmbientContextES5.ts, 23, 20)) +} diff --git a/tests/baselines/reference/accessorInAmbientContextES5.types b/tests/baselines/reference/accessorInAmbientContextES5.types new file mode 100644 index 00000000000..eefedf0cf13 --- /dev/null +++ b/tests/baselines/reference/accessorInAmbientContextES5.types @@ -0,0 +1,64 @@ +//// [tests/cases/compiler/accessorInAmbientContextES5.ts] //// + +=== accessorInAmbientContextES5.ts === +// Should allow accessor in ambient contexts even when targeting ES5 + +declare class AmbientClass { +>AmbientClass : AmbientClass +> : ^^^^^^^^^^^^ + + accessor prop1: string; +>prop1 : string +> : ^^^^^^ + + static accessor prop2: number; +>prop2 : number +> : ^^^^^^ + + private accessor prop3: boolean; +>prop3 : boolean +> : ^^^^^^^ + + private static accessor prop4: symbol; +>prop4 : symbol +> : ^^^^^^ +} + +declare namespace AmbientNamespace { +>AmbientNamespace : typeof AmbientNamespace +> : ^^^^^^^^^^^^^^^^^^^^^^^ + + class C { +>C : C +> : ^ + + accessor prop: string; +>prop : string +> : ^^^^^^ + } +} + +// Should also work in .d.ts files (simulated with declare) +declare module "some-module" { +>"some-module" : typeof import("some-module") +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + export class ExportedClass { +>ExportedClass : ExportedClass +> : ^^^^^^^^^^^^^ + + accessor value: any; +>value : any +> : ^^^ + } +} + +// Regular class should still error when targeting ES5 +class RegularClass { +>RegularClass : RegularClass +> : ^^^^^^^^^^^^ + + accessor shouldError: string; // Should still error +>shouldError : string +> : ^^^^^^ +} diff --git a/tests/cases/compiler/accessorInAmbientContextES5.ts b/tests/cases/compiler/accessorInAmbientContextES5.ts new file mode 100644 index 00000000000..42fb79e9774 --- /dev/null +++ b/tests/cases/compiler/accessorInAmbientContextES5.ts @@ -0,0 +1,29 @@ +// @target: es5 +// @declaration: true + +// Should allow accessor in ambient contexts even when targeting ES5 + +declare class AmbientClass { + accessor prop1: string; + static accessor prop2: number; + private accessor prop3: boolean; + private static accessor prop4: symbol; +} + +declare namespace AmbientNamespace { + class C { + accessor prop: string; + } +} + +// Should also work in .d.ts files (simulated with declare) +declare module "some-module" { + export class ExportedClass { + accessor value: any; + } +} + +// Regular class should still error when targeting ES5 +class RegularClass { + accessor shouldError: string; // Should still error +} \ No newline at end of file From 6e519c59c13e4e99da0bf779a1f2bbee232cf7a1 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Jun 2025 14:29:50 -0700 Subject: [PATCH 2/3] Fix BigInt literal error in ambient contexts when targeting < ES2020 (#61935) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com> --- src/compiler/checker.ts | 3 +- .../reference/bigintAmbientMinimal.errors.txt | 17 +++++++++ .../reference/bigintAmbientMinimal.js | 18 ++++++++++ .../reference/bigintAmbientMinimal.symbols | 22 ++++++++++++ .../reference/bigintAmbientMinimal.types | 35 +++++++++++++++++++ tests/cases/compiler/bigintAmbientMinimal.ts | 14 ++++++++ 6 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/bigintAmbientMinimal.errors.txt create mode 100644 tests/baselines/reference/bigintAmbientMinimal.js create mode 100644 tests/baselines/reference/bigintAmbientMinimal.symbols create mode 100644 tests/baselines/reference/bigintAmbientMinimal.types create mode 100644 tests/cases/compiler/bigintAmbientMinimal.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5614da35039..e66a209af81 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -53188,7 +53188,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const literalType = isLiteralTypeNode(node.parent) || isPrefixUnaryExpression(node.parent) && isLiteralTypeNode(node.parent.parent); if (!literalType) { - if (languageVersion < ScriptTarget.ES2020) { + // Don't error on BigInt literals in ambient contexts + if (!(node.flags & NodeFlags.Ambient) && languageVersion < ScriptTarget.ES2020) { if (grammarErrorOnNode(node, Diagnostics.BigInt_literals_are_not_available_when_targeting_lower_than_ES2020)) { return true; } diff --git a/tests/baselines/reference/bigintAmbientMinimal.errors.txt b/tests/baselines/reference/bigintAmbientMinimal.errors.txt new file mode 100644 index 00000000000..e95b511da01 --- /dev/null +++ b/tests/baselines/reference/bigintAmbientMinimal.errors.txt @@ -0,0 +1,17 @@ +/main.ts(5,17): error TS2737: BigInt literals are not available when targeting lower than ES2020. + + +==== /ambient.d.ts (0 errors) ==== + declare const fromDts = 789n; + declare namespace Lib { + const value = 999n; + } + +==== /main.ts (1 errors) ==== + // Minimal repro from issue + declare const n = 123n; + + // Non-ambient for comparison + const regular = 456n; + ~~~~ +!!! error TS2737: BigInt literals are not available when targeting lower than ES2020. \ No newline at end of file diff --git a/tests/baselines/reference/bigintAmbientMinimal.js b/tests/baselines/reference/bigintAmbientMinimal.js new file mode 100644 index 00000000000..d2147fb7d30 --- /dev/null +++ b/tests/baselines/reference/bigintAmbientMinimal.js @@ -0,0 +1,18 @@ +//// [tests/cases/compiler/bigintAmbientMinimal.ts] //// + +//// [ambient.d.ts] +declare const fromDts = 789n; +declare namespace Lib { + const value = 999n; +} + +//// [main.ts] +// Minimal repro from issue +declare const n = 123n; + +// Non-ambient for comparison +const regular = 456n; + +//// [main.js] +// Non-ambient for comparison +var regular = 456n; diff --git a/tests/baselines/reference/bigintAmbientMinimal.symbols b/tests/baselines/reference/bigintAmbientMinimal.symbols new file mode 100644 index 00000000000..d438ba12359 --- /dev/null +++ b/tests/baselines/reference/bigintAmbientMinimal.symbols @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/bigintAmbientMinimal.ts] //// + +=== /ambient.d.ts === +declare const fromDts = 789n; +>fromDts : Symbol(fromDts, Decl(ambient.d.ts, 0, 13)) + +declare namespace Lib { +>Lib : Symbol(Lib, Decl(ambient.d.ts, 0, 29)) + + const value = 999n; +>value : Symbol(value, Decl(ambient.d.ts, 2, 9)) +} + +=== /main.ts === +// Minimal repro from issue +declare const n = 123n; +>n : Symbol(n, Decl(main.ts, 1, 13)) + +// Non-ambient for comparison +const regular = 456n; +>regular : Symbol(regular, Decl(main.ts, 4, 5)) + diff --git a/tests/baselines/reference/bigintAmbientMinimal.types b/tests/baselines/reference/bigintAmbientMinimal.types new file mode 100644 index 00000000000..086ac1d5676 --- /dev/null +++ b/tests/baselines/reference/bigintAmbientMinimal.types @@ -0,0 +1,35 @@ +//// [tests/cases/compiler/bigintAmbientMinimal.ts] //// + +=== /ambient.d.ts === +declare const fromDts = 789n; +>fromDts : 789n +> : ^^^^ +>789n : 789n +> : ^^^^ + +declare namespace Lib { +>Lib : typeof Lib +> : ^^^^^^^^^^ + + const value = 999n; +>value : 999n +> : ^^^^ +>999n : 999n +> : ^^^^ +} + +=== /main.ts === +// Minimal repro from issue +declare const n = 123n; +>n : 123n +> : ^^^^ +>123n : 123n +> : ^^^^ + +// Non-ambient for comparison +const regular = 456n; +>regular : 456n +> : ^^^^ +>456n : 456n +> : ^^^^ + diff --git a/tests/cases/compiler/bigintAmbientMinimal.ts b/tests/cases/compiler/bigintAmbientMinimal.ts new file mode 100644 index 00000000000..4bad00279bc --- /dev/null +++ b/tests/cases/compiler/bigintAmbientMinimal.ts @@ -0,0 +1,14 @@ +// @target: ES5 + +// @Filename: /ambient.d.ts +declare const fromDts = 789n; +declare namespace Lib { + const value = 999n; +} + +// @Filename: /main.ts +// Minimal repro from issue +declare const n = 123n; + +// Non-ambient for comparison +const regular = 456n; \ No newline at end of file From f3a6d3165ff91289bf8558ce981042d2fff22a36 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 25 Jun 2025 14:35:09 -0700 Subject: [PATCH 3/3] Update copilot-setup-steps.yml (#61948) --- .github/workflows/copilot-setup-steps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 083512529cd..8fc19fa4368 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -19,4 +19,4 @@ jobs: - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - run: npm ci # pull dprint caches before network access is blocked - - run: npx hereby check:format || true + - run: npx hereby check-format || true