From 11c7daef629e650d3e7bd1e48551ddd28de22b8f Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Mon, 26 Jul 2021 21:39:17 +0300 Subject: [PATCH] fix(45114): throw an error when using '#' as an identifier (#45124) --- src/compiler/scanner.ts | 11 +++++-- .../privateNameHashCharName.errors.txt | 25 ++++++++++++++++ .../reference/privateNameHashCharName.js | 29 +++++++++++++++++++ .../reference/privateNameHashCharName.symbols | 18 ++++++++++++ .../reference/privateNameHashCharName.types | 19 ++++++++++++ .../privateNames/privateNameHashCharName.ts | 11 +++++++ 6 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/privateNameHashCharName.errors.txt create mode 100644 tests/baselines/reference/privateNameHashCharName.js create mode 100644 tests/baselines/reference/privateNameHashCharName.symbols create mode 100644 tests/baselines/reference/privateNameHashCharName.types create mode 100644 tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 225dc353a0..8e31a88589 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -2047,8 +2047,15 @@ namespace ts { pos++; return token = SyntaxKind.Unknown; } - pos++; - scanIdentifier(codePointAt(text, pos), languageVersion); + + if (isIdentifierStart(codePointAt(text, pos + 1), languageVersion)) { + pos++; + scanIdentifier(codePointAt(text, pos), languageVersion); + } + else { + tokenValue = String.fromCharCode(codePointAt(text, pos)); + error(Diagnostics.Invalid_character, pos++, charSize(ch)); + } return token = SyntaxKind.PrivateIdentifier; default: const identifierKind = scanIdentifier(ch, languageVersion); diff --git a/tests/baselines/reference/privateNameHashCharName.errors.txt b/tests/baselines/reference/privateNameHashCharName.errors.txt new file mode 100644 index 0000000000..211a62a47f --- /dev/null +++ b/tests/baselines/reference/privateNameHashCharName.errors.txt @@ -0,0 +1,25 @@ +tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts(1,1): error TS1127: Invalid character. +tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts(1,1): error TS2304: Cannot find name '#'. +tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts(4,5): error TS1127: Invalid character. +tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts(7,14): error TS1127: Invalid character. + + +==== tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts (4 errors) ==== + # + ~ +!!! error TS1127: Invalid character. + ~ +!!! error TS2304: Cannot find name '#'. + + class C { + # + ~ +!!! error TS1127: Invalid character. + + m() { + this.# + ~ +!!! error TS1127: Invalid character. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameHashCharName.js b/tests/baselines/reference/privateNameHashCharName.js new file mode 100644 index 0000000000..fcc0dead80 --- /dev/null +++ b/tests/baselines/reference/privateNameHashCharName.js @@ -0,0 +1,29 @@ +//// [privateNameHashCharName.ts] +# + +class C { + # + + m() { + this.# + } +} + + +//// [privateNameHashCharName.js] +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 _C_; +#; +class C { + constructor() { + _C_.set(this, void 0); + } + m() { + __classPrivateFieldGet(this, _C_, "f"); + } +} +_C_ = new WeakMap(); diff --git a/tests/baselines/reference/privateNameHashCharName.symbols b/tests/baselines/reference/privateNameHashCharName.symbols new file mode 100644 index 0000000000..5cb018c50d --- /dev/null +++ b/tests/baselines/reference/privateNameHashCharName.symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts === +# + +class C { +>C : Symbol(C, Decl(privateNameHashCharName.ts, 0, 1)) + + # +># : Symbol(C[#], Decl(privateNameHashCharName.ts, 2, 9)) + + m() { +>m : Symbol(C.m, Decl(privateNameHashCharName.ts, 3, 5)) + + this.# +>this.# : Symbol(C[#], Decl(privateNameHashCharName.ts, 2, 9)) +>this : Symbol(C, Decl(privateNameHashCharName.ts, 0, 1)) + } +} + diff --git a/tests/baselines/reference/privateNameHashCharName.types b/tests/baselines/reference/privateNameHashCharName.types new file mode 100644 index 0000000000..f321b7bcda --- /dev/null +++ b/tests/baselines/reference/privateNameHashCharName.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts === +# +># : any + +class C { +>C : C + + # +># : any + + m() { +>m : () => void + + this.# +>this.# : any +>this : this + } +} + diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts b/tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts new file mode 100644 index 0000000000..4a076565bf --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameHashCharName.ts @@ -0,0 +1,11 @@ +// @target: es6 + +# + +class C { + # + + m() { + this.# + } +}