Skip to content

produce an error if private field helpers are not up to date #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26791,12 +26791,18 @@ namespace ts {
const parentSymbol = getNodeLinks(left).resolvedSymbol;
const assignmentKind = getAssignmentTargetKind(node);
const apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType);
if (isPrivateIdentifier(right)) {
checkExternalEmitHelpers(node, ExternalEmitHelpers.ClassPrivateFieldGet);
}
const isAnyLike = isTypeAny(apparentType) || apparentType === silentNeverType;
let prop: Symbol | undefined;
if (isPrivateIdentifier(right)) {
if (languageVersion < ScriptTarget.ESNext) {
if (assignmentKind !== AssignmentKind.None) {
checkExternalEmitHelpers(node, ExternalEmitHelpers.ClassPrivateFieldSet);
}
if (assignmentKind !== AssignmentKind.Definite) {
checkExternalEmitHelpers(node, ExternalEmitHelpers.ClassPrivateFieldGet);
}
}

const lexicallyScopedSymbol = lookupSymbolForPrivateIdentifierDeclaration(right.escapedText, right);
if (assignmentKind && lexicallyScopedSymbol && lexicallyScopedSymbol.valueDeclaration && isMethodDeclaration(lexicallyScopedSymbol.valueDeclaration)) {
grammarErrorOnNode(right, Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable, idText(right));
Expand All @@ -26817,7 +26823,7 @@ namespace ts {
}
else {
const isSetonlyAccessor = prop && prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
if (isSetonlyAccessor && !isAssignmentTarget(node)) {
if (isSetonlyAccessor && assignmentKind !== AssignmentKind.Definite) {
error(node, Diagnostics.Private_accessor_was_defined_without_a_getter);
}
}
Expand Down Expand Up @@ -39906,6 +39912,16 @@ namespace ts {
if (!symbol) {
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_which_does_not_exist_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name);
}
else if (helper & ExternalEmitHelpers.ClassPrivateFieldGet) {
if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 3)) {
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 4);
}
}
else if (helper & ExternalEmitHelpers.ClassPrivateFieldSet) {
if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 4)) {
error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 5);
}
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3300,6 +3300,10 @@
"category": "Error",
"code": 2806
},
"This syntax requires an imported helper named '{1}' with {2} parameters, which is not compatible with the one in '{0}'. Consider upgrading your version of '{0}'.": {
"category": "Error",
"code": 2807
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
20 changes: 20 additions & 0 deletions tests/baselines/reference/privateNameEmitHelpers.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
tests/cases/conformance/classes/members/privateNames/main.ts(3,12): error TS2807: This syntax requires an imported helper named '__classPrivateFieldSet' with 5 parameters, which is not compatible with the one in 'tslib'. Consider upgrading your version of 'tslib'.
tests/cases/conformance/classes/members/privateNames/main.ts(4,25): error TS2807: This syntax requires an imported helper named '__classPrivateFieldGet' with 4 parameters, which is not compatible with the one in 'tslib'. Consider upgrading your version of 'tslib'.


==== tests/cases/conformance/classes/members/privateNames/main.ts (2 errors) ====
export class C {
#a = 1;
#b() { this.#c = 42; }
~~~~~~~
!!! error TS2807: This syntax requires an imported helper named '__classPrivateFieldSet' with 5 parameters, which is not compatible with the one in 'tslib'. Consider upgrading your version of 'tslib'.
set #c(v: number) { this.#a += v; }
~~~~~~~
!!! error TS2807: This syntax requires an imported helper named '__classPrivateFieldGet' with 4 parameters, which is not compatible with the one in 'tslib'. Consider upgrading your version of 'tslib'.
}

==== tests/cases/conformance/classes/members/privateNames/tslib.d.ts (0 errors) ====
// these are pre-TS4.3 versions of emit helpers, which only supported private instance fields
export declare function __classPrivateFieldGet<T extends object, V>(receiver: T, state: any): V;
export declare function __classPrivateFieldSet<T extends object, V>(receiver: T, state: any, value: V): V;

25 changes: 25 additions & 0 deletions tests/baselines/reference/privateNameEmitHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//// [tests/cases/conformance/classes/members/privateNames/privateNameEmitHelpers.ts] ////

//// [main.ts]
export class C {
#a = 1;
#b() { this.#c = 42; }
set #c(v: number) { this.#a += v; }
}

//// [tslib.d.ts]
// these are pre-TS4.3 versions of emit helpers, which only supported private instance fields
export declare function __classPrivateFieldGet<T extends object, V>(receiver: T, state: any): V;
export declare function __classPrivateFieldSet<T extends object, V>(receiver: T, state: any, value: V): V;


//// [main.js]
var _C_instances, _C_a, _C_b, _C_c_set;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
export class C {
constructor() {
_C_instances.add(this);
_C_a.set(this, 1);
}
}
_C_a = new WeakMap(), _C_instances = new WeakSet(), _C_b = function _C_b() { __classPrivateFieldSet(this, _C_instances, 42, "a", _C_c_set); }, _C_c_set = function _C_c_set(v) { __classPrivateFieldSet(this, _C_a, __classPrivateFieldGet(this, _C_a, "f") + v, "f"); };
42 changes: 42 additions & 0 deletions tests/baselines/reference/privateNameEmitHelpers.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
=== tests/cases/conformance/classes/members/privateNames/main.ts ===
export class C {
>C : Symbol(C, Decl(main.ts, 0, 0))

#a = 1;
>#a : Symbol(C.#a, Decl(main.ts, 0, 16))

#b() { this.#c = 42; }
>#b : Symbol(C.#b, Decl(main.ts, 1, 11))
>this.#c : Symbol(C.#c, Decl(main.ts, 2, 26))
>this : Symbol(C, Decl(main.ts, 0, 0))

set #c(v: number) { this.#a += v; }
>#c : Symbol(C.#c, Decl(main.ts, 2, 26))
>v : Symbol(v, Decl(main.ts, 3, 11))
>this.#a : Symbol(C.#a, Decl(main.ts, 0, 16))
>this : Symbol(C, Decl(main.ts, 0, 0))
>v : Symbol(v, Decl(main.ts, 3, 11))
}

=== tests/cases/conformance/classes/members/privateNames/tslib.d.ts ===
// these are pre-TS4.3 versions of emit helpers, which only supported private instance fields
export declare function __classPrivateFieldGet<T extends object, V>(receiver: T, state: any): V;
>__classPrivateFieldGet : Symbol(__classPrivateFieldGet, Decl(tslib.d.ts, --, --))
>T : Symbol(T, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))
>receiver : Symbol(receiver, Decl(tslib.d.ts, --, --))
>T : Symbol(T, Decl(tslib.d.ts, --, --))
>state : Symbol(state, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))

