Skip to content

Commit ade740e

Browse files
Correct flags scanning for non-BMP characters
(cherry picked from commit e67692a)
1 parent 9370347 commit ade740e

6 files changed

+64
-16
lines changed

src/compiler/scanner.ts

+18-16
Original file line numberDiff line numberDiff line change
@@ -2474,28 +2474,29 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
24742474
const isUnterminated = !!(tokenFlags & TokenFlags.Unterminated);
24752475
const endOfBody = p - (isUnterminated ? 0 : 1);
24762476
let regExpFlags = RegularExpressionFlags.None;
2477-
while (p < end) {
2478-
const ch = charCodeUnchecked(p);
2479-
if (!isIdentifierPart(ch, languageVersion)) {
2477+
while (true) {
2478+
const ch = codePointChecked(p);
2479+
if (ch === CharacterCodes.EOF || !isIdentifierPart(ch, languageVersion)) {
24802480
break;
24812481
}
2482+
const size = charSize(ch);
24822483
if (reportErrors) {
2483-
const flag = characterToRegularExpressionFlag(String.fromCharCode(ch));
2484+
const flag = characterToRegularExpressionFlag(utf16EncodeAsString(ch));
24842485
if (flag === undefined) {
2485-
error(Diagnostics.Unknown_regular_expression_flag, p, 1);
2486+
error(Diagnostics.Unknown_regular_expression_flag, p, size);
24862487
}
24872488
else if (regExpFlags & flag) {
2488-
error(Diagnostics.Duplicate_regular_expression_flag, p, 1);
2489+
error(Diagnostics.Duplicate_regular_expression_flag, p, size);
24892490
}
24902491
else if (((regExpFlags | flag) & RegularExpressionFlags.UnicodeMode) === RegularExpressionFlags.UnicodeMode) {
2491-
error(Diagnostics.The_Unicode_u_flag_and_the_Unicode_Sets_v_flag_cannot_be_set_simultaneously, p, 1);
2492+
error(Diagnostics.The_Unicode_u_flag_and_the_Unicode_Sets_v_flag_cannot_be_set_simultaneously, p, size);
24922493
}
24932494
else {
24942495
regExpFlags |= flag;
2495-
checkRegularExpressionFlagAvailable(flag, p);
2496+
checkRegularExpressionFlagAvailability(flag, p, size);
24962497
}
24972498
}
2498-
p++;
2499+
p += size;
24992500
}
25002501
pos = p;
25012502
if (reportErrors) {
@@ -2763,23 +2764,24 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
27632764

27642765
function scanPatternModifiers(currFlags: RegularExpressionFlags): RegularExpressionFlags {
27652766
while (true) {
2766-
const ch = charCodeChecked(pos);
2767+
const ch = codePointChecked(pos);
27672768
if (ch === CharacterCodes.EOF || !isIdentifierPart(ch, languageVersion)) {
27682769
break;
27692770
}
2771+
const size = charSize(ch);
27702772
const flag = characterToRegularExpressionFlag(String.fromCharCode(ch));
27712773
if (flag === undefined) {
2772-
error(Diagnostics.Unknown_regular_expression_flag, pos, 1);
2774+
error(Diagnostics.Unknown_regular_expression_flag, pos, size);
27732775
}
27742776
else if (currFlags & flag) {
2775-
error(Diagnostics.Duplicate_regular_expression_flag, pos, 1);
2777+
error(Diagnostics.Duplicate_regular_expression_flag, pos, size);
27762778
}
27772779
else if (!(flag & RegularExpressionFlags.Modifiers)) {
2778-
error(Diagnostics.This_regular_expression_flag_cannot_be_toggled_within_a_subpattern, pos, 1);
2780+
error(Diagnostics.This_regular_expression_flag_cannot_be_toggled_within_a_subpattern, pos, size);
27792781
}
27802782
else {
27812783
currFlags |= flag;
2782-
checkRegularExpressionFlagAvailable(flag, pos);
2784+
checkRegularExpressionFlagAvailability(flag, pos, size);
27832785
}
27842786
pos++;
27852787
}
@@ -3494,10 +3496,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
34943496
});
34953497
}
34963498

3497-
function checkRegularExpressionFlagAvailable(flag: RegularExpressionFlags, pos: number) {
3499+
function checkRegularExpressionFlagAvailability(flag: RegularExpressionFlags, pos: number, size: number) {
34983500
const availableFrom = regExpFlagToFirstAvailableLanguageVersion.get(flag) as ScriptTarget | undefined;
34993501
if (availableFrom && languageVersion < availableFrom) {
3500-
error(Diagnostics.This_regular_expression_flag_is_only_available_when_targeting_0_or_later, pos, 1, getNameOfScriptTarget(availableFrom));
3502+
error(Diagnostics.This_regular_expression_flag_is_only_available_when_targeting_0_or_later, pos, size, getNameOfScriptTarget(availableFrom));
35013503
}
35023504
}
35033505

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
regularExpressionWithNonBMPFlags.ts(1,23): error TS1499: Unknown regular expression flag.
2+
regularExpressionWithNonBMPFlags.ts(1,25): error TS1499: Unknown regular expression flag.
3+
regularExpressionWithNonBMPFlags.ts(1,28): error TS1499: Unknown regular expression flag.
4+
regularExpressionWithNonBMPFlags.ts(1,41): error TS1499: Unknown regular expression flag.
5+
regularExpressionWithNonBMPFlags.ts(1,43): error TS1499: Unknown regular expression flag.
6+
regularExpressionWithNonBMPFlags.ts(1,45): error TS1499: Unknown regular expression flag.
7+
8+
9+
==== regularExpressionWithNonBMPFlags.ts (6 errors) ====
10+
const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;
11+
~~
12+
!!! error TS1499: Unknown regular expression flag.
13+
~~
14+
!!! error TS1499: Unknown regular expression flag.
15+
~~
16+
!!! error TS1499: Unknown regular expression flag.
17+
~~
18+
!!! error TS1499: Unknown regular expression flag.
19+
~~
20+
!!! error TS1499: Unknown regular expression flag.
21+
~~
22+
!!! error TS1499: Unknown regular expression flag.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//// [tests/cases/compiler/regularExpressionWithNonBMPFlags.ts] ////
2+
3+
//// [regularExpressionWithNonBMPFlags.ts]
4+
const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;
5+
6+
7+
//// [regularExpressionWithNonBMPFlags.js]
8+
const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//// [tests/cases/compiler/regularExpressionWithNonBMPFlags.ts] ////
2+
3+
=== regularExpressionWithNonBMPFlags.ts ===
4+
const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;
5+
>𝘳𝘦𝘨𝘦𝘹 : Symbol(𝘳𝘦𝘨𝘦𝘹, Decl(regularExpressionWithNonBMPFlags.ts, 0, 5))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//// [tests/cases/compiler/regularExpressionWithNonBMPFlags.ts] ////
2+
3+
=== regularExpressionWithNonBMPFlags.ts ===
4+
const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;
5+
>𝘳𝘦𝘨𝘦𝘹 : RegExp
6+
> : ^^^^^^
7+
>/(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶 : RegExp
8+
> : ^^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// @target: esnext
2+
3+
const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;

0 commit comments

Comments
 (0)