From b9f3c07f9b30cd05a911d1af3743bc17a0e6f161 Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Wed, 4 Nov 2026 07:57:12 +0800 Subject: [PATCH] fix(debugger): identifier boundary check for astral letters under V8 (#1117) Smart Step Into and Safe Delete tested the text before a match with /[\p{L}\p{N}_$]$/u, which V8 in Node 26 fails for a letter outside the BMP (a lone property class before $), so smartStep.test.ts failed. Both checks now use an alternation with the same meaning. --- src/editor/refactor/safeDelete.ts | 3 ++- src/features/debugger/editor/smartStep.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/editor/refactor/safeDelete.ts b/src/editor/refactor/safeDelete.ts index 81b94be0a..215af366b 100644 --- a/src/editor/refactor/safeDelete.ts +++ b/src/editor/refactor/safeDelete.ts @@ -365,7 +365,8 @@ export function textOccurrences( const out: { from: number; to: number }[] = []; for (let m = re.exec(text); m; m = re.exec(text)) { const from = m.index; - if (/[\p{L}\p{N}_$]$/u.test(text.slice(Math.max(0, from - 2), from))) continue; + // Not `[\p{L}\p{N}_$]$`: V8 (Node 26) misses an astral letter with a lone class before `$`. + if (/(?:\p{L}|\p{N}|[_$])$/u.test(text.slice(Math.max(0, from - 2), from))) continue; if (ids.has(from) || (from >= exclude.from && from < exclude.to)) continue; out.push({ from, to: from + name.length }); } diff --git a/src/features/debugger/editor/smartStep.ts b/src/features/debugger/editor/smartStep.ts index c5617ab41..6740d2ffb 100644 --- a/src/features/debugger/editor/smartStep.ts +++ b/src/features/debugger/editor/smartStep.ts @@ -29,7 +29,8 @@ function callPattern(name: string, flags: string): RegExp { } function isCallBoundary(text: string, from: number): boolean { - return !/[\p{L}\p{N}_$]$/u.test(text.slice(Math.max(0, from - 2), from)); + // Not `[\p{L}\p{N}_$]$`: V8 (Node 26) misses an astral letter with a lone class before `$`. + return !/(?:\p{L}|\p{N}|[_$])$/u.test(text.slice(Math.max(0, from - 2), from)); } function identifierEnd(text: string, from: number): number {