export declare function __classPrivateFieldSet<T extends object, V>(receiver: T, state: any, value: V): V;
>__classPrivateFieldSet : Symbol(__classPrivateFieldSet, Decl(tslib.d.ts, --, --))
>T : Symbol(T, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))
>receiver : Symbol(receiver, Decl(tslib.d.ts, --, --))
>T : Symbol(T, Decl(tslib.d.ts, --, --))
>state : Symbol(state, Decl(tslib.d.ts, --, --))
>value : Symbol(value, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))

37 changes: 37 additions & 0 deletions tests/baselines/reference/privateNameEmitHelpers.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
=== tests/cases/conformance/classes/members/privateNames/main.ts ===
export class C {
>C : C

#a = 1;
>#a : number
>1 : 1

#b() { this.#c = 42; }
>#b : () => void
>this.#c = 42 : 42
>this.#c : number
>this : this
>42 : 42

set #c(v: number) { this.#a += v; }
>#c : number
>v : number
>this.#a += v : number
>this.#a : number
>this : this
>v : number
}

=== tests/cases/conformance/classes/members/privateNames/tslib.d.ts ===
// these are pre-TS4.3 versions of emit helpers, which only supported private instance fields
export declare function __classPrivateFieldGet<T extends object, V>(receiver: T, state: any): V;
>__classPrivateFieldGet : <T extends object, V>(receiver: T, state: any) => V
>receiver : T
>state : any

export declare function __classPrivateFieldSet<T extends object, V>(receiver: T, state: any, value: V): V;
>__classPrivateFieldSet : <T extends object, V>(receiver: T, state: any, value: V) => V
>receiver : T
>state : any
>value : V

