Skip to content

fix(parser): preserve escaped class field names across newlines - #65377

Open
Jemmy (JemmyIndex) wants to merge 1 commit into
microsoft:mainfrom
JemmyIndex:fix/escaped-class-modifiers-65306
Open

Jemmy (JemmyIndex) wants to merge 1 commit into
microsoft:mainfrom
JemmyIndex:fix/escaped-class-modifiers-65306

Conversation

@JemmyIndex

Copy link
Copy Markdown

Fixes #65306.

Unicode-escaped class field names that decode to get, set, or static are currently consumed as modifiers when the next member starts on a new line. This produces TS1260 and other diagnostics for valid fields, and can change emitted instance methods into accessors or static methods.

Save the current token's Unicode escape flags before advancing in nextTokenCanFollowModifier. If the token is escaped and the following token has a preceding line break, reject the modifier interpretation so the parser rewinds and parses a field name. Ordinary multiline modifiers and diagnostics for invalid same-line escaped modifiers keep their existing behavior.

Add a compiler regression case for all three names with ordinary and extended Unicode escapes, with ES2015 and ESNext emit baselines. The case also checks member access, ordinary multiline modifiers, escaped method names, and invalid same-line escaped modifiers.

Validation:

  • The focused compiler test passes for both targets and all child checks; before the fix, the valid fields produced syntax/member diagnostics and incorrect emit.
  • Emitted JavaScript behavior was checked on Node 22 and Node 27 alpha. The original JavaScript repro also compiles with ES2015, ES2022, and ESNext targets and produces the expected field ownership and method placement on both runtimes.
  • validate --all completed: compiler/parser/scanner/fourslash/CLI, extension, native/WASM API, tools/options, smoke, lint, and formatting checks passed apart from two Windows symlink tests. The overall command exits unsuccessfully because TestSubscribeSymlinkCreate/windows and TestSubscribeSymlinkDelete/windows cannot create symlinks on this machine (A required privilege is not held by the client); their parent failures account for the other two failure records.
  • hereby tidy and hereby check:format passed, with no dependency or unrelated generated-file changes.

AI assistance: Codex authored the patch and regression test and ran validation for this specifically selected issue.

Copilot AI balanced review requested due to automatic review settings November 7, 2026 06:28
@typescript-automation typescript-automation Bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Nov 7, 2026
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Nov 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

There are no active review issues for the parser change preserving Unicode-escaped class field names.

No open issues 🎉

What changed in this PR

Fixes #65306 in the native TypeScript parser by preserving Unicode-escaped get, set, and static as class field names when followed by a line break, avoiding incorrect diagnostics and emitted member placement.

Changes:

  • Captures Unicode escape flags before advancing modifier lookahead.
  • Adds regression coverage for ordinary and extended escapes, while checking existing modifier and method-name behavior.
  • Adds ES2015 and ESNext diagnostic, emit, symbol, and type baselines.
File Description
tsc/​testdata/​tests/​cases/​compiler/​escapedClassFieldModifiers.ts Adds regression cases for escaped fields and related modifier behavior.
tsc/​testdata/​baselines/​reference/​compiler/​escapedClassFieldModifiers(target=esnext).types Records expected ESNext member types.
tsc/​testdata/​baselines/​reference/​compiler/​escapedClassFieldModifiers(target=esnext).symbols Records expected ESNext symbol bindings.
tsc/​testdata/​baselines/​reference/​compiler/​escapedClassFieldModifiers(target=esnext).js Verifies native class-field emit and member placement.
tsc/​testdata/​baselines/​reference/​compiler/​escapedClassFieldModifiers(target=esnext).errors.txt Limits expected errors to invalid same-line escaped modifiers.
tsc/​testdata/​baselines/​reference/​compiler/​escapedClassFieldModifiers(target=es2015).types Records expected ES2015 member types.
tsc/​testdata/​baselines/​reference/​compiler/​escapedClassFieldModifiers(target=es2015).symbols Records expected ES2015 symbol bindings.
tsc/​testdata/​baselines/​reference/​compiler/​escapedClassFieldModifiers(target=es2015).js Verifies downlevel field initialization and instance methods.
tsc/​testdata/​baselines/​reference/​compiler/​escapedClassFieldModifiers(target=es2015).errors.txt Preserves same-line escaped-modifier diagnostics for ES2015.
tsc/​internal/​parser/​parser.go Rejects modifier interpretation for escaped names followed by a line break.

Review effort: Balanced

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

Escaped get/set/static followed by a line break is parsed as an accessor/static modifier instead of a field name (TS1260)

2 participants