fix(parser): parse escaped class field names after initializers (#28061)

The Babel class-field fixtures added in #28057 use escaped `in` and `instanceof` names after an initializer. Oxc consumes these names as binary operators and rejects valid class members.

Stop binary-expression parsing at these escaped names after a newline so ASI can end the initializer and class-member parsing can consume the name. Preserve escaped-keyword diagnostics for same-line operator expressions and after ASI, with diagnostic fixtures for both newline cases.
This commit is contained in:
camc314 committed 2026-10-22 18:02:31 +00:00
1 parent 90c58ac971
commit 83633a7a64
8 files changed
+61 -42

No files matched your search

+10
View File
@@ -83,6 +83,9 @@ impl<'a, C: Config> ParserImpl<'a, C> {
// allow `await` and `yield`, let semantic analysis report error
let kind = self.cur_kind();
if !kind.is_identifier_reference(false, false) {
if self.cur_token().escaped() && matches!(kind, Kind::In | Kind::Instanceof) {
return self.fatal_error(diagnostics::escaped_keyword(self.cur_token().span()));
}
return self.unexpected();
}
// Track await identifier for potential reparsing in unambiguous mode
@@ -1350,6 +1353,13 @@ impl<'a, C: Config> ParserImpl<'a, C> {
break;
}
if matches!(kind, Kind::In | Kind::Instanceof)
&& self.cur_token().escaped()
&& self.cur_token().is_on_new_line()
{
break;
}
if matches!(kind, Kind::As | Kind::Satisfies) {
if self.cur_token().is_on_new_line() {
break;
@@ -0,0 +1,2 @@
a
\u{69}n b;
@@ -0,0 +1,2 @@
a
\u{69}nstanceof b;
@@ -2,7 +2,7 @@ commit: a56fe4a4
formatter_babel Summary:
AST Parsed : 2280/2280 (100.00%)
Positive Passed: 2271/2280 (99.61%)
Positive Passed: 2269/2280 (99.52%)
Mismatch: tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-b/enabled/1.1-html-comments-close-let-declaration/input.js
Mismatch: tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-b/enabled/1.1-html-comments-close-let-declaration-cr/input.js
@@ -21,3 +21,7 @@ Mismatch: tasks/coverage/babel/packages/babel-parser/test/fixtures/comments/basi
Mismatch: tasks/coverage/babel/packages/babel-parser/test/fixtures/comments/basic/sequence-expression/input.js
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-properties/escaped-in-after-initializer/input.js
Cannot assign to this expression
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/escaped-in-after-initializer/input.ts
Cannot assign to this expression
+2 -2
View File
@@ -1,3 +1,3 @@
lexer_misc Summary:
AST Parsed : 367/367 (100.00%)
Positive Passed: 367/367 (100.00%)
AST Parsed : 369/369 (100.00%)
Positive Passed: 369/369 (100.00%)
+22 -31
View File
@@ -1,8 +1,8 @@
commit: a56fe4a4
parser_babel Summary:
AST Parsed : 2278/2280 (99.91%)
Positive Passed: 2259/2280 (99.08%)
AST Parsed : 2280/2280 (100.00%)
Positive Passed: 2260/2280 (99.12%)
Negative Passed: 1789/1804 (99.17%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/input.ts
@@ -63,25 +63,6 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-
· ╰── `g` has already been declared here
╰────
Fatal error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-properties/escaped-in-after-initializer/input.js
× Keywords cannot contain escape characters
╭─[babel/packages/babel-parser/test/fixtures/es2022/class-properties/escaped-in-after-initializer/input.js:3:3]
2 │ x = 1
3 │ \u{69}n
· ───────
4 │ y = a
╰────
× Cannot assign to this expression
╭─[babel/packages/babel-parser/test/fixtures/es2022/class-properties/escaped-in-after-initializer/input.js:2:7]
1 │ class C {
2 │ ╭─▶ x = 1
3 │ │ \u{69}n
4 │ ╰─▶ y = a
5 │ \u{69}nstanceof
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/estree/class-private-method/typescript-invalid-abstract/input.ts
× TS(18019): 'abstract' modifier cannot be used with a private identifier.
@@ -120,23 +101,33 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
5 │ f();
╰────
Fatal error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/escaped-in-after-initializer/input.ts
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/escaped-in-after-initializer/input.ts
× Keywords cannot contain escape characters
× Identifier `\u{69}n` has already been declared
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/escaped-in-after-initializer/input.ts:3:3]
2 │ x = 1
3 │ \u{69}n
· ───────
· ───┬───
· ╰── `\u{69}n` has already been declared here
4 │ y = () => a
5 │ \u{69}nstanceof
6 │ z = 1
7 │ \u{69}n() {}
· ───┬───
· ╰── It can not be redeclared here
8 │ \u{69}n = 1
╰────
× Cannot assign to this expression
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/escaped-in-after-initializer/input.ts:2:7]
1 │ class C {
2 │ ╭─▶ x = 1
3 │ │ \u{69}n
4 │ ╰─▶ y = () => a
5 │ \u{69}nstanceof
× Identifier `\u{69}n` has already been declared
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/escaped-in-after-initializer/input.ts:7:3]
6 │ z = 1
7 │ \u{69}n() {}
· ───┬───
· ╰── `\u{69}n` has already been declared here
8 │ \u{69}n = 1
· ───┬───
· ╰── It can not be redeclared here
9 │ }
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/members-with-modifier-names/input.ts
+15 -1
View File
@@ -1,7 +1,7 @@
parser_misc Summary:
AST Parsed : 114/114 (100.00%)
Positive Passed: 114/114 (100.00%)
Negative Passed: 255/255 (100.00%)
Negative Passed: 257/257 (100.00%)
× TS(1275): 'accessor' modifier can only appear on a property declaration.
╭─[misc/fail/accessor-modifier-abstract-method.ts:1:29]
@@ -573,6 +573,20 @@ Negative Passed: 255/255 (100.00%)
· ───────────
╰────
× Keywords cannot contain escape characters
╭─[misc/fail/escaped-in-after-newline.js:2:1]
1 │ a
2 │ \u{69}n b;
· ───────
╰────
× Keywords cannot contain escape characters
╭─[misc/fail/escaped-instanceof-after-newline.js:2:1]
1 │ a
2 │ \u{69}nstanceof b;
· ───────────────
╰────
× Keywords cannot contain escape characters
╭─[misc/fail/escaped-type-import.ts:1:8]
1 │ import t\u0079pe Foo = require("m");
+3 -7
View File
@@ -2,7 +2,7 @@ commit: a56fe4a4
semantic_babel Summary:
AST Parsed : 2280/2280 (100.00%)
Positive Passed: 2185/2280 (95.83%)
Positive Passed: 2186/2280 (95.88%)
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-b/enabled/1.1-html-comments-open-export-default-from/input.js
Cannot use export statement outside a module
@@ -42,10 +42,6 @@ Symbol scope ID mismatch for "_await":
after transform: SymbolId(3): ScopeId(2)
rebuilt : SymbolId(2): ScopeId(0)
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-properties/escaped-in-after-initializer/input.js
Keywords cannot contain escape characters
Cannot assign to this expression
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/valid-for-using-binding-of-of/input.js
Symbol reference IDs mismatch for "of":
after transform: SymbolId(1): [ReferenceId(0)]
@@ -108,8 +104,8 @@ after transform: ["a"]
rebuilt : []
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/escaped-in-after-initializer/input.ts
Keywords cannot contain escape characters
Cannot assign to this expression
Identifier `\u{69}n` has already been declared
Identifier `\u{69}n` has already been declared
semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/get-generic/input.ts
Bindings mismatch: