Merge branch 'main' into copilot/fix-61944

This commit is contained in:
Ryan Cavanaugh
2025-06-25 14:45:37 -07:00
committed by GitHub
12 changed files with 367 additions and 3 deletions

View File

@@ -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

View File

@@ -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)) {
@@ -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;
}

View File

@@ -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.
}

View File

@@ -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;
}

View File

@@ -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))
}

View File

@@ -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
> : ^^^^^^
}

View File

@@ -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.

View File

@@ -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;

View File

@@ -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))

View File

@@ -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
> : ^^^^

View File

@@ -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
}

View File

@@ -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;