From e04943898d938670eb2d71dbc49974b03851d449 Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Fri, 26 Apr 2024 05:43:01 +0800 Subject: [PATCH 01/10] Correct RegExp Behavior Related to Annex B --- src/compiler/scanner.ts | 28 +++++++++++++------ ...pressionScanning(target=es2015).errors.txt | 5 +--- ...rExpressionScanning(target=es5).errors.txt | 5 +--- ...pressionScanning(target=esnext).errors.txt | 5 +--- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index f8a8c52debf35..e673fe9112103 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -2638,6 +2638,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean const digitsStart = pos; scanDigits(); const min = tokenValue; + if (annexB && !min) { + isPreviousTermQuantifiable = true; + break; + } if (text.charCodeAt(pos) === CharacterCodes.comma) { pos++; scanDigits(); @@ -2647,25 +2651,28 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean error(Diagnostics.Incomplete_quantifier_Digit_expected, digitsStart, 0); } else { - if (unicodeMode) { - error(Diagnostics.Unexpected_0_Did_you_mean_to_escape_it_with_backslash, start, 1, String.fromCharCode(ch)); - } + error(Diagnostics.Unexpected_0_Did_you_mean_to_escape_it_with_backslash, start, 1, String.fromCharCode(ch)); isPreviousTermQuantifiable = true; break; } } - if (max && Number.parseInt(min) > Number.parseInt(max)) { + else if (max && Number.parseInt(min) > Number.parseInt(max) && (!annexB || text.charCodeAt(pos) === CharacterCodes.closeBrace)) { error(Diagnostics.Numbers_out_of_order_in_quantifier, digitsStart, pos - digitsStart); } } else if (!min) { - if (unicodeMode) { + if (!annexB) { error(Diagnostics.Unexpected_0_Did_you_mean_to_escape_it_with_backslash, start, 1, String.fromCharCode(ch)); } isPreviousTermQuantifiable = true; break; } - scanExpectedChar(CharacterCodes.closeBrace); + if (!annexB) { + scanExpectedChar(CharacterCodes.closeBrace); + } + else if (text.charCodeAt(pos) === CharacterCodes.closeBrace) { + pos++; + } pos--; // falls through case CharacterCodes.asterisk: @@ -2707,7 +2714,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean // Assume what starting from the character to be outside of the regex return; } - if (unicodeMode || ch === CharacterCodes.closeParen) { + if (!annexB || ch === CharacterCodes.closeParen) { error(Diagnostics.Unexpected_0_Did_you_mean_to_escape_it_with_backslash, pos, 1, String.fromCharCode(ch)); } pos++; @@ -2767,7 +2774,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean scanGroupName(/*isReference*/ true); scanExpectedChar(CharacterCodes.greaterThan); } - else if (unicodeMode) { + else { + // This actually is allowed in Annex B if there are no named capturing groups in the regex, + // but if we were going to slience these errors, we would have to record the positions of all '\k's + // and defer the errors until after the scanning to know if the regex has any named capturing groups. error(Diagnostics.k_must_be_followed_by_a_capturing_group_name_enclosed_in_angle_brackets, pos - 2, 2); } break; @@ -3390,7 +3400,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean error(Diagnostics.Unicode_property_value_expressions_are_only_available_when_the_Unicode_u_flag_or_the_Unicode_Sets_v_flag_is_set, start, pos - start); } } - else if (unicodeMode) { + else if (!annexB) { error(Diagnostics._0_must_be_followed_by_a_Unicode_property_value_expression_enclosed_in_braces, pos - 2, 2, String.fromCharCode(ch)); } return true; diff --git a/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt index c2a61dc5f1dcc..53799b79f78d5 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt @@ -38,7 +38,6 @@ regularExpressionScanning.ts(15,59): error TS1515: Named capturing groups with t regularExpressionScanning.ts(17,31): error TS1507: There is nothing available for repetition. regularExpressionScanning.ts(17,32): error TS1506: Numbers out of order in quantifier. regularExpressionScanning.ts(17,40): error TS1507: There is nothing available for repetition. -regularExpressionScanning.ts(17,61): error TS1505: Incomplete quantifier. Digit expected. regularExpressionScanning.ts(19,12): error TS1517: Range out of order in character class. regularExpressionScanning.ts(19,15): error TS1517: Range out of order in character class. regularExpressionScanning.ts(19,28): error TS1517: Range out of order in character class. @@ -203,7 +202,7 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag is only available when targeting 'esnext' or later. -==== regularExpressionScanning.ts (203 errors) ==== +==== regularExpressionScanning.ts (202 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -301,8 +300,6 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag !!! error TS1506: Numbers out of order in quantifier. ~~~~~~~~~ !!! error TS1507: There is nothing available for repetition. - -!!! error TS1505: Incomplete quantifier. Digit expected. // Character classes /[-A-Za-z-z-aZ-A\d_-\d-.-.\r-\n\w-\W]/, ~~~ diff --git a/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt index 83b45f8443492..082c0e5a35361 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt @@ -39,7 +39,6 @@ regularExpressionScanning.ts(15,59): error TS1515: Named capturing groups with t regularExpressionScanning.ts(17,31): error TS1507: There is nothing available for repetition. regularExpressionScanning.ts(17,32): error TS1506: Numbers out of order in quantifier. regularExpressionScanning.ts(17,40): error TS1507: There is nothing available for repetition. -regularExpressionScanning.ts(17,61): error TS1505: Incomplete quantifier. Digit expected. regularExpressionScanning.ts(19,12): error TS1517: Range out of order in character class. regularExpressionScanning.ts(19,15): error TS1517: Range out of order in character class. regularExpressionScanning.ts(19,28): error TS1517: Range out of order in character class. @@ -210,7 +209,7 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag is only available when targeting 'esnext' or later. -==== regularExpressionScanning.ts (210 errors) ==== +==== regularExpressionScanning.ts (209 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -310,8 +309,6 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag !!! error TS1506: Numbers out of order in quantifier. ~~~~~~~~~ !!! error TS1507: There is nothing available for repetition. - -!!! error TS1505: Incomplete quantifier. Digit expected. // Character classes /[-A-Za-z-z-aZ-A\d_-\d-.-.\r-\n\w-\W]/, ~~~ diff --git a/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt index 3fd6f79843695..3d0cd3f5d9c0c 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt @@ -26,7 +26,6 @@ regularExpressionScanning.ts(15,59): error TS1515: Named capturing groups with t regularExpressionScanning.ts(17,31): error TS1507: There is nothing available for repetition. regularExpressionScanning.ts(17,32): error TS1506: Numbers out of order in quantifier. regularExpressionScanning.ts(17,40): error TS1507: There is nothing available for repetition. -regularExpressionScanning.ts(17,61): error TS1505: Incomplete quantifier. Digit expected. regularExpressionScanning.ts(19,12): error TS1517: Range out of order in character class. regularExpressionScanning.ts(19,15): error TS1517: Range out of order in character class. regularExpressionScanning.ts(19,28): error TS1517: Range out of order in character class. @@ -177,7 +176,7 @@ regularExpressionScanning.ts(47,5): error TS1518: Anything that would possibly m regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly match more than a single character is invalid inside a negated character class. -==== regularExpressionScanning.ts (177 errors) ==== +==== regularExpressionScanning.ts (176 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -251,8 +250,6 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly !!! error TS1506: Numbers out of order in quantifier. ~~~~~~~~~ !!! error TS1507: There is nothing available for repetition. - -!!! error TS1505: Incomplete quantifier. Digit expected. // Character classes /[-A-Za-z-z-aZ-A\d_-\d-.-.\r-\n\w-\W]/, ~~~ From 358eb301a2158e206b7b7c39d07608669fdf162a Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Fri, 26 Apr 2024 05:58:36 +0800 Subject: [PATCH 02/10] Fix Comment --- src/compiler/scanner.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index e673fe9112103..ac66bc3ac8be4 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -2775,8 +2775,8 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean scanExpectedChar(CharacterCodes.greaterThan); } else { - // This actually is allowed in Annex B if there are no named capturing groups in the regex, - // but if we were going to slience these errors, we would have to record the positions of all '\k's + // This is actually allowed in Annex B if there are no named capturing groups in the regex, + // but if we were going to suppress these errors, we would have to record the positions of all '\k's // and defer the errors until after the scanning to know if the regex has any named capturing groups. error(Diagnostics.k_must_be_followed_by_a_capturing_group_name_enclosed_in_angle_brackets, pos - 2, 2); } From 8facb0a78691bc92e1bce34aec287037557b07f0 Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Sat, 27 Apr 2024 15:21:01 +0800 Subject: [PATCH 03/10] Correct Quantifiability of `{1` in Annex B --- src/compiler/scanner.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index ac66bc3ac8be4..4e86f7e79ba37 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -2667,13 +2667,16 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean isPreviousTermQuantifiable = true; break; } - if (!annexB) { - scanExpectedChar(CharacterCodes.closeBrace); - } - else if (text.charCodeAt(pos) === CharacterCodes.closeBrace) { - pos++; + if (text.charCodeAt(pos) !== CharacterCodes.closeBrace) { + if (annexB) { + isPreviousTermQuantifiable = true; + break; + } + else { + error(Diagnostics._0_expected, pos, 0, String.fromCharCode(CharacterCodes.closeBrace)); + pos--; + } } - pos--; // falls through case CharacterCodes.asterisk: case CharacterCodes.plus: From f5c0b60edef1216a1e50f75b6c0a62d9ec9d0c71 Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Sat, 27 Apr 2024 16:19:37 +0800 Subject: [PATCH 04/10] `\c` is an Annex B thing --- src/compiler/scanner.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 4e86f7e79ba37..fcfb171ec0bb6 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -2830,10 +2830,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean pos++; return String.fromCharCode(ch & 0x1f); } - if (unicodeMode) { + if (!annexB) { error(Diagnostics.c_must_be_followed_by_an_ASCII_letter, pos - 2, 2); } - else if (atomEscape && annexB) { + else if (atomEscape) { // Annex B treats // // ExtendedAtom : `\` [lookahead = `c`] @@ -3403,7 +3403,11 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean error(Diagnostics.Unicode_property_value_expressions_are_only_available_when_the_Unicode_u_flag_or_the_Unicode_Sets_v_flag_is_set, start, pos - start); } } - else if (!annexB) { + else if (annexB) { + pos--; + return false; + } + else { error(Diagnostics._0_must_be_followed_by_a_Unicode_property_value_expression_enclosed_in_braces, pos - 2, 2, String.fromCharCode(ch)); } return true; From cff993f22418041690c1236c163ddf04002a2709 Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Sat, 27 Apr 2024 16:34:51 +0800 Subject: [PATCH 05/10] Add Tests --- .../regularExpressionAnnexB.errors.txt | 272 ++++++++++++++++++ .../reference/regularExpressionAnnexB.js | 89 ++++++ .../reference/regularExpressionAnnexB.symbols | 53 ++++ .../reference/regularExpressionAnnexB.types | 157 ++++++++++ .../cases/compiler/regularExpressionAnnexB.ts | 45 +++ 5 files changed, 616 insertions(+) create mode 100644 tests/baselines/reference/regularExpressionAnnexB.errors.txt create mode 100644 tests/baselines/reference/regularExpressionAnnexB.js create mode 100644 tests/baselines/reference/regularExpressionAnnexB.symbols create mode 100644 tests/baselines/reference/regularExpressionAnnexB.types create mode 100644 tests/cases/compiler/regularExpressionAnnexB.ts diff --git a/tests/baselines/reference/regularExpressionAnnexB.errors.txt b/tests/baselines/reference/regularExpressionAnnexB.errors.txt new file mode 100644 index 0000000000000..371bf65ac1fc5 --- /dev/null +++ b/tests/baselines/reference/regularExpressionAnnexB.errors.txt @@ -0,0 +1,272 @@ +regularExpressionAnnexB.ts(2,8): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(2,12): error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. +regularExpressionAnnexB.ts(2,22): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(2,28): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(3,9): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(3,23): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(3,29): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(7,4): error TS1535: This character cannot be escaped in a regular expression. +regularExpressionAnnexB.ts(7,8): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(7,10): error TS1512: '\c' must be followed by an ASCII letter. +regularExpressionAnnexB.ts(7,12): error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. +regularExpressionAnnexB.ts(7,14): error TS1535: This character cannot be escaped in a regular expression. +regularExpressionAnnexB.ts(7,18): error TS1535: This character cannot be escaped in a regular expression. +regularExpressionAnnexB.ts(7,22): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(7,24): error TS1535: This character cannot be escaped in a regular expression. +regularExpressionAnnexB.ts(7,28): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(7,30): error TS1531: '\p' must be followed by a Unicode property value expression enclosed in braces. +regularExpressionAnnexB.ts(8,5): error TS1535: This character cannot be escaped in a regular expression. +regularExpressionAnnexB.ts(8,9): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(8,11): error TS1512: '\c' must be followed by an ASCII letter. +regularExpressionAnnexB.ts(8,13): error TS1535: This character cannot be escaped in a regular expression. +regularExpressionAnnexB.ts(8,15): error TS1535: This character cannot be escaped in a regular expression. +regularExpressionAnnexB.ts(8,19): error TS1535: This character cannot be escaped in a regular expression. +regularExpressionAnnexB.ts(8,23): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(8,25): error TS1535: This character cannot be escaped in a regular expression. +regularExpressionAnnexB.ts(8,29): error TS1125: Hexadecimal digit expected. +regularExpressionAnnexB.ts(8,31): error TS1531: '\p' must be followed by a Unicode property value expression enclosed in braces. +regularExpressionAnnexB.ts(9,4): error TS1531: '\P' must be followed by a Unicode property value expression enclosed in braces. +regularExpressionAnnexB.ts(9,7): error TS1531: '\P' must be followed by a Unicode property value expression enclosed in braces. +regularExpressionAnnexB.ts(9,9): error TS1516: A character class range must not be bounded by another character class. +regularExpressionAnnexB.ts(23,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(23,8): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(24,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(24,9): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(25,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(25,10): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(26,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(26,5): error TS1506: Numbers out of order in quantifier. +regularExpressionAnnexB.ts(26,10): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(29,4): error TS1508: Unexpected '{'. Did you mean to escape it with backslash? +regularExpressionAnnexB.ts(30,4): error TS1508: Unexpected '{'. Did you mean to escape it with backslash? +regularExpressionAnnexB.ts(31,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(31,5): error TS1505: Incomplete quantifier. Digit expected. +regularExpressionAnnexB.ts(31,7): error TS1005: '}' expected. +regularExpressionAnnexB.ts(31,8): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(32,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(32,6): error TS1005: '}' expected. +regularExpressionAnnexB.ts(32,7): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(33,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(33,7): error TS1005: '}' expected. +regularExpressionAnnexB.ts(33,8): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(34,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(34,8): error TS1005: '}' expected. +regularExpressionAnnexB.ts(34,9): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(35,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(35,5): error TS1506: Numbers out of order in quantifier. +regularExpressionAnnexB.ts(35,8): error TS1005: '}' expected. +regularExpressionAnnexB.ts(35,9): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(36,4): error TS1508: Unexpected '{'. Did you mean to escape it with backslash? +regularExpressionAnnexB.ts(36,5): error TS1508: Unexpected '}'. Did you mean to escape it with backslash? +regularExpressionAnnexB.ts(37,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(37,5): error TS1505: Incomplete quantifier. Digit expected. +regularExpressionAnnexB.ts(37,8): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(38,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(38,5): error TS1505: Incomplete quantifier. Digit expected. +regularExpressionAnnexB.ts(38,9): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(39,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(39,8): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(40,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(40,9): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(41,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(41,10): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(42,4): error TS1507: There is nothing available for repetition. +regularExpressionAnnexB.ts(42,5): error TS1506: Numbers out of order in quantifier. +regularExpressionAnnexB.ts(42,10): error TS1507: There is nothing available for repetition. + + +==== regularExpressionAnnexB.ts (75 errors) ==== + const regexes: RegExp[] = [ + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/, + +!!! error TS1125: Hexadecimal digit expected. + ~~ +!!! error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. + +!!! error TS1125: Hexadecimal digit expected. + +!!! error TS1125: Hexadecimal digit expected. + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/, + +!!! error TS1125: Hexadecimal digit expected. + +!!! error TS1125: Hexadecimal digit expected. + +!!! error TS1125: Hexadecimal digit expected. + /\P[\P\w-_]/, + + // Compare to + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/u, + ~~ +!!! error TS1535: This character cannot be escaped in a regular expression. + +!!! error TS1125: Hexadecimal digit expected. + ~~ +!!! error TS1512: '\c' must be followed by an ASCII letter. + ~~ +!!! error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. + ~~ +!!! error TS1535: This character cannot be escaped in a regular expression. + ~~ +!!! error TS1535: This character cannot be escaped in a regular expression. + +!!! error TS1125: Hexadecimal digit expected. + ~~ +!!! error TS1535: This character cannot be escaped in a regular expression. + +!!! error TS1125: Hexadecimal digit expected. + ~~ +!!! error TS1531: '\p' must be followed by a Unicode property value expression enclosed in braces. + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/u, + ~~ +!!! error TS1535: This character cannot be escaped in a regular expression. + +!!! error TS1125: Hexadecimal digit expected. + ~~ +!!! error TS1512: '\c' must be followed by an ASCII letter. + ~~ +!!! error TS1535: This character cannot be escaped in a regular expression. + ~~ +!!! error TS1535: This character cannot be escaped in a regular expression. + ~~ +!!! error TS1535: This character cannot be escaped in a regular expression. + +!!! error TS1125: Hexadecimal digit expected. + ~~ +!!! error TS1535: This character cannot be escaped in a regular expression. + +!!! error TS1125: Hexadecimal digit expected. + ~~ +!!! error TS1531: '\p' must be followed by a Unicode property value expression enclosed in braces. + /\P[\P\w-_]/u, + ~~ +!!! error TS1531: '\P' must be followed by a Unicode property value expression enclosed in braces. + ~~ +!!! error TS1531: '\P' must be followed by a Unicode property value expression enclosed in braces. + ~~ +!!! error TS1516: A character class range must not be bounded by another character class. + ]; + + const regexesWithBraces: RegExp[] = [ + /{??/, + /{,??/, + /{,1??/, + /{1??/, + /{1,??/, + /{1,2??/, + /{2,1??/, + /{}??/, + /{,}??/, + /{,1}??/, + /{1}??/, + ~~~~ +!!! error TS1507: There is nothing available for repetition. + ~ +!!! error TS1507: There is nothing available for repetition. + /{1,}??/, + ~~~~~ +!!! error TS1507: There is nothing available for repetition. + ~ +!!! error TS1507: There is nothing available for repetition. + /{1,2}??/, + ~~~~~~ +!!! error TS1507: There is nothing available for repetition. + ~ +!!! error TS1507: There is nothing available for repetition. + /{2,1}??/, + ~~~~~~ +!!! error TS1507: There is nothing available for repetition. + ~~~ +!!! error TS1506: Numbers out of order in quantifier. + ~ +!!! error TS1507: There is nothing available for repetition. + + // Compare to + /{??/u, + ~ +!!! error TS1508: Unexpected '{'. Did you mean to escape it with backslash? + /{,??/u, + ~ +!!! error TS1508: Unexpected '{'. Did you mean to escape it with backslash? + /{,1??/u, + ~~~~ +!!! error TS1507: There is nothing available for repetition. + +!!! error TS1505: Incomplete quantifier. Digit expected. + +!!! error TS1005: '}' expected. + ~ +!!! error TS1507: There is nothing available for repetition. + /{1??/u, + ~~~ +!!! error TS1507: There is nothing available for repetition. + +!!! error TS1005: '}' expected. + ~ +!!! error TS1507: There is nothing available for repetition. + /{1,??/u, + ~~~~ +!!! error TS1507: There is nothing available for repetition. + +!!! error TS1005: '}' expected. + ~ +!!! error TS1507: There is nothing available for repetition. + /{1,2??/u, + ~~~~~ +!!! error TS1507: There is nothing available for repetition. + +!!! error TS1005: '}' expected. + ~ +!!! error TS1507: There is nothing available for repetition. + /{2,1??/u, + ~~~~~ +!!! error TS1507: There is nothing available for repetition. + ~~~ +!!! error TS1506: Numbers out of order in quantifier. + +!!! error TS1005: '}' expected. + ~ +!!! error TS1507: There is nothing available for repetition. + /{}??/u, + ~ +!!! error TS1508: Unexpected '{'. Did you mean to escape it with backslash? + ~ +!!! error TS1508: Unexpected '}'. Did you mean to escape it with backslash? + /{,}??/u, + ~~~~ +!!! error TS1507: There is nothing available for repetition. + +!!! error TS1505: Incomplete quantifier. Digit expected. + ~ +!!! error TS1507: There is nothing available for repetition. + /{,1}??/u, + ~~~~~ +!!! error TS1507: There is nothing available for repetition. + +!!! error TS1505: Incomplete quantifier. Digit expected. + ~ +!!! error TS1507: There is nothing available for repetition. + /{1}??/u, + ~~~~ +!!! error TS1507: There is nothing available for repetition. + ~ +!!! error TS1507: There is nothing available for repetition. + /{1,}??/u, + ~~~~~ +!!! error TS1507: There is nothing available for repetition. + ~ +!!! error TS1507: There is nothing available for repetition. + /{1,2}??/u, + ~~~~~~ +!!! error TS1507: There is nothing available for repetition. + ~ +!!! error TS1507: There is nothing available for repetition. + /{2,1}??/u, + ~~~~~~ +!!! error TS1507: There is nothing available for repetition. + ~~~ +!!! error TS1506: Numbers out of order in quantifier. + ~ +!!! error TS1507: There is nothing available for repetition. + ]; + \ No newline at end of file diff --git a/tests/baselines/reference/regularExpressionAnnexB.js b/tests/baselines/reference/regularExpressionAnnexB.js new file mode 100644 index 0000000000000..c1ee8d1343858 --- /dev/null +++ b/tests/baselines/reference/regularExpressionAnnexB.js @@ -0,0 +1,89 @@ +//// [tests/cases/compiler/regularExpressionAnnexB.ts] //// + +//// [regularExpressionAnnexB.ts] +const regexes: RegExp[] = [ + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/, + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/, + /\P[\P\w-_]/, + + // Compare to + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/u, + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/u, + /\P[\P\w-_]/u, +]; + +const regexesWithBraces: RegExp[] = [ + /{??/, + /{,??/, + /{,1??/, + /{1??/, + /{1,??/, + /{1,2??/, + /{2,1??/, + /{}??/, + /{,}??/, + /{,1}??/, + /{1}??/, + /{1,}??/, + /{1,2}??/, + /{2,1}??/, + + // Compare to + /{??/u, + /{,??/u, + /{,1??/u, + /{1??/u, + /{1,??/u, + /{1,2??/u, + /{2,1??/u, + /{}??/u, + /{,}??/u, + /{,1}??/u, + /{1}??/u, + /{1,}??/u, + /{1,2}??/u, + /{2,1}??/u, +]; + + +//// [regularExpressionAnnexB.js] +const regexes = [ + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/, + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/, + /\P[\P\w-_]/, + // Compare to + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/u, + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/u, + /\P[\P\w-_]/u, +]; +const regexesWithBraces = [ + /{??/, + /{,??/, + /{,1??/, + /{1??/, + /{1,??/, + /{1,2??/, + /{2,1??/, + /{}??/, + /{,}??/, + /{,1}??/, + /{1}??/, + /{1,}??/, + /{1,2}??/, + /{2,1}??/, + // Compare to + /{??/u, + /{,??/u, + /{,1??/u, + /{1??/u, + /{1,??/u, + /{1,2??/u, + /{2,1??/u, + /{}??/u, + /{,}??/u, + /{,1}??/u, + /{1}??/u, + /{1,}??/u, + /{1,2}??/u, + /{2,1}??/u, +]; diff --git a/tests/baselines/reference/regularExpressionAnnexB.symbols b/tests/baselines/reference/regularExpressionAnnexB.symbols new file mode 100644 index 0000000000000..78ac17b509968 --- /dev/null +++ b/tests/baselines/reference/regularExpressionAnnexB.symbols @@ -0,0 +1,53 @@ +//// [tests/cases/compiler/regularExpressionAnnexB.ts] //// + +=== regularExpressionAnnexB.ts === +const regexes: RegExp[] = [ +>regexes : Symbol(regexes, Decl(regularExpressionAnnexB.ts, 0, 5)) +>RegExp : Symbol(RegExp, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.regexp.d.ts, --, --) ... and 3 more) + + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/, + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/, + /\P[\P\w-_]/, + + // Compare to + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/u, + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/u, + /\P[\P\w-_]/u, +]; + +const regexesWithBraces: RegExp[] = [ +>regexesWithBraces : Symbol(regexesWithBraces, Decl(regularExpressionAnnexB.ts, 11, 5)) +>RegExp : Symbol(RegExp, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.regexp.d.ts, --, --) ... and 3 more) + + /{??/, + /{,??/, + /{,1??/, + /{1??/, + /{1,??/, + /{1,2??/, + /{2,1??/, + /{}??/, + /{,}??/, + /{,1}??/, + /{1}??/, + /{1,}??/, + /{1,2}??/, + /{2,1}??/, + + // Compare to + /{??/u, + /{,??/u, + /{,1??/u, + /{1??/u, + /{1,??/u, + /{1,2??/u, + /{2,1??/u, + /{}??/u, + /{,}??/u, + /{,1}??/u, + /{1}??/u, + /{1,}??/u, + /{1,2}??/u, + /{2,1}??/u, +]; + diff --git a/tests/baselines/reference/regularExpressionAnnexB.types b/tests/baselines/reference/regularExpressionAnnexB.types new file mode 100644 index 0000000000000..68460384b3808 --- /dev/null +++ b/tests/baselines/reference/regularExpressionAnnexB.types @@ -0,0 +1,157 @@ +//// [tests/cases/compiler/regularExpressionAnnexB.ts] //// + +=== regularExpressionAnnexB.ts === +const regexes: RegExp[] = [ +>regexes : RegExp[] +> : ^^^^^^^^ +>[ /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/, /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/, /\P[\P\w-_]/, // Compare to /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/u, /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/u, /\P[\P\w-_]/u,] : RegExp[] +> : ^^^^^^^^ + + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/, +>/\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/ : RegExp +> : ^^^^^^ + + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/, +>/[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/ : RegExp +> : ^^^^^^ + + /\P[\P\w-_]/, +>/\P[\P\w-_]/ : RegExp +> : ^^^^^^ + + // Compare to + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/u, +>/\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/u : RegExp +> : ^^^^^^ + + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/u, +>/[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/u : RegExp +> : ^^^^^^ + + /\P[\P\w-_]/u, +>/\P[\P\w-_]/u : RegExp +> : ^^^^^^ + +]; + +const regexesWithBraces: RegExp[] = [ +>regexesWithBraces : RegExp[] +> : ^^^^^^^^ +>[ /{??/, /{,??/, /{,1??/, /{1??/, /{1,??/, /{1,2??/, /{2,1??/, /{}??/, /{,}??/, /{,1}??/, /{1}??/, /{1,}??/, /{1,2}??/, /{2,1}??/, // Compare to /{??/u, /{,??/u, /{,1??/u, /{1??/u, /{1,??/u, /{1,2??/u, /{2,1??/u, /{}??/u, /{,}??/u, /{,1}??/u, /{1}??/u, /{1,}??/u, /{1,2}??/u, /{2,1}??/u,] : RegExp[] +> : ^^^^^^^^ + + /{??/, +>/{??/ : RegExp +> : ^^^^^^ + + /{,??/, +>/{,??/ : RegExp +> : ^^^^^^ + + /{,1??/, +>/{,1??/ : RegExp +> : ^^^^^^ + + /{1??/, +>/{1??/ : RegExp +> : ^^^^^^ + + /{1,??/, +>/{1,??/ : RegExp +> : ^^^^^^ + + /{1,2??/, +>/{1,2??/ : RegExp +> : ^^^^^^ + + /{2,1??/, +>/{2,1??/ : RegExp +> : ^^^^^^ + + /{}??/, +>/{}??/ : RegExp +> : ^^^^^^ + + /{,}??/, +>/{,}??/ : RegExp +> : ^^^^^^ + + /{,1}??/, +>/{,1}??/ : RegExp +> : ^^^^^^ + + /{1}??/, +>/{1}??/ : RegExp +> : ^^^^^^ + + /{1,}??/, +>/{1,}??/ : RegExp +> : ^^^^^^ + + /{1,2}??/, +>/{1,2}??/ : RegExp +> : ^^^^^^ + + /{2,1}??/, +>/{2,1}??/ : RegExp +> : ^^^^^^ + + // Compare to + /{??/u, +>/{??/u : RegExp +> : ^^^^^^ + + /{,??/u, +>/{,??/u : RegExp +> : ^^^^^^ + + /{,1??/u, +>/{,1??/u : RegExp +> : ^^^^^^ + + /{1??/u, +>/{1??/u : RegExp +> : ^^^^^^ + + /{1,??/u, +>/{1,??/u : RegExp +> : ^^^^^^ + + /{1,2??/u, +>/{1,2??/u : RegExp +> : ^^^^^^ + + /{2,1??/u, +>/{2,1??/u : RegExp +> : ^^^^^^ + + /{}??/u, +>/{}??/u : RegExp +> : ^^^^^^ + + /{,}??/u, +>/{,}??/u : RegExp +> : ^^^^^^ + + /{,1}??/u, +>/{,1}??/u : RegExp +> : ^^^^^^ + + /{1}??/u, +>/{1}??/u : RegExp +> : ^^^^^^ + + /{1,}??/u, +>/{1,}??/u : RegExp +> : ^^^^^^ + + /{1,2}??/u, +>/{1,2}??/u : RegExp +> : ^^^^^^ + + /{2,1}??/u, +>/{2,1}??/u : RegExp +> : ^^^^^^ + +]; + diff --git a/tests/cases/compiler/regularExpressionAnnexB.ts b/tests/cases/compiler/regularExpressionAnnexB.ts new file mode 100644 index 0000000000000..785fe22598b72 --- /dev/null +++ b/tests/cases/compiler/regularExpressionAnnexB.ts @@ -0,0 +1,45 @@ +// @target: esnext + +const regexes: RegExp[] = [ + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/, + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/, + /\P[\P\w-_]/, + + // Compare to + /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/u, + /[\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s]/u, + /\P[\P\w-_]/u, +]; + +const regexesWithBraces: RegExp[] = [ + /{??/, + /{,??/, + /{,1??/, + /{1??/, + /{1,??/, + /{1,2??/, + /{2,1??/, + /{}??/, + /{,}??/, + /{,1}??/, + /{1}??/, + /{1,}??/, + /{1,2}??/, + /{2,1}??/, + + // Compare to + /{??/u, + /{,??/u, + /{,1??/u, + /{1??/u, + /{1,??/u, + /{1,2??/u, + /{2,1??/u, + /{}??/u, + /{,}??/u, + /{,1}??/u, + /{1}??/u, + /{1,}??/u, + /{1,2}??/u, + /{2,1}??/u, +]; From 2e62d25d1a9c6158379c9b9daea2ed306ecbb103 Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Wed, 22 May 2024 07:09:23 +0800 Subject: [PATCH 06/10] Apply Suggested Changes --- src/compiler/scanner.ts | 67 ++++++++++--------- .../regularExpressionAnnexB.errors.txt | 8 +-- ...pressionScanning(target=es2015).errors.txt | 17 ++++- ...rExpressionScanning(target=es5).errors.txt | 17 ++++- ...pressionScanning(target=esnext).errors.txt | 17 ++++- 5 files changed, 84 insertions(+), 42 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index f23c2af6d3a9c..ba6b438ee5f83 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1556,9 +1556,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean tokenFlags |= TokenFlags.ContainsInvalidEscape; if (isRegularExpression || shouldEmitInvalidEscapeError) { const code = parseInt(text.substring(start + 1, pos), 8); - if (isRegularExpression !== "annex-b") { - error(Diagnostics.Octal_escape_sequences_are_not_allowed_Use_the_syntax_0, start, pos - start, "\\x" + code.toString(16).padStart(2, "0")); - } + error(Diagnostics.Octal_escape_sequences_are_not_allowed_Use_the_syntax_0, start, pos - start, "\\x" + code.toString(16).padStart(2, "0")); return String.fromCharCode(code); } return text.substring(start, pos); @@ -2426,6 +2424,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean // Quickly get to the end of regex such that we know the flags let p = tokenStart + 1; let inEscape = false; + let namedCaptureGroups = false; // Although nested character classes are allowed in Unicode Sets mode, // an unescaped slash is nevertheless invalid even in a character class in Unicode mode. // Additionally, parsing nested character classes will misinterpret regexes like `/[[]/` @@ -2469,6 +2468,15 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean else if (ch === CharacterCodes.closeBracket) { inCharacterClass = false; } + else if ( + ch === CharacterCodes.openParen + && charCodeUnchecked(p + 1) === CharacterCodes.question + && charCodeUnchecked(p + 2) === CharacterCodes.lessThan + && charCodeUnchecked(p + 3) !== CharacterCodes.equals + && charCodeUnchecked(p + 3) !== CharacterCodes.exclamation + ) { + namedCaptureGroups = true; + } p++; } const isUnterminated = !!(tokenFlags & TokenFlags.Unterminated); @@ -2505,7 +2513,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean const saveEnd = end; pos = tokenStart + 1; end = endOfBody; - scanRegularExpressionWorker(regExpFlags, isUnterminated, /*annexB*/ true); + scanRegularExpressionWorker(regExpFlags, isUnterminated, /*annexB*/ true, namedCaptureGroups); tokenStart = saveTokenStart; tokenFlags = saveTokenFlags; pos = savePos; @@ -2517,7 +2525,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean return token; } - function scanRegularExpressionWorker(regExpFlags: RegularExpressionFlags, isUnterminated: boolean, annexB: boolean) { + function scanRegularExpressionWorker(regExpFlags: RegularExpressionFlags, isUnterminated: boolean, annexB: boolean, namedCaptureGroups: boolean) { // Why var? It avoids TDZ checks in the runtime which can be costly. // See: https://github.com/microsoft/TypeScript/issues/52924 /* eslint-disable no-var */ @@ -2527,10 +2535,8 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean /** Grammar parameter */ var unicodeMode = !!(regExpFlags & RegularExpressionFlags.UnicodeMode); - if (unicodeMode) { - // Annex B treats any unicode mode as the strict syntax. - annexB = false; - } + // Annex B treats any unicode mode as the strict syntax. + var anyUnicodeModeOrNonAnnexB = unicodeMode || !annexB; /** @see {scanClassSetExpression} */ var mayContainStrings = false; @@ -2626,7 +2632,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean case CharacterCodes.exclamation: pos++; // In Annex B, `(?=Disjunction)` and `(?!Disjunction)` are quantifiable - isPreviousTermQuantifiable = annexB; + isPreviousTermQuantifiable = !anyUnicodeModeOrNonAnnexB; break; case CharacterCodes.lessThan: const groupNameStart = pos; @@ -2675,7 +2681,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean const digitsStart = pos; scanDigits(); const min = tokenValue; - if (annexB && !min) { + if (!anyUnicodeModeOrNonAnnexB && !min) { isPreviousTermQuantifiable = true; break; } @@ -2693,26 +2699,26 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean break; } } - else if (max && Number.parseInt(min) > Number.parseInt(max) && (!annexB || text.charCodeAt(pos) === CharacterCodes.closeBrace)) { + else if (max && Number.parseInt(min) > Number.parseInt(max) && (anyUnicodeModeOrNonAnnexB || text.charCodeAt(pos) === CharacterCodes.closeBrace)) { error(Diagnostics.Numbers_out_of_order_in_quantifier, digitsStart, pos - digitsStart); } } else if (!min) { - if (!annexB) { + if (anyUnicodeModeOrNonAnnexB) { error(Diagnostics.Unexpected_0_Did_you_mean_to_escape_it_with_backslash, start, 1, String.fromCharCode(ch)); } isPreviousTermQuantifiable = true; break; } if (charCodeChecked(pos) !== CharacterCodes.closeBrace) { - if (annexB) { - isPreviousTermQuantifiable = true; - break; - } - else { + if (anyUnicodeModeOrNonAnnexB) { error(Diagnostics._0_expected, pos, 0, String.fromCharCode(CharacterCodes.closeBrace)); pos--; } + else { + isPreviousTermQuantifiable = true; + break; + } } // falls through case CharacterCodes.asterisk: @@ -2754,7 +2760,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean // Assume what starting from the character to be outside of the regex return; } - if (!annexB || ch === CharacterCodes.closeParen) { + if (anyUnicodeModeOrNonAnnexB || ch === CharacterCodes.closeParen) { error(Diagnostics.Unexpected_0_Did_you_mean_to_escape_it_with_backslash, pos, 1, String.fromCharCode(ch)); } pos++; @@ -2811,10 +2817,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean scanGroupName(/*isReference*/ true); scanExpectedChar(CharacterCodes.greaterThan); } - else { - // This is actually allowed in Annex B if there are no named capturing groups in the regex, - // but if we were going to suppress these errors, we would have to record the positions of all '\k's - // and defer the errors until after the scanning to know if the regex has any named capturing groups. + else if (namedCaptureGroups) { error(Diagnostics.k_must_be_followed_by_a_capturing_group_name_enclosed_in_angle_brackets, pos - 2, 2); } break; @@ -2864,7 +2867,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean pos++; return String.fromCharCode(ch & 0x1f); } - if (!annexB) { + if (anyUnicodeModeOrNonAnnexB) { error(Diagnostics.c_must_be_followed_by_an_ASCII_letter, pos - 2, 2); } else if (atomEscape) { @@ -2900,7 +2903,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean return "\\"; } pos--; - return scanEscapeSequence(/*shouldEmitInvalidEscapeError*/ unicodeMode, /*isRegularExpression*/ annexB ? "annex-b" : true); + return scanEscapeSequence(/*shouldEmitInvalidEscapeError*/ unicodeMode, /*isRegularExpression*/ anyUnicodeModeOrNonAnnexB || "annex-b"); } } @@ -2949,12 +2952,12 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean if (isClassContentExit(ch)) { return; } - if (!minCharacter && !annexB) { + if (!minCharacter && anyUnicodeModeOrNonAnnexB) { error(Diagnostics.A_character_class_range_must_not_be_bounded_by_another_character_class, minStart, pos - 1 - minStart); } const maxStart = pos; const maxCharacter = scanClassAtom(); - if (!maxCharacter && !annexB) { + if (!maxCharacter && anyUnicodeModeOrNonAnnexB) { error(Diagnostics.A_character_class_range_must_not_be_bounded_by_another_character_class, maxStart, pos - maxStart); continue; } @@ -3450,12 +3453,12 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean error(Diagnostics.Unicode_property_value_expressions_are_only_available_when_the_Unicode_u_flag_or_the_Unicode_Sets_v_flag_is_set, start, pos - start); } } - else if (annexB) { - pos--; - return false; + else if (anyUnicodeModeOrNonAnnexB) { + error(Diagnostics._0_must_be_followed_by_a_Unicode_property_value_expression_enclosed_in_braces, pos - 2, 2, String.fromCharCode(ch)); } else { - error(Diagnostics._0_must_be_followed_by_a_Unicode_property_value_expression_enclosed_in_braces, pos - 2, 2, String.fromCharCode(ch)); + pos--; + return false; } return true; } @@ -3500,7 +3503,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean forEach(decimalEscapes, escape => { // in AnnexB, if a DecimalEscape is greater than the number of capturing groups then it is treated as // either a LegacyOctalEscapeSequence or IdentityEscape - if (!annexB && escape.value > numberOfCapturingGroups) { + if (anyUnicodeModeOrNonAnnexB && escape.value > numberOfCapturingGroups) { if (numberOfCapturingGroups) { error(Diagnostics.This_backreference_refers_to_a_group_that_does_not_exist_There_are_only_0_capturing_groups_in_this_regular_expression, escape.pos, escape.end - escape.pos, numberOfCapturingGroups); } diff --git a/tests/baselines/reference/regularExpressionAnnexB.errors.txt b/tests/baselines/reference/regularExpressionAnnexB.errors.txt index 371bf65ac1fc5..26788ab87eb68 100644 --- a/tests/baselines/reference/regularExpressionAnnexB.errors.txt +++ b/tests/baselines/reference/regularExpressionAnnexB.errors.txt @@ -1,5 +1,4 @@ regularExpressionAnnexB.ts(2,8): error TS1125: Hexadecimal digit expected. -regularExpressionAnnexB.ts(2,12): error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. regularExpressionAnnexB.ts(2,22): error TS1125: Hexadecimal digit expected. regularExpressionAnnexB.ts(2,28): error TS1125: Hexadecimal digit expected. regularExpressionAnnexB.ts(3,9): error TS1125: Hexadecimal digit expected. @@ -8,7 +7,6 @@ regularExpressionAnnexB.ts(3,29): error TS1125: Hexadecimal digit expected. regularExpressionAnnexB.ts(7,4): error TS1535: This character cannot be escaped in a regular expression. regularExpressionAnnexB.ts(7,8): error TS1125: Hexadecimal digit expected. regularExpressionAnnexB.ts(7,10): error TS1512: '\c' must be followed by an ASCII letter. -regularExpressionAnnexB.ts(7,12): error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. regularExpressionAnnexB.ts(7,14): error TS1535: This character cannot be escaped in a regular expression. regularExpressionAnnexB.ts(7,18): error TS1535: This character cannot be escaped in a regular expression. regularExpressionAnnexB.ts(7,22): error TS1125: Hexadecimal digit expected. @@ -75,13 +73,11 @@ regularExpressionAnnexB.ts(42,5): error TS1506: Numbers out of order in quantifi regularExpressionAnnexB.ts(42,10): error TS1507: There is nothing available for repetition. -==== regularExpressionAnnexB.ts (75 errors) ==== +==== regularExpressionAnnexB.ts (73 errors) ==== const regexes: RegExp[] = [ /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/, !!! error TS1125: Hexadecimal digit expected. - ~~ -!!! error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. !!! error TS1125: Hexadecimal digit expected. @@ -103,8 +99,6 @@ regularExpressionAnnexB.ts(42,10): error TS1507: There is nothing available for !!! error TS1125: Hexadecimal digit expected. ~~ !!! error TS1512: '\c' must be followed by an ASCII letter. - ~~ -!!! error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. ~~ !!! error TS1535: This character cannot be escaped in a regular expression. ~~ diff --git a/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt index 0762f98712041..19b29fa5c2b67 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt @@ -17,6 +17,11 @@ regularExpressionScanning.ts(5,6): error TS1499: Unknown regular expression flag regularExpressionScanning.ts(5,7): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,10): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,11): error TS1500: Duplicate regular expression flag. +regularExpressionScanning.ts(12,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(12,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(12,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. +regularExpressionScanning.ts(12,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(12,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. regularExpressionScanning.ts(13,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(13,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. regularExpressionScanning.ts(13,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. @@ -202,7 +207,7 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag is only available when targeting 'esnext' or later. -==== regularExpressionScanning.ts (202 errors) ==== +==== regularExpressionScanning.ts (207 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -253,6 +258,16 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, + ~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. + ~~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. + ~~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, ~~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. diff --git a/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt index dffb110c8057b..29d7725433780 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt @@ -17,6 +17,11 @@ regularExpressionScanning.ts(5,6): error TS1499: Unknown regular expression flag regularExpressionScanning.ts(5,7): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,10): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,11): error TS1500: Duplicate regular expression flag. +regularExpressionScanning.ts(12,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(12,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(12,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. +regularExpressionScanning.ts(12,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(12,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. regularExpressionScanning.ts(13,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(13,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. regularExpressionScanning.ts(13,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. @@ -209,7 +214,7 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag is only available when targeting 'esnext' or later. -==== regularExpressionScanning.ts (209 errors) ==== +==== regularExpressionScanning.ts (214 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -260,6 +265,16 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, + ~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. + ~~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. + ~~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, ~~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. diff --git a/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt index 3c0a631d6bec2..95750036f4073 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt @@ -14,6 +14,11 @@ regularExpressionScanning.ts(5,6): error TS1499: Unknown regular expression flag regularExpressionScanning.ts(5,7): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,10): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,11): error TS1500: Duplicate regular expression flag. +regularExpressionScanning.ts(12,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(12,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(12,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. +regularExpressionScanning.ts(12,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(12,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. regularExpressionScanning.ts(13,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(13,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. regularExpressionScanning.ts(13,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. @@ -176,7 +181,7 @@ regularExpressionScanning.ts(47,5): error TS1518: Anything that would possibly m regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly match more than a single character is invalid inside a negated character class. -==== regularExpressionScanning.ts (176 errors) ==== +==== regularExpressionScanning.ts (181 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -221,6 +226,16 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, + ~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. + ~~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. + ~~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, ~~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. From ed08ef7df9f178ec73145dab8240469a073f63d2 Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Sat, 25 May 2024 03:17:27 +0800 Subject: [PATCH 07/10] Apply Suggested Changes --- src/compiler/scanner.ts | 20 ++++++++++--------- ...pressionScanning(target=es2015).errors.txt | 14 ++++++++++++- ...rExpressionScanning(target=es5).errors.txt | 14 ++++++++++++- ...pressionScanning(target=esnext).errors.txt | 14 ++++++++++++- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index ba6b438ee5f83..60dad01d822ef 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -2470,10 +2470,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } else if ( ch === CharacterCodes.openParen - && charCodeUnchecked(p + 1) === CharacterCodes.question - && charCodeUnchecked(p + 2) === CharacterCodes.lessThan - && charCodeUnchecked(p + 3) !== CharacterCodes.equals - && charCodeUnchecked(p + 3) !== CharacterCodes.exclamation + && charCodeChecked(p + 1) === CharacterCodes.question + && charCodeChecked(p + 2) === CharacterCodes.lessThan + && charCodeChecked(p + 3) !== CharacterCodes.equals + && charCodeChecked(p + 3) !== CharacterCodes.exclamation ) { namedCaptureGroups = true; } @@ -2535,7 +2535,8 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean /** Grammar parameter */ var unicodeMode = !!(regExpFlags & RegularExpressionFlags.UnicodeMode); - // Annex B treats any unicode mode as the strict syntax. + // Regular expressions are checked more strictly when either in 'u' or 'v' mode, or + // when not using the looser interpretation of the syntax from ECMA-262 Annex B. var anyUnicodeModeOrNonAnnexB = unicodeMode || !annexB; /** @see {scanClassSetExpression} */ @@ -2699,7 +2700,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean break; } } - else if (max && Number.parseInt(min) > Number.parseInt(max) && (anyUnicodeModeOrNonAnnexB || text.charCodeAt(pos) === CharacterCodes.closeBrace)) { + else if (max && Number.parseInt(min) > Number.parseInt(max) && (anyUnicodeModeOrNonAnnexB || charCodeChecked(pos) === CharacterCodes.closeBrace)) { error(Diagnostics.Numbers_out_of_order_in_quantifier, digitsStart, pos - digitsStart); } } @@ -3501,9 +3502,10 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } }); forEach(decimalEscapes, escape => { - // in AnnexB, if a DecimalEscape is greater than the number of capturing groups then it is treated as - // either a LegacyOctalEscapeSequence or IdentityEscape - if (anyUnicodeModeOrNonAnnexB && escape.value > numberOfCapturingGroups) { + // Although a DecimalEscape with a value greater than the number of capturing groups + // is treated as either a LegacyOctalEscapeSequence or an IdentityEscape in Annex B, + // an error is nevertheless reported since it's most likely a mistake. + if (escape.value > numberOfCapturingGroups) { if (numberOfCapturingGroups) { error(Diagnostics.This_backreference_refers_to_a_group_that_does_not_exist_There_are_only_0_capturing_groups_in_this_regular_expression, escape.pos, escape.end - escape.pos, numberOfCapturingGroups); } diff --git a/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt index 19b29fa5c2b67..fe13dc3f66d71 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt @@ -17,10 +17,14 @@ regularExpressionScanning.ts(5,6): error TS1499: Unknown regular expression flag regularExpressionScanning.ts(5,7): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,10): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,11): error TS1500: Duplicate regular expression flag. +regularExpressionScanning.ts(8,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +regularExpressionScanning.ts(9,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +regularExpressionScanning.ts(12,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(12,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. regularExpressionScanning.ts(12,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. regularExpressionScanning.ts(12,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. regularExpressionScanning.ts(12,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(12,42): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(12,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. regularExpressionScanning.ts(13,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(13,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. @@ -207,7 +211,7 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag is only available when targeting 'esnext' or later. -==== regularExpressionScanning.ts (207 errors) ==== +==== regularExpressionScanning.ts (211 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -254,10 +258,16 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag // Capturing groups /\0/, /\1/, + ~ +!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. /\2/, + ~ +!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, + ~~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. ~~~ @@ -266,6 +276,8 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. + ~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, diff --git a/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt index 29d7725433780..0e1260db49e57 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt @@ -17,10 +17,14 @@ regularExpressionScanning.ts(5,6): error TS1499: Unknown regular expression flag regularExpressionScanning.ts(5,7): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,10): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,11): error TS1500: Duplicate regular expression flag. +regularExpressionScanning.ts(8,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +regularExpressionScanning.ts(9,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +regularExpressionScanning.ts(12,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(12,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. regularExpressionScanning.ts(12,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. regularExpressionScanning.ts(12,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. regularExpressionScanning.ts(12,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(12,42): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(12,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. regularExpressionScanning.ts(13,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(13,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. @@ -214,7 +218,7 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag is only available when targeting 'esnext' or later. -==== regularExpressionScanning.ts (214 errors) ==== +==== regularExpressionScanning.ts (218 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -261,10 +265,16 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag // Capturing groups /\0/, /\1/, + ~ +!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. /\2/, + ~ +!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, + ~~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. ~~~ @@ -273,6 +283,8 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. + ~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, diff --git a/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt index 95750036f4073..d6ec4db6f6891 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt @@ -14,10 +14,14 @@ regularExpressionScanning.ts(5,6): error TS1499: Unknown regular expression flag regularExpressionScanning.ts(5,7): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,10): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,11): error TS1500: Duplicate regular expression flag. +regularExpressionScanning.ts(8,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +regularExpressionScanning.ts(9,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +regularExpressionScanning.ts(12,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(12,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. regularExpressionScanning.ts(12,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. regularExpressionScanning.ts(12,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. regularExpressionScanning.ts(12,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(12,42): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(12,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. regularExpressionScanning.ts(13,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. regularExpressionScanning.ts(13,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. @@ -181,7 +185,7 @@ regularExpressionScanning.ts(47,5): error TS1518: Anything that would possibly m regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly match more than a single character is invalid inside a negated character class. -==== regularExpressionScanning.ts (181 errors) ==== +==== regularExpressionScanning.ts (185 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -222,10 +226,16 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly // Capturing groups /\0/, /\1/, + ~ +!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. /\2/, + ~ +!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, + ~~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. ~~~ @@ -234,6 +244,8 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. + ~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, From b48f0d0ebf0839bb68a15e9caf57a23ca75ab4e8 Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Sat, 25 May 2024 05:21:31 +0800 Subject: [PATCH 08/10] Provide User-Friendly Errors for Decimal Escapes Inside Character Classes --- src/compiler/diagnosticMessages.json | 10 ++- src/compiler/scanner.ts | 63 ++++++++++---- ...pressionScanning(target=es2015).errors.txt | 78 ++++++++++++------ ...egularExpressionScanning(target=es2015).js | 8 +- ...rExpressionScanning(target=es2015).symbols | 4 +- ...larExpressionScanning(target=es2015).types | 16 ++-- ...rExpressionScanning(target=es5).errors.txt | 82 ++++++++++++------- .../regularExpressionScanning(target=es5).js | 8 +- ...ularExpressionScanning(target=es5).symbols | 4 +- ...egularExpressionScanning(target=es5).types | 16 ++-- ...pressionScanning(target=esnext).errors.txt | 78 ++++++++++++------ ...egularExpressionScanning(target=esnext).js | 8 +- ...rExpressionScanning(target=esnext).symbols | 4 +- ...larExpressionScanning(target=esnext).types | 16 ++-- .../compiler/regularExpressionScanning.ts | 4 +- 15 files changed, 256 insertions(+), 143 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 71b2c712b91cf..e74033719b5b8 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1789,7 +1789,7 @@ "category": "Error", "code": 1533 }, - "This backreference is invalid because the containing regular expression contains no capturing groups.": { + "This backreference refers to a group that does not exist. There are no capturing groups in this regular expression.": { "category": "Error", "code": 1534 }, @@ -1797,6 +1797,14 @@ "category": "Error", "code": 1535 }, + "Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '{0}' instead.": { + "category": "Error", + "code": 1536 + }, + "Decimal escape sequences and backreferences are not allowed in a character class.": { + "category": "Error", + "code": 1537 + }, "The types of '{0}' are incompatible between these types.": { "category": "Error", diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 8288e2030d910..b06fa55b93360 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -997,6 +997,19 @@ export function isIdentifierText(name: string, languageVersion: ScriptTarget | u return true; } +const enum EscapeSequenceScanningFlags { + String = 1 << 0, + ReportErrors = 1 << 1, + + RegularExpression = 1 << 2, + AnnexB = 1 << 3, + AnyUnicodeMode = 1 << 4, + AtomEscape = 1 << 5, + + ReportInvalidEscapeErrors = RegularExpression | ReportErrors, + ScanExtendedUnicodeEscape = String | AnyUnicodeMode, +} + const enum ClassSetExpressionType { Unknown, ClassUnion, @@ -1416,7 +1429,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } if (ch === CharacterCodes.backslash && !jsxAttributeString) { result += text.substring(start, pos); - result += scanEscapeSequence(/*shouldEmitInvalidEscapeError*/ true, /*isRegularExpression*/ false); + result += scanEscapeSequence(EscapeSequenceScanningFlags.String | EscapeSequenceScanningFlags.ReportErrors); start = pos; continue; } @@ -1474,7 +1487,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean // Escape character if (currChar === CharacterCodes.backslash) { contents += text.substring(start, pos); - contents += scanEscapeSequence(shouldEmitInvalidEscapeError, /*isRegularExpression*/ false); + contents += scanEscapeSequence(EscapeSequenceScanningFlags.String | (shouldEmitInvalidEscapeError ? EscapeSequenceScanningFlags.ReportErrors : 0)); start = pos; continue; } @@ -1517,7 +1530,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean // | [0-3] [0-7] [0-7]? // | [4-7] [0-7] // NonOctalDecimalEscapeSequence ::= [89] - function scanEscapeSequence(shouldEmitInvalidEscapeError: boolean, isRegularExpression: boolean | "annex-b"): string { + function scanEscapeSequence(flags: EscapeSequenceScanningFlags): string { const start = pos; pos++; if (pos >= end) { @@ -1554,9 +1567,14 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean } // '\47' tokenFlags |= TokenFlags.ContainsInvalidEscape; - if (isRegularExpression || shouldEmitInvalidEscapeError) { + if (flags & EscapeSequenceScanningFlags.ReportInvalidEscapeErrors) { const code = parseInt(text.substring(start + 1, pos), 8); - error(Diagnostics.Octal_escape_sequences_are_not_allowed_Use_the_syntax_0, start, pos - start, "\\x" + code.toString(16).padStart(2, "0")); + if (flags & EscapeSequenceScanningFlags.RegularExpression && !(flags & EscapeSequenceScanningFlags.AtomEscape) && ch !== CharacterCodes._0) { + error(Diagnostics.Octal_escape_sequences_and_backreferences_are_not_allowed_in_a_character_class_If_this_was_intended_as_an_escape_sequence_use_the_syntax_0_instead, start, pos - start, "\\x" + code.toString(16).padStart(2, "0")); + } + else { + error(Diagnostics.Octal_escape_sequences_are_not_allowed_Use_the_syntax_0, start, pos - start, "\\x" + code.toString(16).padStart(2, "0")); + } return String.fromCharCode(code); } return text.substring(start, pos); @@ -1564,8 +1582,13 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean case CharacterCodes._9: // the invalid '\8' and '\9' tokenFlags |= TokenFlags.ContainsInvalidEscape; - if (isRegularExpression || shouldEmitInvalidEscapeError) { - error(Diagnostics.Escape_sequence_0_is_not_allowed, start, pos - start, text.substring(start, pos)); + if (flags & EscapeSequenceScanningFlags.ReportInvalidEscapeErrors) { + if (flags & EscapeSequenceScanningFlags.RegularExpression && !(flags & EscapeSequenceScanningFlags.AtomEscape)) { + error(Diagnostics.Decimal_escape_sequences_and_backreferences_are_not_allowed_in_a_character_class, start, pos - start); + } + else { + error(Diagnostics.Escape_sequence_0_is_not_allowed, start, pos - start, text.substring(start, pos)); + } return String.fromCharCode(ch); } return text.substring(start, pos); @@ -1587,18 +1610,18 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean return '"'; case CharacterCodes.u: if ( - (!isRegularExpression || shouldEmitInvalidEscapeError) && + flags & EscapeSequenceScanningFlags.ScanExtendedUnicodeEscape && pos < end && charCodeUnchecked(pos) === CharacterCodes.openBrace ) { // '\u{DDDDDD}' pos -= 2; - return scanExtendedUnicodeEscape(!!isRegularExpression || shouldEmitInvalidEscapeError); + return scanExtendedUnicodeEscape(!!(flags & EscapeSequenceScanningFlags.ReportInvalidEscapeErrors)); } // '\uDDDD' for (; pos < start + 6; pos++) { if (!(pos < end && isHexDigit(charCodeUnchecked(pos)))) { tokenFlags |= TokenFlags.ContainsInvalidEscape; - if (isRegularExpression || shouldEmitInvalidEscapeError) { + if (flags & EscapeSequenceScanningFlags.ReportInvalidEscapeErrors) { error(Diagnostics.Hexadecimal_digit_expected); } return text.substring(start, pos); @@ -1608,7 +1631,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean const escapedValue = parseInt(text.substring(start + 2, pos), 16); const escapedValueString = String.fromCharCode(escapedValue); if ( - isRegularExpression && shouldEmitInvalidEscapeError && escapedValue >= 0xD800 && escapedValue <= 0xDBFF && + flags & EscapeSequenceScanningFlags.AnyUnicodeMode && escapedValue >= 0xD800 && escapedValue <= 0xDBFF && pos + 6 < end && text.substring(pos, pos + 2) === "\\u" && charCodeUnchecked(pos + 2) !== CharacterCodes.openBrace ) { // For regular expressions in any Unicode mode, \u HexLeadSurrogate \u HexTrailSurrogate is treated as a single character @@ -1635,7 +1658,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean for (; pos < start + 4; pos++) { if (!(pos < end && isHexDigit(charCodeUnchecked(pos)))) { tokenFlags |= TokenFlags.ContainsInvalidEscape; - if (isRegularExpression || shouldEmitInvalidEscapeError) { + if (flags & EscapeSequenceScanningFlags.ReportInvalidEscapeErrors) { error(Diagnostics.Hexadecimal_digit_expected); } return text.substring(start, pos); @@ -1656,7 +1679,12 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean case CharacterCodes.paragraphSeparator: return ""; default: - if (isRegularExpression === true && (shouldEmitInvalidEscapeError || isIdentifierPart(ch, languageVersion))) { + if ( + flags & EscapeSequenceScanningFlags.AnyUnicodeMode + || flags & EscapeSequenceScanningFlags.RegularExpression + && !(flags & EscapeSequenceScanningFlags.AnnexB) + && isIdentifierPart(ch, languageVersion) + ) { error(Diagnostics.This_character_cannot_be_escaped_in_a_regular_expression, pos - 2, 2); } return String.fromCharCode(ch); @@ -2934,7 +2962,12 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean return String.fromCharCode(ch); default: pos--; - return scanEscapeSequence(/*shouldEmitInvalidEscapeError*/ anyUnicodeMode, /*isRegularExpression*/ anyUnicodeModeOrNonAnnexB || "annex-b"); + return scanEscapeSequence( + EscapeSequenceScanningFlags.RegularExpression + | (annexB ? EscapeSequenceScanningFlags.AnnexB : 0) + | (anyUnicodeMode ? EscapeSequenceScanningFlags.AnyUnicodeMode : 0) + | (atomEscape ? EscapeSequenceScanningFlags.AtomEscape : 0), + ); } } @@ -3540,7 +3573,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean error(Diagnostics.This_backreference_refers_to_a_group_that_does_not_exist_There_are_only_0_capturing_groups_in_this_regular_expression, escape.pos, escape.end - escape.pos, numberOfCapturingGroups); } else { - error(Diagnostics.This_backreference_is_invalid_because_the_containing_regular_expression_contains_no_capturing_groups, escape.pos, escape.end - escape.pos); + error(Diagnostics.This_backreference_refers_to_a_group_that_does_not_exist_There_are_no_capturing_groups_in_this_regular_expression, escape.pos, escape.end - escape.pos); } } }); diff --git a/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt index fe13dc3f66d71..e5afde3d2f4b2 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=es2015).errors.txt @@ -17,22 +17,30 @@ regularExpressionScanning.ts(5,6): error TS1499: Unknown regular expression flag regularExpressionScanning.ts(5,7): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,10): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,11): error TS1500: Duplicate regular expression flag. -regularExpressionScanning.ts(8,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. -regularExpressionScanning.ts(9,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +regularExpressionScanning.ts(8,4): error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. +regularExpressionScanning.ts(9,4): error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. regularExpressionScanning.ts(12,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(12,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(12,24): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. regularExpressionScanning.ts(12,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. -regularExpressionScanning.ts(12,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. -regularExpressionScanning.ts(12,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. -regularExpressionScanning.ts(12,42): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(12,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(12,29): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. +regularExpressionScanning.ts(12,33): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. +regularExpressionScanning.ts(12,36): error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. +regularExpressionScanning.ts(12,42): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(12,47): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(12,48): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(12,53): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(12,54): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. regularExpressionScanning.ts(13,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(13,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(13,24): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. regularExpressionScanning.ts(13,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. -regularExpressionScanning.ts(13,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. -regularExpressionScanning.ts(13,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. -regularExpressionScanning.ts(13,42): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(13,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(13,29): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. +regularExpressionScanning.ts(13,33): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. +regularExpressionScanning.ts(13,36): error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. +regularExpressionScanning.ts(13,42): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(13,47): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(13,48): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(13,53): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(13,54): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. regularExpressionScanning.ts(14,5): error TS1503: Named capturing groups are only available when targeting 'ES2018' or later. regularExpressionScanning.ts(14,14): error TS1503: Named capturing groups are only available when targeting 'ES2018' or later. regularExpressionScanning.ts(14,29): error TS1503: Named capturing groups are only available when targeting 'ES2018' or later. @@ -211,7 +219,7 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag is only available when targeting 'esnext' or later. -==== regularExpressionScanning.ts (211 errors) ==== +==== regularExpressionScanning.ts (219 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -259,42 +267,58 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag /\0/, /\1/, ~ -!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +!!! error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. /\2/, ~ -!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +!!! error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, ~~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. ~~~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. - ~~~ +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. + ~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + ~~ +!!! error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. + ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. - ~ + ~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. - ~~~~ + ~~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + ~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, ~~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. ~~~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. - ~~~ +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. + ~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + ~~ +!!! error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. + ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. - ~ + ~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. - ~~~~ + ~~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. + ~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, ~~~~~ !!! error TS1503: Named capturing groups are only available when targeting 'ES2018' or later. diff --git a/tests/baselines/reference/regularExpressionScanning(target=es2015).js b/tests/baselines/reference/regularExpressionScanning(target=es2015).js index 0c7a8eb88a13f..532b81598e326 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es2015).js +++ b/tests/baselines/reference/regularExpressionScanning(target=es2015).js @@ -12,8 +12,8 @@ const regexes: RegExp[] = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers @@ -63,8 +63,8 @@ const regexes = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers diff --git a/tests/baselines/reference/regularExpressionScanning(target=es2015).symbols b/tests/baselines/reference/regularExpressionScanning(target=es2015).symbols index d46a82ed9a797..be3fb1bc3fdac 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es2015).symbols +++ b/tests/baselines/reference/regularExpressionScanning(target=es2015).symbols @@ -15,8 +15,8 @@ const regexes: RegExp[] = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers diff --git a/tests/baselines/reference/regularExpressionScanning(target=es2015).types b/tests/baselines/reference/regularExpressionScanning(target=es2015).types index 18219dd210a87..7bd5841bd26be 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es2015).types +++ b/tests/baselines/reference/regularExpressionScanning(target=es2015).types @@ -4,8 +4,8 @@ const regexes: RegExp[] = [ >regexes : RegExp[] > : ^^^^^^^^ ->[ // Flags /foo/visualstudiocode, // Pattern modifiers /(?med-ium:bar)/, // Capturing groups /\0/, /\1/, /\2/, /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers /{}{1,2}_{3}.{4,}?(foo){008}${32,16}\b{064,128}.+&*?\???\n{,256}{\\{,/, // Character classes /[-A-Za-z-z-aZ-A\d_-\d-.-.\r-\n\w-\W]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/u, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/v, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/u, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/v, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/u, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/v, // Character escapes /\c[\c0\ca\cQ\c\C]\c1\C/, /\c[\c0\ca\cQ\c\C]\c1\C/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/v, // Unicode sets notation /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/u, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/v, /[[^\P{Decimal_Number}&&[0-9]]&&\p{L}&&\p{ID_Continue}--\p{ASCII}\p{CWCF}]/v, /[^\p{Emoji}\p{RGI_Emoji}][^\p{Emoji}--\p{RGI_Emoji}][^\p{Emoji}&&\p{RGI_Emoji}]/v, /[^\p{RGI_Emoji}\p{Emoji}][^\p{RGI_Emoji}--\p{Emoji}][^\p{RGI_Emoji}&&\p{Emoji}]/v, /[^\p{RGI_Emoji}\q{foo}][^\p{RGI_Emoji}--\q{foo}][^\p{RGI_Emoji}&&\q{foo}]/v, /[^\p{Emoji}[[\p{RGI_Emoji}]]][^\p{Emoji}--[[\p{RGI_Emoji}]]][^\p{Emoji}&&[[\p{RGI_Emoji}]]]/v, /[^[[\p{RGI_Emoji}]]\p{Emoji}][^[[\p{RGI_Emoji}]]--\p{Emoji}][^[[\p{RGI_Emoji}]]&&\p{Emoji}]/v, /[^[[\p{RGI_Emoji}]]\q{foo}][^[[\p{RGI_Emoji}]]--\q{foo}][^[[\p{RGI_Emoji}]]&&\q{foo}]/v, /[^\q{foo|bar|baz}--\q{foo}--\q{bar}--\q{baz}][^\p{L}--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v, /[^[[\q{foo|bar|baz}]]--\q{foo}--\q{bar}--\q{baz}][^[^[^\p{L}]]--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v,] : RegExp[] -> : ^^^^^^^^ +>[ // Flags /foo/visualstudiocode, // Pattern modifiers /(?med-ium:bar)/, // Capturing groups /\0/, /\1/, /\2/, /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers /{}{1,2}_{3}.{4,}?(foo){008}${32,16}\b{064,128}.+&*?\???\n{,256}{\\{,/, // Character classes /[-A-Za-z-z-aZ-A\d_-\d-.-.\r-\n\w-\W]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/u, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/v, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/u, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/v, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/u, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/v, // Character escapes /\c[\c0\ca\cQ\c\C]\c1\C/, /\c[\c0\ca\cQ\c\C]\c1\C/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/v, // Unicode sets notation /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/u, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/v, /[[^\P{Decimal_Number}&&[0-9]]&&\p{L}&&\p{ID_Continue}--\p{ASCII}\p{CWCF}]/v, /[^\p{Emoji}\p{RGI_Emoji}][^\p{Emoji}--\p{RGI_Emoji}][^\p{Emoji}&&\p{RGI_Emoji}]/v, /[^\p{RGI_Emoji}\p{Emoji}][^\p{RGI_Emoji}--\p{Emoji}][^\p{RGI_Emoji}&&\p{Emoji}]/v, /[^\p{RGI_Emoji}\q{foo}][^\p{RGI_Emoji}--\q{foo}][^\p{RGI_Emoji}&&\q{foo}]/v, /[^\p{Emoji}[[\p{RGI_Emoji}]]][^\p{Emoji}--[[\p{RGI_Emoji}]]][^\p{Emoji}&&[[\p{RGI_Emoji}]]]/v, /[^[[\p{RGI_Emoji}]]\p{Emoji}][^[[\p{RGI_Emoji}]]--\p{Emoji}][^[[\p{RGI_Emoji}]]&&\p{Emoji}]/v, /[^[[\p{RGI_Emoji}]]\q{foo}][^[[\p{RGI_Emoji}]]--\q{foo}][^[[\p{RGI_Emoji}]]&&\q{foo}]/v, /[^\q{foo|bar|baz}--\q{foo}--\q{bar}--\q{baz}][^\p{L}--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v, /[^[[\q{foo|bar|baz}]]--\q{foo}--\q{bar}--\q{baz}][^[^[^\p{L}]]--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v,] : RegExp[] +> : ^^^^^^^^ // Flags /foo/visualstudiocode, @@ -38,13 +38,13 @@ const regexes: RegExp[] = [ >/(hi) (hello) \2/ : RegExp > : ^^^^^^ - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, ->/\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/ : RegExp -> : ^^^^^^ + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, +>/\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/ : RegExp +> : ^^^^^^ - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, ->/\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u : RegExp -> : ^^^^^^ + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, +>/\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u : RegExp +> : ^^^^^^ /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, >/(?)((?bar)bar)(?baz)|(foo(?foo))(?)/ : RegExp diff --git a/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt index 0e1260db49e57..2c185950185a0 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=es5).errors.txt @@ -17,23 +17,31 @@ regularExpressionScanning.ts(5,6): error TS1499: Unknown regular expression flag regularExpressionScanning.ts(5,7): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,10): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,11): error TS1500: Duplicate regular expression flag. -regularExpressionScanning.ts(8,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. -regularExpressionScanning.ts(9,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +regularExpressionScanning.ts(8,4): error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. +regularExpressionScanning.ts(9,4): error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. regularExpressionScanning.ts(12,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(12,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(12,24): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. regularExpressionScanning.ts(12,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. -regularExpressionScanning.ts(12,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. -regularExpressionScanning.ts(12,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. -regularExpressionScanning.ts(12,42): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(12,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(12,29): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. +regularExpressionScanning.ts(12,33): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. +regularExpressionScanning.ts(12,36): error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. +regularExpressionScanning.ts(12,42): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(12,47): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(12,48): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(12,53): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(12,54): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. regularExpressionScanning.ts(13,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(13,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(13,24): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. regularExpressionScanning.ts(13,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. -regularExpressionScanning.ts(13,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. -regularExpressionScanning.ts(13,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. -regularExpressionScanning.ts(13,42): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(13,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. -regularExpressionScanning.ts(13,48): error TS1501: This regular expression flag is only available when targeting 'es6' or later. +regularExpressionScanning.ts(13,29): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. +regularExpressionScanning.ts(13,33): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. +regularExpressionScanning.ts(13,36): error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. +regularExpressionScanning.ts(13,42): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(13,47): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(13,48): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(13,53): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(13,54): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. +regularExpressionScanning.ts(13,59): error TS1501: This regular expression flag is only available when targeting 'es6' or later. regularExpressionScanning.ts(14,5): error TS1503: Named capturing groups are only available when targeting 'ES2018' or later. regularExpressionScanning.ts(14,14): error TS1503: Named capturing groups are only available when targeting 'ES2018' or later. regularExpressionScanning.ts(14,29): error TS1503: Named capturing groups are only available when targeting 'ES2018' or later. @@ -218,7 +226,7 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag is only available when targeting 'esnext' or later. -==== regularExpressionScanning.ts (218 errors) ==== +==== regularExpressionScanning.ts (226 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -266,43 +274,59 @@ regularExpressionScanning.ts(47,101): error TS1501: This regular expression flag /\0/, /\1/, ~ -!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +!!! error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. /\2/, ~ -!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +!!! error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, ~~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. ~~~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. - ~~~ +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. + ~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + ~~ +!!! error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. + ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. - ~ + ~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. - ~~~~ + ~~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + ~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, ~~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. ~~~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. - ~~~ +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. + ~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + ~~ +!!! error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. + ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. - ~ + ~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. - ~~~~ + ~~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. - ~ + ~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + ~ !!! error TS1501: This regular expression flag is only available when targeting 'es6' or later. /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, ~~~~~ diff --git a/tests/baselines/reference/regularExpressionScanning(target=es5).js b/tests/baselines/reference/regularExpressionScanning(target=es5).js index fa691f88c1b0f..9b9e04d7ae9cc 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es5).js +++ b/tests/baselines/reference/regularExpressionScanning(target=es5).js @@ -12,8 +12,8 @@ const regexes: RegExp[] = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers @@ -63,8 +63,8 @@ var regexes = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers diff --git a/tests/baselines/reference/regularExpressionScanning(target=es5).symbols b/tests/baselines/reference/regularExpressionScanning(target=es5).symbols index 7f424ca297bad..510a311226e8e 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es5).symbols +++ b/tests/baselines/reference/regularExpressionScanning(target=es5).symbols @@ -15,8 +15,8 @@ const regexes: RegExp[] = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers diff --git a/tests/baselines/reference/regularExpressionScanning(target=es5).types b/tests/baselines/reference/regularExpressionScanning(target=es5).types index 18219dd210a87..7bd5841bd26be 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=es5).types +++ b/tests/baselines/reference/regularExpressionScanning(target=es5).types @@ -4,8 +4,8 @@ const regexes: RegExp[] = [ >regexes : RegExp[] > : ^^^^^^^^ ->[ // Flags /foo/visualstudiocode, // Pattern modifiers /(?med-ium:bar)/, // Capturing groups /\0/, /\1/, /\2/, /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers /{}{1,2}_{3}.{4,}?(foo){008}${32,16}\b{064,128}.+&*?\???\n{,256}{\\{,/, // Character classes /[-A-Za-z-z-aZ-A\d_-\d-.-.\r-\n\w-\W]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/u, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/v, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/u, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/v, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/u, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/v, // Character escapes /\c[\c0\ca\cQ\c\C]\c1\C/, /\c[\c0\ca\cQ\c\C]\c1\C/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/v, // Unicode sets notation /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/u, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/v, /[[^\P{Decimal_Number}&&[0-9]]&&\p{L}&&\p{ID_Continue}--\p{ASCII}\p{CWCF}]/v, /[^\p{Emoji}\p{RGI_Emoji}][^\p{Emoji}--\p{RGI_Emoji}][^\p{Emoji}&&\p{RGI_Emoji}]/v, /[^\p{RGI_Emoji}\p{Emoji}][^\p{RGI_Emoji}--\p{Emoji}][^\p{RGI_Emoji}&&\p{Emoji}]/v, /[^\p{RGI_Emoji}\q{foo}][^\p{RGI_Emoji}--\q{foo}][^\p{RGI_Emoji}&&\q{foo}]/v, /[^\p{Emoji}[[\p{RGI_Emoji}]]][^\p{Emoji}--[[\p{RGI_Emoji}]]][^\p{Emoji}&&[[\p{RGI_Emoji}]]]/v, /[^[[\p{RGI_Emoji}]]\p{Emoji}][^[[\p{RGI_Emoji}]]--\p{Emoji}][^[[\p{RGI_Emoji}]]&&\p{Emoji}]/v, /[^[[\p{RGI_Emoji}]]\q{foo}][^[[\p{RGI_Emoji}]]--\q{foo}][^[[\p{RGI_Emoji}]]&&\q{foo}]/v, /[^\q{foo|bar|baz}--\q{foo}--\q{bar}--\q{baz}][^\p{L}--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v, /[^[[\q{foo|bar|baz}]]--\q{foo}--\q{bar}--\q{baz}][^[^[^\p{L}]]--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v,] : RegExp[] -> : ^^^^^^^^ +>[ // Flags /foo/visualstudiocode, // Pattern modifiers /(?med-ium:bar)/, // Capturing groups /\0/, /\1/, /\2/, /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers /{}{1,2}_{3}.{4,}?(foo){008}${32,16}\b{064,128}.+&*?\???\n{,256}{\\{,/, // Character classes /[-A-Za-z-z-aZ-A\d_-\d-.-.\r-\n\w-\W]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/u, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/v, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/u, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/v, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/u, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/v, // Character escapes /\c[\c0\ca\cQ\c\C]\c1\C/, /\c[\c0\ca\cQ\c\C]\c1\C/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/v, // Unicode sets notation /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/u, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/v, /[[^\P{Decimal_Number}&&[0-9]]&&\p{L}&&\p{ID_Continue}--\p{ASCII}\p{CWCF}]/v, /[^\p{Emoji}\p{RGI_Emoji}][^\p{Emoji}--\p{RGI_Emoji}][^\p{Emoji}&&\p{RGI_Emoji}]/v, /[^\p{RGI_Emoji}\p{Emoji}][^\p{RGI_Emoji}--\p{Emoji}][^\p{RGI_Emoji}&&\p{Emoji}]/v, /[^\p{RGI_Emoji}\q{foo}][^\p{RGI_Emoji}--\q{foo}][^\p{RGI_Emoji}&&\q{foo}]/v, /[^\p{Emoji}[[\p{RGI_Emoji}]]][^\p{Emoji}--[[\p{RGI_Emoji}]]][^\p{Emoji}&&[[\p{RGI_Emoji}]]]/v, /[^[[\p{RGI_Emoji}]]\p{Emoji}][^[[\p{RGI_Emoji}]]--\p{Emoji}][^[[\p{RGI_Emoji}]]&&\p{Emoji}]/v, /[^[[\p{RGI_Emoji}]]\q{foo}][^[[\p{RGI_Emoji}]]--\q{foo}][^[[\p{RGI_Emoji}]]&&\q{foo}]/v, /[^\q{foo|bar|baz}--\q{foo}--\q{bar}--\q{baz}][^\p{L}--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v, /[^[[\q{foo|bar|baz}]]--\q{foo}--\q{bar}--\q{baz}][^[^[^\p{L}]]--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v,] : RegExp[] +> : ^^^^^^^^ // Flags /foo/visualstudiocode, @@ -38,13 +38,13 @@ const regexes: RegExp[] = [ >/(hi) (hello) \2/ : RegExp > : ^^^^^^ - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, ->/\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/ : RegExp -> : ^^^^^^ + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, +>/\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/ : RegExp +> : ^^^^^^ - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, ->/\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u : RegExp -> : ^^^^^^ + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, +>/\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u : RegExp +> : ^^^^^^ /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, >/(?)((?bar)bar)(?baz)|(foo(?foo))(?)/ : RegExp diff --git a/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt b/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt index d6ec4db6f6891..c2d144d42c511 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt +++ b/tests/baselines/reference/regularExpressionScanning(target=esnext).errors.txt @@ -14,22 +14,30 @@ regularExpressionScanning.ts(5,6): error TS1499: Unknown regular expression flag regularExpressionScanning.ts(5,7): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,10): error TS1509: This regular expression flag cannot be toggled within a subpattern. regularExpressionScanning.ts(5,11): error TS1500: Duplicate regular expression flag. -regularExpressionScanning.ts(8,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. -regularExpressionScanning.ts(9,4): error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +regularExpressionScanning.ts(8,4): error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. +regularExpressionScanning.ts(9,4): error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. regularExpressionScanning.ts(12,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(12,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(12,24): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. regularExpressionScanning.ts(12,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. -regularExpressionScanning.ts(12,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. -regularExpressionScanning.ts(12,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. -regularExpressionScanning.ts(12,42): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(12,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(12,29): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. +regularExpressionScanning.ts(12,33): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. +regularExpressionScanning.ts(12,36): error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. +regularExpressionScanning.ts(12,42): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(12,47): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(12,48): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(12,53): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(12,54): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. regularExpressionScanning.ts(13,9): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(13,24): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +regularExpressionScanning.ts(13,24): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. regularExpressionScanning.ts(13,26): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. -regularExpressionScanning.ts(13,29): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. -regularExpressionScanning.ts(13,37): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. -regularExpressionScanning.ts(13,42): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. -regularExpressionScanning.ts(13,43): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(13,29): error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. +regularExpressionScanning.ts(13,33): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. +regularExpressionScanning.ts(13,36): error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. +regularExpressionScanning.ts(13,42): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. +regularExpressionScanning.ts(13,47): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(13,48): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. +regularExpressionScanning.ts(13,53): error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. +regularExpressionScanning.ts(13,54): error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. regularExpressionScanning.ts(15,15): error TS1532: There is no capturing group named 'absent' in this regular expression. regularExpressionScanning.ts(15,59): error TS1515: Named capturing groups with the same name must be mutually exclusive to each other. regularExpressionScanning.ts(17,31): error TS1507: There is nothing available for repetition. @@ -185,7 +193,7 @@ regularExpressionScanning.ts(47,5): error TS1518: Anything that would possibly m regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly match more than a single character is invalid inside a negated character class. -==== regularExpressionScanning.ts (185 errors) ==== +==== regularExpressionScanning.ts (193 errors) ==== const regexes: RegExp[] = [ // Flags /foo/visualstudiocode, @@ -227,42 +235,58 @@ regularExpressionScanning.ts(47,89): error TS1518: Anything that would possibly /\0/, /\1/, ~ -!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +!!! error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. /\2/, ~ -!!! error TS1534: This backreference is invalid because the containing regular expression contains no capturing groups. +!!! error TS1534: This backreference refers to a group that does not exist. There are no capturing groups in this regular expression. /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, ~~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. ~~~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. - ~~~ +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. + ~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + ~~ +!!! error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. + ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. - ~ + ~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. - ~~~~ + ~~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + ~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, ~~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. ~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x01' instead. ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x01'. ~~~~ -!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x53'. - ~~~ +!!! error TS1536: Octal escape sequences and backreferences are not allowed in a character class. If this was intended as an escape sequence, use the syntax '\x53' instead. + ~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. + ~~ +!!! error TS1537: Decimal escape sequences and backreferences are not allowed in a character class. + ~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x03'. - ~ + ~ !!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. - ~~~~ + ~~~~ !!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x05'. + ~ +!!! error TS1533: This backreference refers to a group that does not exist. There are only 4 capturing groups in this regular expression. + ~~~ +!!! error TS1487: Octal escape sequences are not allowed. Use the syntax '\x00'. /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, ~~~~~~ diff --git a/tests/baselines/reference/regularExpressionScanning(target=esnext).js b/tests/baselines/reference/regularExpressionScanning(target=esnext).js index 0c7a8eb88a13f..532b81598e326 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=esnext).js +++ b/tests/baselines/reference/regularExpressionScanning(target=esnext).js @@ -12,8 +12,8 @@ const regexes: RegExp[] = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers @@ -63,8 +63,8 @@ const regexes = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers diff --git a/tests/baselines/reference/regularExpressionScanning(target=esnext).symbols b/tests/baselines/reference/regularExpressionScanning(target=esnext).symbols index 72c3617f33d6f..fccd492b24d86 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=esnext).symbols +++ b/tests/baselines/reference/regularExpressionScanning(target=esnext).symbols @@ -15,8 +15,8 @@ const regexes: RegExp[] = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers diff --git a/tests/baselines/reference/regularExpressionScanning(target=esnext).types b/tests/baselines/reference/regularExpressionScanning(target=esnext).types index 18219dd210a87..7bd5841bd26be 100644 --- a/tests/baselines/reference/regularExpressionScanning(target=esnext).types +++ b/tests/baselines/reference/regularExpressionScanning(target=esnext).types @@ -4,8 +4,8 @@ const regexes: RegExp[] = [ >regexes : RegExp[] > : ^^^^^^^^ ->[ // Flags /foo/visualstudiocode, // Pattern modifiers /(?med-ium:bar)/, // Capturing groups /\0/, /\1/, /\2/, /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers /{}{1,2}_{3}.{4,}?(foo){008}${32,16}\b{064,128}.+&*?\???\n{,256}{\\{,/, // Character classes /[-A-Za-z-z-aZ-A\d_-\d-.-.\r-\n\w-\W]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/u, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/v, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/u, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/v, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/u, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/v, // Character escapes /\c[\c0\ca\cQ\c\C]\c1\C/, /\c[\c0\ca\cQ\c\C]\c1\C/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/v, // Unicode sets notation /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/u, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/v, /[[^\P{Decimal_Number}&&[0-9]]&&\p{L}&&\p{ID_Continue}--\p{ASCII}\p{CWCF}]/v, /[^\p{Emoji}\p{RGI_Emoji}][^\p{Emoji}--\p{RGI_Emoji}][^\p{Emoji}&&\p{RGI_Emoji}]/v, /[^\p{RGI_Emoji}\p{Emoji}][^\p{RGI_Emoji}--\p{Emoji}][^\p{RGI_Emoji}&&\p{Emoji}]/v, /[^\p{RGI_Emoji}\q{foo}][^\p{RGI_Emoji}--\q{foo}][^\p{RGI_Emoji}&&\q{foo}]/v, /[^\p{Emoji}[[\p{RGI_Emoji}]]][^\p{Emoji}--[[\p{RGI_Emoji}]]][^\p{Emoji}&&[[\p{RGI_Emoji}]]]/v, /[^[[\p{RGI_Emoji}]]\p{Emoji}][^[[\p{RGI_Emoji}]]--\p{Emoji}][^[[\p{RGI_Emoji}]]&&\p{Emoji}]/v, /[^[[\p{RGI_Emoji}]]\q{foo}][^[[\p{RGI_Emoji}]]--\q{foo}][^[[\p{RGI_Emoji}]]&&\q{foo}]/v, /[^\q{foo|bar|baz}--\q{foo}--\q{bar}--\q{baz}][^\p{L}--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v, /[^[[\q{foo|bar|baz}]]--\q{foo}--\q{bar}--\q{baz}][^[^[^\p{L}]]--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v,] : RegExp[] -> : ^^^^^^^^ +>[ // Flags /foo/visualstudiocode, // Pattern modifiers /(?med-ium:bar)/, // Capturing groups /\0/, /\1/, /\2/, /(hi)\1/, /(hi) (hello) \2/, /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers /{}{1,2}_{3}.{4,}?(foo){008}${32,16}\b{064,128}.+&*?\???\n{,256}{\\{,/, // Character classes /[-A-Za-z-z-aZ-A\d_-\d-.-.\r-\n\w-\W]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/u, /\p{L}\p{gc=L}\p{ASCII}\p{Invalid}[\p{L}\p{gc=L}\P{ASCII}\p{Invalid}]/v, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/u, /\p{InvalidProperty=Value}\p{=}\p{sc=}\P{=foo}[\p{}\p\\\P\P{]\p{/v, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/u, /\p{RGI_Emoji}\P{RGI_Emoji}[^\p{RGI_Emoji}\P{RGI_Emoji}]/v, // Character escapes /\c[\c0\ca\cQ\c\C]\c1\C/, /\c[\c0\ca\cQ\c\C]\c1\C/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/u, /\q\\\`[\q\\\`[\Q\\\Q{\q{foo|bar|baz]\q{]\q{/v, // Unicode sets notation /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/u, /[a--b[--][\d++[]]&&[[&0-9--]&&[\p{L}]--\P{L}-_-]]&&&\q{foo}[0---9][&&q&&&\q{bar}&&]/v, /[[^\P{Decimal_Number}&&[0-9]]&&\p{L}&&\p{ID_Continue}--\p{ASCII}\p{CWCF}]/v, /[^\p{Emoji}\p{RGI_Emoji}][^\p{Emoji}--\p{RGI_Emoji}][^\p{Emoji}&&\p{RGI_Emoji}]/v, /[^\p{RGI_Emoji}\p{Emoji}][^\p{RGI_Emoji}--\p{Emoji}][^\p{RGI_Emoji}&&\p{Emoji}]/v, /[^\p{RGI_Emoji}\q{foo}][^\p{RGI_Emoji}--\q{foo}][^\p{RGI_Emoji}&&\q{foo}]/v, /[^\p{Emoji}[[\p{RGI_Emoji}]]][^\p{Emoji}--[[\p{RGI_Emoji}]]][^\p{Emoji}&&[[\p{RGI_Emoji}]]]/v, /[^[[\p{RGI_Emoji}]]\p{Emoji}][^[[\p{RGI_Emoji}]]--\p{Emoji}][^[[\p{RGI_Emoji}]]&&\p{Emoji}]/v, /[^[[\p{RGI_Emoji}]]\q{foo}][^[[\p{RGI_Emoji}]]--\q{foo}][^[[\p{RGI_Emoji}]]&&\q{foo}]/v, /[^\q{foo|bar|baz}--\q{foo}--\q{bar}--\q{baz}][^\p{L}--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v, /[^[[\q{foo|bar|baz}]]--\q{foo}--\q{bar}--\q{baz}][^[^[^\p{L}]]--\q{foo}--[\q{bar}]--[^[\q{baz}]]]/v,] : RegExp[] +> : ^^^^^^^^ // Flags /foo/visualstudiocode, @@ -38,13 +38,13 @@ const regexes: RegExp[] = [ >/(hi) (hello) \2/ : RegExp > : ^^^^^^ - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, ->/\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/ : RegExp -> : ^^^^^^ + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, +>/\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/ : RegExp +> : ^^^^^^ - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, ->/\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u : RegExp -> : ^^^^^^ + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, +>/\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u : RegExp +> : ^^^^^^ /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, >/(?)((?bar)bar)(?baz)|(foo(?foo))(?)/ : RegExp diff --git a/tests/cases/compiler/regularExpressionScanning.ts b/tests/cases/compiler/regularExpressionScanning.ts index f153631ed6d6d..ad2ebc669ef2d 100644 --- a/tests/cases/compiler/regularExpressionScanning.ts +++ b/tests/cases/compiler/regularExpressionScanning.ts @@ -11,8 +11,8 @@ const regexes: RegExp[] = [ /\2/, /(hi)\1/, /(hi) (hello) \2/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/, - /\2()(\12)(foo)\1\0[\0\1\01\123](\3\03)\5\005/u, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/, + /\2()(\12)(foo)\1\0[\0\1\01\123\08\8](\3\03)\5\005\9\009/u, /(?)((?bar)bar)(?baz)|(foo(?foo))(?)/, /(\k)\k(?foo)|(?)((?)|(bar(?bar)))/, // Quantifiers From c72f92faf22238f5498b0242a99c028770cabd31 Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Tue, 28 May 2024 10:57:10 +0800 Subject: [PATCH 09/10] Fix Behavior Related to `namedCaptureGroups` --- src/compiler/scanner.ts | 5 +++-- tests/baselines/reference/regularExpressionAnnexB.errors.txt | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index b06fa55b93360..3d1af3309e943 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -2490,7 +2490,8 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean inCharacterClass = false; } else if ( - ch === CharacterCodes.openParen + !inCharacterClass + && ch === CharacterCodes.openParen && charCodeChecked(pos + 1) === CharacterCodes.question && charCodeChecked(pos + 2) === CharacterCodes.lessThan && charCodeChecked(pos + 3) !== CharacterCodes.equals @@ -2877,7 +2878,7 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean scanGroupName(/*isReference*/ true); scanExpectedChar(CharacterCodes.greaterThan); } - else if (namedCaptureGroups) { + else if (anyUnicodeModeOrNonAnnexB || namedCaptureGroups) { error(Diagnostics.k_must_be_followed_by_a_capturing_group_name_enclosed_in_angle_brackets, pos - 2, 2); } break; diff --git a/tests/baselines/reference/regularExpressionAnnexB.errors.txt b/tests/baselines/reference/regularExpressionAnnexB.errors.txt index 26788ab87eb68..f08ceaf89590a 100644 --- a/tests/baselines/reference/regularExpressionAnnexB.errors.txt +++ b/tests/baselines/reference/regularExpressionAnnexB.errors.txt @@ -7,6 +7,7 @@ regularExpressionAnnexB.ts(3,29): error TS1125: Hexadecimal digit expected. regularExpressionAnnexB.ts(7,4): error TS1535: This character cannot be escaped in a regular expression. regularExpressionAnnexB.ts(7,8): error TS1125: Hexadecimal digit expected. regularExpressionAnnexB.ts(7,10): error TS1512: '\c' must be followed by an ASCII letter. +regularExpressionAnnexB.ts(7,12): error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. regularExpressionAnnexB.ts(7,14): error TS1535: This character cannot be escaped in a regular expression. regularExpressionAnnexB.ts(7,18): error TS1535: This character cannot be escaped in a regular expression. regularExpressionAnnexB.ts(7,22): error TS1125: Hexadecimal digit expected. @@ -73,7 +74,7 @@ regularExpressionAnnexB.ts(42,5): error TS1506: Numbers out of order in quantifi regularExpressionAnnexB.ts(42,10): error TS1507: There is nothing available for repetition. -==== regularExpressionAnnexB.ts (73 errors) ==== +==== regularExpressionAnnexB.ts (74 errors) ==== const regexes: RegExp[] = [ /\q\u\i\c\k\_\f\o\x\-\j\u\m\p\s/, @@ -99,6 +100,8 @@ regularExpressionAnnexB.ts(42,10): error TS1507: There is nothing available for !!! error TS1125: Hexadecimal digit expected. ~~ !!! error TS1512: '\c' must be followed by an ASCII letter. + ~~ +!!! error TS1510: '\k' must be followed by a capturing group name enclosed in angle brackets. ~~ !!! error TS1535: This character cannot be escaped in a regular expression. ~~ From 70a321417c5a705e23c037ce0229f6e8a7ce3b58 Mon Sep 17 00:00:00 2001 From: graphemecluster Date: Tue, 28 May 2024 11:31:36 +0800 Subject: [PATCH 10/10] Clarify why nested character classes should not be considered in the first pass --- src/compiler/scanner.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 3d1af3309e943..ad6928331f26d 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -2456,6 +2456,9 @@ export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean let namedCaptureGroups = false; // Although nested character classes are allowed in Unicode Sets mode, // an unescaped slash is nevertheless invalid even in a character class in any Unicode mode. + // This is indicated by Section 12.9.5 Regular Expression Literals of the specification, + // where nested character classes are not considered at all. (A `[` RegularExpressionClassChar + // does nothing in a RegularExpressionClass, and a `]` always closes the class.) // Additionally, parsing nested character classes will misinterpret regexes like `/[[]/` // as unterminated, consuming characters beyond the slash. (This even applies to `/[[]/v`, // which should be parsed as a well-terminated regex with an incomplete character class.)