20 changes: 20 additions & 0 deletions tests/baselines/reference/privateNameStaticEmitHelpers.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
tests/cases/conformance/classes/members/privateNames/main.ts(3,19): error TS2807: This syntax requires an imported helper named '__classPrivateFieldSet' with 5 parameters, which is not compatible with the one in 'tslib'. Consider upgrading your version of 'tslib'.
tests/cases/conformance/classes/members/privateNames/main.ts(4,30): error TS2807: This syntax requires an imported helper named '__classPrivateFieldGet' with 4 parameters, which is not compatible with the one in 'tslib'. Consider upgrading your version of 'tslib'.


==== tests/cases/conformance/classes/members/privateNames/main.ts (2 errors) ====
export class S {
static #a = 1;
static #b() { this.#a = 42; }
~~~~~~~
!!! error TS2807: This syntax requires an imported helper named '__classPrivateFieldSet' with 5 parameters, which is not compatible with the one in 'tslib'. Consider upgrading your version of 'tslib'.
static get #c() { return S.#b(); }
~~~~
!!! error TS2807: This syntax requires an imported helper named '__classPrivateFieldGet' with 4 parameters, which is not compatible with the one in 'tslib'. Consider upgrading your version of 'tslib'.
}

==== tests/cases/conformance/classes/members/privateNames/tslib.d.ts (0 errors) ====
// these are pre-TS4.3 versions of emit helpers, which only supported private instance fields
export declare function __classPrivateFieldGet<T extends object, V>(receiver: T, state: any): V;
export declare function __classPrivateFieldSet<T extends object, V>(receiver: T, state: any, value: V): V;

22 changes: 22 additions & 0 deletions tests/baselines/reference/privateNameStaticEmitHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/classes/members/privateNames/privateNameStaticEmitHelpers.ts] ////

//// [main.ts]
export class S {
static #a = 1;
static #b() { this.#a = 42; }
static get #c() { return S.#b(); }
}

//// [tslib.d.ts]
// these are pre-TS4.3 versions of emit helpers, which only supported private instance fields
export declare function __classPrivateFieldGet<T extends object, V>(receiver: T, state: any): V;
export declare function __classPrivateFieldSet<T extends object, V>(receiver: T, state: any, value: V): V;


//// [main.js]
var _a, _S_a, _S_b, _S_c_get;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
export class S {
}
_a = S, _S_b = function _S_b() { __classPrivateFieldSet(this, _a, 42, "f", _S_a); }, _S_c_get = function _S_c_get() { return __classPrivateFieldGet(S, _a, "m", _S_b).call(S); };
_S_a = { value: 1 };
40 changes: 40 additions & 0 deletions tests/baselines/reference/privateNameStaticEmitHelpers.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
=== tests/cases/conformance/classes/members/privateNames/main.ts ===
export class S {
>S : Symbol(S, Decl(main.ts, 0, 0))

static #a = 1;
>#a : Symbol(S.#a, Decl(main.ts, 0, 16))

static #b() { this.#a = 42; }
>#b : Symbol(S.#b, Decl(main.ts, 1, 18))
>this.#a : Symbol(S.#a, Decl(main.ts, 0, 16))
>this : Symbol(S, Decl(main.ts, 0, 0))

static get #c() { return S.#b(); }
>#c : Symbol(S.#c, Decl(main.ts, 2, 33))
>S.#b : Symbol(S.#b, Decl(main.ts, 1, 18))
>S : Symbol(S, Decl(main.ts, 0, 0))
}

=== tests/cases/conformance/classes/members/privateNames/tslib.d.ts ===
// these are pre-TS4.3 versions of emit helpers, which only supported private instance fields
export declare function __classPrivateFieldGet<T extends object, V>(receiver: T, state: any): V;
>__classPrivateFieldGet : Symbol(__classPrivateFieldGet, Decl(tslib.d.ts, --, --))
>T : Symbol(T, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))
>receiver : Symbol(receiver, Decl(tslib.d.ts, --, --))
>T : Symbol(T, Decl(tslib.d.ts, --, --))
>state : Symbol(state, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))

export declare function __classPrivateFieldSet<T extends object, V>(receiver: T, state: any, value: V): V;
>__classPrivateFieldSet : Symbol(__classPrivateFieldSet, Decl(tslib.d.ts, --, --))
>T : Symbol(T, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))
>receiver : Symbol(receiver, Decl(tslib.d.ts, --, --))
>T : Symbol(T, Decl(tslib.d.ts, --, --))
>state : Symbol(state, Decl(tslib.d.ts, --, --))
>value : Symbol(value, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))
>V : Symbol(V, Decl(tslib.d.ts, --, --))

