Skip to content

Commit e67692a

Browse files
Correct flags scanning for non-BMP characters
1 parent 76acd92 commit e67692a

6 files changed

+66
-15
lines changed

src/compiler/scanner.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,27 +2485,28 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
24852485
pos++;
24862486
let regExpFlags = RegularExpressionFlags.None;
24872487
while (pos < end) {
2488-
const ch = text.charCodeAt(pos);
2488+
const ch = codePointAt(text, pos);
24892489
if (!isIdentifierPart(ch, languageVersion)) {
24902490
break;
24912491
}
2492+
const size = charSize(ch);
24922493
if (reportErrors) {
2493-
const flag = characterToRegularExpressionFlag(String.fromCharCode(ch));
2494+
const flag = characterToRegularExpressionFlag(utf16EncodeAsString(ch));
24942495
if (flag === undefined) {
2495-
error(Diagnostics.Unknown_regular_expression_flag, pos, 1);
2496+
error(Diagnostics.Unknown_regular_expression_flag, pos, size);
24962497
}
24972498
else if (regExpFlags & flag) {
2498-
error(Diagnostics.Duplicate_regular_expression_flag, pos, 1);
2499+
error(Diagnostics.Duplicate_regular_expression_flag, pos, size);
24992500
}
25002501
else if (((regExpFlags | flag) & RegularExpressionFlags.UnicodeMode) === RegularExpressionFlags.UnicodeMode) {
2501-
error(Diagnostics.The_Unicode_u_flag_and_the_Unicode_Sets_v_flag_cannot_be_set_simultaneously, pos, 1);
2502+
error(Diagnostics.The_Unicode_u_flag_and_the_Unicode_Sets_v_flag_cannot_be_set_simultaneously, pos, size);
25022503
}
25032504
else {
25042505
regExpFlags |= flag;
2505-
checkRegularExpressionFlagAvailable(flag);
2506+
checkRegularExpressionFlagAvailability(flag);
25062507
}
25072508
}
2508-
pos++;
2509+
pos += size;
25092510
}
25102511
if (reportErrors) {
25112512
scanRange(startOfRegExpBody, endOfRegExpBody - startOfRegExpBody, () => {
@@ -2752,25 +2753,26 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
27522753

27532754
function scanPatternModifiers(currFlags: RegularExpressionFlags): RegularExpressionFlags {
27542755
while (pos < end) {
2755-
const ch = text.charCodeAt(pos);
2756+
const ch = codePointAt(text, pos);
27562757
if (!isIdentifierPart(ch, languageVersion)) {
27572758
break;
27582759
}
2759-
const flag = characterToRegularExpressionFlag(String.fromCharCode(ch));
2760+
const size = charSize(ch);
2761+
const flag = characterToRegularExpressionFlag(utf16EncodeAsString(ch));
27602762
if (flag === undefined) {
2761-
error(Diagnostics.Unknown_regular_expression_flag, pos, 1);
2763+
error(Diagnostics.Unknown_regular_expression_flag, pos, size);
27622764
}
27632765
else if (currFlags & flag) {
2764-
error(Diagnostics.Duplicate_regular_expression_flag, pos, 1);
2766+
error(Diagnostics.Duplicate_regular_expression_flag, pos, size);
27652767
}
27662768
else if (!(flag & RegularExpressionFlags.Modifiers)) {
2767-
error(Diagnostics.This_regular_expression_flag_cannot_be_toggled_within_a_subpattern, pos, 1);
2769+
error(Diagnostics.This_regular_expression_flag_cannot_be_toggled_within_a_subpattern, pos, size);
27682770
}
27692771
else {
27702772
currFlags |= flag;
2771-
checkRegularExpressionFlagAvailable(flag);
2773+
checkRegularExpressionFlagAvailability(flag);
27722774
}
2773-
pos++;
2775+
pos += size;
27742776
}
27752777
return currFlags;
27762778
}
@@ -3470,7 +3472,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean
34703472
});
34713473
}
34723474

3473-
function checkRegularExpressionFlagAvailable(flag: RegularExpressionFlags) {
3475+
function checkRegularExpressionFlagAvailability(flag: RegularExpressionFlags) {
34743476
const availableFrom = regExpFlagToFirstAvailableLanguageVersion.get(flag) as ScriptTarget | undefined;
34753477
if (availableFrom && languageVersion < availableFrom) {
34763478
error(Diagnostics.This_regular_expression_flag_is_only_available_when_targeting_0_or_later, pos, 1, getNameOfScriptTarget(availableFrom));
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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.
23+
Lines changed: 8 additions & 0 deletions
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 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [tests/cases/compiler/regularExpressionWithNonBMPFlags.ts] ////
2+
3+
=== regularExpressionWithNonBMPFlags.ts ===
4+
const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;
5+
>𝘳𝘦𝘨𝘦𝘹 : Symbol(𝘳𝘦𝘨𝘦𝘹, Decl(regularExpressionWithNonBMPFlags.ts, 0, 5))
6+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//// [tests/cases/compiler/regularExpressionWithNonBMPFlags.ts] ////
2+
3+
=== regularExpressionWithNonBMPFlags.ts ===
4+
const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;
5+
>𝘳𝘦𝘨𝘦𝘹 : RegExp
6+
> : ^^^^^^
7+
>/(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶 : RegExp
8+
> : ^^^^^^
9+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// @target: esnext
2+
3+
const 𝘳𝘦𝘨𝘦𝘹 = /(?𝘴𝘪-𝘮:^𝘧𝘰𝘰.)/𝘨𝘮𝘶;

0 commit comments

Comments
 (0)