Skip to content

Gate ES2025 regex syntax behind target - #4877

Open
Dayong Lee (dayongkr) wants to merge 3 commits into
microsoft:mainfrom
dayongkr:fix/gate-es2025-regex-syntax
Open

Gate ES2025 regex syntax behind target#4877
Dayong Lee (dayongkr) wants to merge 3 commits into
microsoft:mainfrom
dayongkr:fix/gate-es2025-regex-syntax

Conversation

@dayongkr

Copy link
Copy Markdown

Fixes microsoft/TypeScript#63682

Analysis

Pattern modifiers and duplicate named capturing groups are parsed and validated, but never checked against target:

// target: es2022
/[\p{ASCII}]/v                          // TS1501
/(?i:abc)/                              // no error
/(?<y>\d{4})-\d{2}|\d{2}\/(?<y>\d{4})/  // no error

Both are a SyntaxError before ES2025. The v flag and named capturing groups already have version gates. These two were Stage 3 with no edition assigned when regex body validation was written, so they never got one.

Fix

Two checks in internal/scanner/regexp.go:

  • Modifiers: gate in scanDisjunction when the group actually consumed modifier characters. Comparing against flagsStart keeps plain (?: out.
  • Duplicate names: gate in scanGroupName when the name is already in groupSpecifiers but not in scope for any enclosing alternative. Duplicates inside one alternative still report only TS1515.

New messages go in extraDiagnosticMessages.json since the submodule's json is not editable here. 18062 and 18063 are unused upstream.

Test: regularExpressionES2025Syntax.ts at es2022 and es2025, including the cases that must stay clean ((?:, non-duplicated names).

One thing to flag: this creates a 6.0/7.0 difference instead of removing one. Upstream's regularExpressionScanning.ts at es2015 gains 4 errors, so this adds a .diff baseline. 6.0 is closed, so the gate can only land on 7.x. Happy to close it if you would rather keep the gap.

Copilot Checklist

I successfully ran these commands at the end of my session, and they completed without error:

  • npx hereby build
  • npx hereby test
  • npx hereby lint
  • npx hereby format

Lint fails only in internal/nativepath/realpath_darwin_test.go, which is identical to main on this branch. ./internal/scanner/... and ./internal/diagnostics/... report 0 issues.

Disclosure: written with AI assistance (Claude Code). I read the change and will handle review myself.

Pattern modifiers and duplicate named capturing groups are parsed and
validated by the scanner but never checked against target, so they
compile clean at every target even though both are a SyntaxError on
engines that predate ES2025. Report them below ES2025, matching how the
v flag and named capturing groups are already gated.

Fixes microsoft/TypeScript#63682
Copilot AI balanced review requested due to automatic review settings August 11, 2026 15:32

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.

Pull request overview

Adds ES2025 target checks for regular-expression pattern modifiers and duplicate named capture groups.

Changes:

  • Adds scanner target diagnostics.
  • Registers diagnostic codes TS18062 and TS18063.
  • Adds compiler tests and baselines for ES2022 and ES2025.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
internal/scanner/regexp.go Implements target checks.
internal/diagnostics/extraDiagnosticMessages.json Defines new diagnostics.
internal/diagnostics/diagnostics_generated.go Adds generated diagnostic mappings.
testdata/tests/cases/compiler/regularExpressionES2025Syntax.ts Adds target-dependent tests.
testdata/baselines/reference/compiler/regularExpressionES2025Syntax(target=es2022).errors.txt Records pre-ES2025 errors.
testdata/baselines/reference/compiler/regularExpressionES2025Syntax(target=es2022).symbols Records ES2022 symbols.
testdata/baselines/reference/compiler/regularExpressionES2025Syntax(target=es2022).types Records ES2022 types.
testdata/baselines/reference/compiler/regularExpressionES2025Syntax(target=es2025).errors.txt Records ES2025 errors.
testdata/baselines/reference/compiler/regularExpressionES2025Syntax(target=es2025).symbols Records ES2025 symbols.
testdata/baselines/reference/compiler/regularExpressionES2025Syntax(target=es2025).types Records ES2025 types.
testdata/baselines/reference/submodule/compiler/regularExpressionScanning(target=es2015).errors.txt Updates submodule baseline.
testdata/baselines/reference/submodule/compiler/regularExpressionScanning(target=es2015).errors.txt.diff Records upstream divergence.
Files not reviewed (1)
  • internal/diagnostics/diagnostics_generated.go: Generated file

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +491 to +494
// The name is not in scope for any enclosing alternative, so a previous definition of it
// can only have come from a mutually exclusive alternative.
if p.groupSpecifiers[p.scanner.tokenValue] && p.scanner.languageVersion() < core.ScriptTargetES2025 {
p.error(diagnostics.Duplicate_named_capturing_groups_are_only_available_when_targeting_0_or_later, p.scanner.tokenStart, p.pos()-p.scanner.tokenStart, strings.ToLower(core.ScriptTargetES2025.String()))

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Confirmed, but I would rather fix it separately.

The missing TS1515 predates this change. scanDisjunction drops an alternative's scope once the alternative ends, in Strada too (topNamedCapturingGroupsScope = namedCapturingGroupsScopeStack.pop()), so the check is never reached for that pattern:

  • tsc 5.9.3 on /(?:(?<a>x)|y)(?<a>z)/: no error. It does report TS1515 for /(?<a>x)(?<a>y)/, so the rule itself works.
  • typescript@7.0.2 without this patch: no error.

What this PR does add is the wrong message for that pattern below ES2025: TS18063 where TS1515 belongs. It is still reported as an error, so nothing valid starts or stops compiling, but the wording points at the wrong cause.

Fixing the scope tracking means 7.x reports an error 6.0 does not, which is the same divergence question as in the description, so it seems better as its own PR with its own test matrix. Happy to open that once this lands.

@dayongkr

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ES2025 regex syntax (duplicate named groups, pattern modifiers) is not gated by target

3 participants