35 changes: 35 additions & 0 deletions tests/baselines/reference/privateNameStaticEmitHelpers.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
=== tests/cases/conformance/classes/members/privateNames/main.ts ===
export class S {
>S : S

static #a = 1;
>#a : number
>1 : 1

static #b() { this.#a = 42; }
>#b : () => void
>this.#a = 42 : 42
>this.#a : number
>this : typeof S
>42 : 42

static get #c() { return S.#b(); }
>#c : void
>S.#b() : void
>S.#b : () => void
>S : typeof S
}

=== tests/cases/conformance/classes/members/privateNames/tslib.d.ts ===
// these are pre-TS4.3 versions of emit helpers, which only supported private instance fields
export declare function __classPrivateFieldGet<T extends object, V>(receiver: T, state: any): V;
>__classPrivateFieldGet : <T extends object, V>(receiver: T, state: any) => V
>receiver : T
>state : any

export declare function __classPrivateFieldSet<T extends object, V>(receiver: T, state: any, value: V): V;
>__classPrivateFieldSet : <T extends object, V>(receiver: T, state: any, value: V) => V
>receiver : T
>state : any
>value : V

22 changes: 14 additions & 8 deletions tests/baselines/reference/privateWriteOnlyAccessorRead.errors.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(8,17): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(11,5): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(16,13): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(18,17): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(21,18): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(25,9): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(26,12): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(9,17): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(12,5): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(17,13): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(19,17): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(22,18): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(26,9): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(27,12): error TS2806: Private accessor was defined without a getter.
tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts(30,5): error TS2806: Private accessor was defined without a getter.


==== tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts (7 errors) ====
==== tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRead.ts (8 errors) ====
class Test {
set #value(v: { foo: { bar: number } }) {}
set #valueRest(v: number[]) {}
set #valueOne(v: number) {}
set #valueCompound(v: number) {}

m() {
const foo = { bar: 1 };
Expand Down Expand Up @@ -49,6 +51,10 @@ tests/cases/conformance/classes/members/privateNames/privateWriteOnlyAccessorRea
~~~~~~~~~~~~~~~
!!! error TS2806: Private accessor was defined without a getter.
];

this.#valueCompound += 3;
~~~~~~~~~~~~~~~~~~~
!!! error TS2806: Private accessor was defined without a getter.
}
}
new Test().m();
Expand Down
8 changes: 6 additions & 2 deletions tests/baselines/reference/privateWriteOnlyAccessorRead.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class Test {
set #value(v: { foo: { bar: number } }) {}
set #valueRest(v: number[]) {}
set #valueOne(v: number) {}
set #valueCompound(v: number) {}

m() {
const foo = { bar: 1 };
Expand All @@ -26,6 +27,8 @@ class Test {
this.#valueOne,
...this.#valueRest
];

this.#valueCompound += 3;
}
}
new Test().m();
Expand Down Expand Up @@ -54,7 +57,7 @@ var __rest = (this && this.__rest) || function (s, e) {
}
return t;
};
var _Test_instances, _Test_value_set, _Test_valueRest_set, _Test_valueOne_set;
var _Test_instances, _Test_value_set, _Test_valueRest_set, _Test_valueOne_set, _Test_valueCompound_set;
class Test {
constructor() {
_Test_instances.add(this);
Expand All @@ -81,7 +84,8 @@ class Test {
__classPrivateFieldGet(this, _Test_instances, "a"),
...__classPrivateFieldGet(this, _Test_instances, "a")
];
__classPrivateFieldSet(this, _Test_instances, __classPrivateFieldGet(this, _Test_instances, "a") + 3, "a", _Test_valueCompound_set);
}
}
_Test_instances = new WeakSet(), _Test_value_set = function _Test_value_set(v) { }, _Test_valueRest_set = function _Test_valueRest_set(v) { }, _Test_valueOne_set = function _Test_valueOne_set(v) { };
_Test_instances = new WeakSet(), _Test_value_set = function _Test_value_set(v) { }, _Test_valueRest_set = function _Test_valueRest_set(v) { }, _Test_valueOne_set = function _Test_valueOne_set(v) { }, _Test_valueCompound_set = function _Test_valueCompound_set(v) { };
new Test().m();
Loading