From b19624804941679bfd641c7c81bd9f17a11d803e Mon Sep 17 00:00:00 2001 From: uhyo Date: Sun, 11 Oct 2020 00:26:20 +0900 Subject: [PATCH 1/6] remove invalid escape error from tagged template literals --- src/compiler/parser.ts | 27 ++++++----- src/compiler/scanner.ts | 105 ++++++++++++++++++++++------------------ 2 files changed, 75 insertions(+), 57 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1d42346123b87..303f477d3658d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1418,8 +1418,8 @@ namespace ts { return currentToken = scanner.reScanTemplateToken(isTaggedTemplate); } - function reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind { - return currentToken = scanner.reScanTemplateHeadOrNoSubstitutionTemplate(); + function reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate: boolean): SyntaxKind { + return currentToken = scanner.reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate); } function reScanLessThanToken(): SyntaxKind { @@ -2631,11 +2631,12 @@ namespace ts { return createNodeArray(list, pos); } - function parseTemplateExpression(isTaggedTemplate: boolean): TemplateExpression { + function parseTemplateExpression(isTaggedTemplate: boolean, containsInvalidEscape: boolean): TemplateExpression { const pos = getNodePos(); + console.log({ isTaggedTemplate, containsInvalidEscape }); return finishNode( factory.createTemplateExpression( - parseTemplateHead(isTaggedTemplate), + parseTemplateHead(isTaggedTemplate, containsInvalidEscape), parseTemplateSpans(isTaggedTemplate) ), pos @@ -2646,7 +2647,7 @@ namespace ts { const pos = getNodePos(); return finishNode( factory.createTemplateLiteralType( - parseTemplateHead(/*isTaggedTemplate*/ false), + parseTemplateHead(/*isTaggedTemplate*/ false, /* containsInvalidEscape */ false), parseTemplateTypeSpans() ), pos @@ -2702,9 +2703,9 @@ namespace ts { return parseLiteralLikeNode(token()); } - function parseTemplateHead(isTaggedTemplate: boolean): TemplateHead { - if (isTaggedTemplate) { - reScanTemplateHeadOrNoSubstitutionTemplate(); + function parseTemplateHead(isTaggedTemplate: boolean, containsInvalidEscape: boolean): TemplateHead { + if (isTaggedTemplate || containsInvalidEscape) { + reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate); } const fragment = parseLiteralLikeNode(token()); Debug.assert(fragment.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind"); @@ -5239,8 +5240,8 @@ namespace ts { tag, typeArguments, token() === SyntaxKind.NoSubstitutionTemplateLiteral ? - (reScanTemplateHeadOrNoSubstitutionTemplate(), parseLiteralNode() as NoSubstitutionTemplateLiteral) : - parseTemplateExpression(/*isTaggedTemplate*/ true) + (reScanTemplateHeadOrNoSubstitutionTemplate(true), parseLiteralNode() as NoSubstitutionTemplateLiteral) : + parseTemplateExpression(/*isTaggedTemplate*/ true, !!(scanner.getTokenFlags() & TokenFlags.ContainsInvalidEscape)) ); if (questionDotToken || tag.flags & NodeFlags.OptionalChain) { (tagExpression as Mutable).flags |= NodeFlags.OptionalChain; @@ -5372,7 +5373,11 @@ namespace ts { case SyntaxKind.NumericLiteral: case SyntaxKind.BigIntLiteral: case SyntaxKind.StringLiteral: + return parseLiteralNode(); case SyntaxKind.NoSubstitutionTemplateLiteral: + if (scanner.getTokenFlags() & TokenFlags.ContainsInvalidEscape) { + reScanTemplateHeadOrNoSubstitutionTemplate(/* isTaggedTemplate */ false) + } return parseLiteralNode(); case SyntaxKind.ThisKeyword: case SyntaxKind.SuperKeyword: @@ -5408,7 +5413,7 @@ namespace ts { } break; case SyntaxKind.TemplateHead: - return parseTemplateExpression(/* isTaggedTemplate */ false); + return parseTemplateExpression(/* isTaggedTemplate */ false, !!(scanner.getTokenFlags() & TokenFlags.ContainsInvalidEscape)); } return parseIdentifier(Diagnostics.Expression_expected); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 79b414d3d4c09..46308fcac86f4 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -36,7 +36,7 @@ namespace ts { reScanSlashToken(): SyntaxKind; reScanAsteriskEqualsToken(): SyntaxKind; reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind; - reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind; + reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate: boolean): SyntaxKind; scanJsxIdentifier(): SyntaxKind; scanJsxAttributeValue(): SyntaxKind; reScanJsxAttributeValue(): SyntaxKind; @@ -1208,7 +1208,7 @@ namespace ts { } if (ch === CharacterCodes.backslash && !jsxAttributeString) { result += text.substring(start, pos); - result += scanEscapeSequence(); + result += scanEscapeSequence(false, true); start = pos; continue; } @@ -1227,7 +1227,7 @@ namespace ts { * Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or * a literal component of a TemplateExpression. */ - function scanTemplateAndSetTokenValue(isTaggedTemplate: boolean): SyntaxKind { + function scanTemplateAndSetTokenValue(isTaggedTemplate: boolean, shouldEmitInvalidEscapeError: boolean): SyntaxKind { const startedWithBacktick = text.charCodeAt(pos) === CharacterCodes.backtick; pos++; @@ -1265,7 +1265,7 @@ namespace ts { // Escape character if (currChar === CharacterCodes.backslash) { contents += text.substring(start, pos); - contents += scanEscapeSequence(isTaggedTemplate); + contents += scanEscapeSequence(isTaggedTemplate, shouldEmitInvalidEscapeError); start = pos; continue; } @@ -1294,7 +1294,7 @@ namespace ts { return resultingToken; } - function scanEscapeSequence(isTaggedTemplate?: boolean): string { + function scanEscapeSequence(isTaggedTemplate: boolean, shouldEmitInvalidEscapeError: boolean): string { const start = pos; pos++; if (pos >= end) { @@ -1306,10 +1306,12 @@ namespace ts { switch (ch) { case CharacterCodes._0: // '\01' - if (isTaggedTemplate && pos < end && isDigit(text.charCodeAt(pos))) { - pos++; + if (pos < end && isDigit(text.charCodeAt(pos))) { tokenFlags |= TokenFlags.ContainsInvalidEscape; - return text.substring(start, pos); + if (isTaggedTemplate) { + pos++; + return text.substring(start, pos); + } } return "\0"; case CharacterCodes.b: @@ -1329,14 +1331,15 @@ namespace ts { case CharacterCodes.doubleQuote: return "\""; case CharacterCodes.u: - if (isTaggedTemplate) { - // '\u' or '\u0' or '\u00' or '\u000' - for (let escapePos = pos; escapePos < pos + 4; escapePos++) { - if (escapePos < end && !isHexDigit(text.charCodeAt(escapePos)) && text.charCodeAt(escapePos) !== CharacterCodes.openBrace) { + // '\u' or '\u0' or '\u00' or '\u000' + for (let escapePos = pos; escapePos < pos + 4; escapePos++) { + if (escapePos < end && !isHexDigit(text.charCodeAt(escapePos)) && text.charCodeAt(escapePos) !== CharacterCodes.openBrace) { + tokenFlags |= TokenFlags.ContainsInvalidEscape; + if (isTaggedTemplate) { pos = escapePos; - tokenFlags |= TokenFlags.ContainsInvalidEscape; return text.substring(start, pos); } + break; } } // '\u{DDDDDDDD}' @@ -1344,47 +1347,49 @@ namespace ts { pos++; // '\u{' - if (isTaggedTemplate && !isHexDigit(text.charCodeAt(pos))) { + if (!isHexDigit(text.charCodeAt(pos))) { tokenFlags |= TokenFlags.ContainsInvalidEscape; - return text.substring(start, pos); + if (isTaggedTemplate) { + return text.substring(start, pos); + } } - if (isTaggedTemplate) { - const savePos = pos; - const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); - const escapedValue = escapedValueString ? parseInt(escapedValueString, 16) : -1; + const savePos = pos; + const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); + const escapedValue = escapedValueString ? parseInt(escapedValueString, 16) : -1; - // '\u{Not Code Point' or '\u{CodePoint' - if (!isCodePoint(escapedValue) || text.charCodeAt(pos) !== CharacterCodes.closeBrace) { - tokenFlags |= TokenFlags.ContainsInvalidEscape; + // '\u{Not Code Point' or '\u{CodePoint' + if (!isCodePoint(escapedValue) || text.charCodeAt(pos) !== CharacterCodes.closeBrace) { + tokenFlags |= TokenFlags.ContainsInvalidEscape; + if (isTaggedTemplate) { return text.substring(start, pos); } - else { - pos = savePos; - } } + pos = savePos; tokenFlags |= TokenFlags.ExtendedUnicodeEscape; - return scanExtendedUnicodeEscape(); + return scanExtendedUnicodeEscape(shouldEmitInvalidEscapeError); } tokenFlags |= TokenFlags.UnicodeEscape; // '\uDDDD' - return scanHexadecimalEscape(/*numDigits*/ 4); + return scanHexadecimalEscape(/*numDigits*/ 4, shouldEmitInvalidEscapeError); case CharacterCodes.x: - if (isTaggedTemplate) { - if (!isHexDigit(text.charCodeAt(pos))) { - tokenFlags |= TokenFlags.ContainsInvalidEscape; + if (!isHexDigit(text.charCodeAt(pos))) { + tokenFlags |= TokenFlags.ContainsInvalidEscape; + if (isTaggedTemplate) { return text.substring(start, pos); } - else if (!isHexDigit(text.charCodeAt(pos + 1))) { + } + else if (!isHexDigit(text.charCodeAt(pos + 1))) { + tokenFlags |= TokenFlags.ContainsInvalidEscape; + if (isTaggedTemplate) { pos++; - tokenFlags |= TokenFlags.ContainsInvalidEscape; return text.substring(start, pos); } } // '\xDD' - return scanHexadecimalEscape(/*numDigits*/ 2); + return scanHexadecimalEscape(/*numDigits*/ 2, shouldEmitInvalidEscapeError); // when encountering a LineContinuation (i.e. a backslash and a line terminator sequence), // the line terminator is interpreted to be "the empty code unit sequence". @@ -1402,30 +1407,36 @@ namespace ts { } } - function scanHexadecimalEscape(numDigits: number): string { + function scanHexadecimalEscape(numDigits: number, shouldEmitInvalidEscapeError: boolean): string { const escapedValue = scanExactNumberOfHexDigits(numDigits, /*canHaveSeparators*/ false); if (escapedValue >= 0) { return String.fromCharCode(escapedValue); } else { - error(Diagnostics.Hexadecimal_digit_expected); + if (shouldEmitInvalidEscapeError) { + error(Diagnostics.Hexadecimal_digit_expected); + } return ""; } } - function scanExtendedUnicodeEscape(): string { + function scanExtendedUnicodeEscape(shouldEmitInvalidEscapeError: boolean): string { const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); const escapedValue = escapedValueString ? parseInt(escapedValueString, 16) : -1; let isInvalidExtendedEscape = false; // Validate the value of the digit if (escapedValue < 0) { - error(Diagnostics.Hexadecimal_digit_expected); + if (shouldEmitInvalidEscapeError) { + error(Diagnostics.Hexadecimal_digit_expected); + } isInvalidExtendedEscape = true; } else if (escapedValue > 0x10FFFF) { - error(Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive); + if (shouldEmitInvalidEscapeError) { + error(Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive); + } isInvalidExtendedEscape = true; } @@ -1438,7 +1449,9 @@ namespace ts { pos++; } else { - error(Diagnostics.Unterminated_Unicode_escape_sequence); + if (shouldEmitInvalidEscapeError) { + error(Diagnostics.Unterminated_Unicode_escape_sequence); + } isInvalidExtendedEscape = true; } @@ -1488,7 +1501,7 @@ namespace ts { if (ch >= 0 && isIdentifierPart(ch, languageVersion)) { pos += 3; tokenFlags |= TokenFlags.ExtendedUnicodeEscape; - result += scanExtendedUnicodeEscape(); + result += scanExtendedUnicodeEscape(true); start = pos; continue; } @@ -1673,7 +1686,7 @@ namespace ts { tokenValue = scanString(); return token = SyntaxKind.StringLiteral; case CharacterCodes.backtick: - return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ false); + return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ false, false); case CharacterCodes.percent: if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { return pos += 2, token = SyntaxKind.PercentEqualsToken; @@ -2008,7 +2021,7 @@ namespace ts { if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) { pos += 3; tokenFlags |= TokenFlags.ExtendedUnicodeEscape; - tokenValue = scanExtendedUnicodeEscape() + scanIdentifierParts(); + tokenValue = scanExtendedUnicodeEscape(true) + scanIdentifierParts(); return token = getIdentifierToken(); } @@ -2216,12 +2229,12 @@ namespace ts { function reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind { Debug.assert(token === SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'"); pos = tokenPos; - return token = scanTemplateAndSetTokenValue(isTaggedTemplate); + return token = scanTemplateAndSetTokenValue(isTaggedTemplate, true); } - function reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind { + function reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate: boolean): SyntaxKind { pos = tokenPos; - return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ true); + return token = scanTemplateAndSetTokenValue(isTaggedTemplate, true); } function reScanJsxToken(allowMultilineJsxText = true): JsxTokenSyntaxKind { @@ -2429,7 +2442,7 @@ namespace ts { if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) { pos += 3; tokenFlags |= TokenFlags.ExtendedUnicodeEscape; - tokenValue = scanExtendedUnicodeEscape() + scanIdentifierParts(); + tokenValue = scanExtendedUnicodeEscape(true) + scanIdentifierParts(); return token = getIdentifierToken(); } From a2ba977c172a1adbbf98269b3d7f14a432bc2b21 Mon Sep 17 00:00:00 2001 From: uhyo Date: Sun, 11 Oct 2020 00:33:11 +0900 Subject: [PATCH 2/6] add tests --- .../templateLiteralInvalidEscape.errors.txt | 55 ++++++++++ .../reference/templateLiteralInvalidEscape.js | 62 +++++++++++ .../templateLiteralInvalidEscape.symbols | 55 ++++++++++ .../templateLiteralInvalidEscape.types | 102 ++++++++++++++++++ .../compiler/templateLiteralInvalidEscape.ts | 27 +++++ 5 files changed, 301 insertions(+) create mode 100644 tests/baselines/reference/templateLiteralInvalidEscape.errors.txt create mode 100644 tests/baselines/reference/templateLiteralInvalidEscape.js create mode 100644 tests/baselines/reference/templateLiteralInvalidEscape.symbols create mode 100644 tests/baselines/reference/templateLiteralInvalidEscape.types create mode 100644 tests/cases/compiler/templateLiteralInvalidEscape.ts diff --git a/tests/baselines/reference/templateLiteralInvalidEscape.errors.txt b/tests/baselines/reference/templateLiteralInvalidEscape.errors.txt new file mode 100644 index 0000000000000..9e4a8fea63a93 --- /dev/null +++ b/tests/baselines/reference/templateLiteralInvalidEscape.errors.txt @@ -0,0 +1,55 @@ +tests/cases/compiler/templateLiteralInvalidEscape.ts(11,4): error TS1125: Hexadecimal digit expected. +tests/cases/compiler/templateLiteralInvalidEscape.ts(12,5): error TS1125: Hexadecimal digit expected. +tests/cases/compiler/templateLiteralInvalidEscape.ts(13,6): error TS1125: Hexadecimal digit expected. +tests/cases/compiler/templateLiteralInvalidEscape.ts(14,5): error TS1125: Hexadecimal digit expected. +tests/cases/compiler/templateLiteralInvalidEscape.ts(23,8): error TS1125: Hexadecimal digit expected. +tests/cases/compiler/templateLiteralInvalidEscape.ts(24,9): error TS1125: Hexadecimal digit expected. +tests/cases/compiler/templateLiteralInvalidEscape.ts(25,10): error TS1125: Hexadecimal digit expected. +tests/cases/compiler/templateLiteralInvalidEscape.ts(26,9): error TS1125: Hexadecimal digit expected. + + +==== tests/cases/compiler/templateLiteralInvalidEscape.ts (8 errors) ==== + function raw(arr: TemplateStringsArray, ...args: unknown[]) { + return arr.raw; + } + + raw`\x`; + raw`\x0`; + raw`\u11`; + raw`\u{}`; + raw`\0123`; + + `\x`; + +!!! error TS1125: Hexadecimal digit expected. + `\x0`; + +!!! error TS1125: Hexadecimal digit expected. + `\u11`; + +!!! error TS1125: Hexadecimal digit expected. + `\u{}`; + +!!! error TS1125: Hexadecimal digit expected. + `\0123`; + + raw`${0}\x`; + raw`${0}\x0`; + raw`${0}\u11`; + raw`${0}\u{}`; + raw`${0}\0123`; + + `${0}\x`; + +!!! error TS1125: Hexadecimal digit expected. + `${0}\x0`; + +!!! error TS1125: Hexadecimal digit expected. + `${0}\u11`; + +!!! error TS1125: Hexadecimal digit expected. + `${0}\u{}`; + +!!! error TS1125: Hexadecimal digit expected. + `${0}\0123`; + \ No newline at end of file diff --git a/tests/baselines/reference/templateLiteralInvalidEscape.js b/tests/baselines/reference/templateLiteralInvalidEscape.js new file mode 100644 index 0000000000000..57e15f3398800 --- /dev/null +++ b/tests/baselines/reference/templateLiteralInvalidEscape.js @@ -0,0 +1,62 @@ +//// [templateLiteralInvalidEscape.ts] +function raw(arr: TemplateStringsArray, ...args: unknown[]) { + return arr.raw; +} + +raw`\x`; +raw`\x0`; +raw`\u11`; +raw`\u{}`; +raw`\0123`; + +`\x`; +`\x0`; +`\u11`; +`\u{}`; +`\0123`; + +raw`${0}\x`; +raw`${0}\x0`; +raw`${0}\u11`; +raw`${0}\u{}`; +raw`${0}\0123`; + +`${0}\x`; +`${0}\x0`; +`${0}\u11`; +`${0}\u{}`; +`${0}\0123`; + + +//// [templateLiteralInvalidEscape.js] +var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; +function raw(arr) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + return arr.raw; +} +raw(__makeTemplateObject([void 0], ["\\x"])); +raw(__makeTemplateObject([void 0], ["\\x0"])); +raw(__makeTemplateObject([void 0], ["\\u11"])); +raw(__makeTemplateObject([void 0], ["\\u{}"])); +raw(__makeTemplateObject([void 0], ["\\0123"])); +""; +""; +""; +""; +"\x00123"; +raw(__makeTemplateObject(["", void 0], ["", "\\x"]), 0); +raw(__makeTemplateObject(["", void 0], ["", "\\x0"]), 0); +raw(__makeTemplateObject(["", void 0], ["", "\\u11"]), 0); +raw(__makeTemplateObject(["", void 0], ["", "\\u{}"]), 0); +raw(__makeTemplateObject(["", void 0], ["", "\\0123"]), 0); +"" + 0; +"" + 0; +"" + 0; +"" + 0; +0 + "\x00123"; diff --git a/tests/baselines/reference/templateLiteralInvalidEscape.symbols b/tests/baselines/reference/templateLiteralInvalidEscape.symbols new file mode 100644 index 0000000000000..37e44a2edb960 --- /dev/null +++ b/tests/baselines/reference/templateLiteralInvalidEscape.symbols @@ -0,0 +1,55 @@ +=== tests/cases/compiler/templateLiteralInvalidEscape.ts === +function raw(arr: TemplateStringsArray, ...args: unknown[]) { +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) +>arr : Symbol(arr, Decl(templateLiteralInvalidEscape.ts, 0, 13)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>args : Symbol(args, Decl(templateLiteralInvalidEscape.ts, 0, 39)) + + return arr.raw; +>arr.raw : Symbol(TemplateStringsArray.raw, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(templateLiteralInvalidEscape.ts, 0, 13)) +>raw : Symbol(TemplateStringsArray.raw, Decl(lib.es5.d.ts, --, --)) +} + +raw`\x`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +raw`\x0`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +raw`\u11`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +raw`\u{}`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +raw`\0123`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +`\x`; +`\x0`; +`\u11`; +`\u{}`; +`\0123`; + +raw`${0}\x`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +raw`${0}\x0`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +raw`${0}\u11`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +raw`${0}\u{}`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +raw`${0}\0123`; +>raw : Symbol(raw, Decl(templateLiteralInvalidEscape.ts, 0, 0)) + +`${0}\x`; +`${0}\x0`; +`${0}\u11`; +`${0}\u{}`; +`${0}\0123`; + diff --git a/tests/baselines/reference/templateLiteralInvalidEscape.types b/tests/baselines/reference/templateLiteralInvalidEscape.types new file mode 100644 index 0000000000000..7cbf344917c36 --- /dev/null +++ b/tests/baselines/reference/templateLiteralInvalidEscape.types @@ -0,0 +1,102 @@ +=== tests/cases/compiler/templateLiteralInvalidEscape.ts === +function raw(arr: TemplateStringsArray, ...args: unknown[]) { +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>arr : TemplateStringsArray +>args : unknown[] + + return arr.raw; +>arr.raw : readonly string[] +>arr : TemplateStringsArray +>raw : readonly string[] +} + +raw`\x`; +>raw`\x` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`\x` : "\\x" + +raw`\x0`; +>raw`\x0` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`\x0` : "\\x0" + +raw`\u11`; +>raw`\u11` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`\u11` : "\\u11" + +raw`\u{}`; +>raw`\u{}` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`\u{}` : "\\u{}" + +raw`\0123`; +>raw`\0123` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`\0123` : "\\0123" + +`\x`; +>`\x` : "" + +`\x0`; +>`\x0` : "" + +`\u11`; +>`\u11` : "" + +`\u{}`; +>`\u{}` : "" + +`\0123`; +>`\0123` : "\x00123" + +raw`${0}\x`; +>raw`${0}\x` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`${0}\x` : string +>0 : 0 + +raw`${0}\x0`; +>raw`${0}\x0` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`${0}\x0` : string +>0 : 0 + +raw`${0}\u11`; +>raw`${0}\u11` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`${0}\u11` : string +>0 : 0 + +raw`${0}\u{}`; +>raw`${0}\u{}` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`${0}\u{}` : string +>0 : 0 + +raw`${0}\0123`; +>raw`${0}\0123` : readonly string[] +>raw : (arr: TemplateStringsArray, ...args: unknown[]) => readonly string[] +>`${0}\0123` : string +>0 : 0 + +`${0}\x`; +>`${0}\x` : string +>0 : 0 + +`${0}\x0`; +>`${0}\x0` : string +>0 : 0 + +`${0}\u11`; +>`${0}\u11` : string +>0 : 0 + +`${0}\u{}`; +>`${0}\u{}` : string +>0 : 0 + +`${0}\0123`; +>`${0}\0123` : string +>0 : 0 + diff --git a/tests/cases/compiler/templateLiteralInvalidEscape.ts b/tests/cases/compiler/templateLiteralInvalidEscape.ts new file mode 100644 index 0000000000000..6515fb06ea9c1 --- /dev/null +++ b/tests/cases/compiler/templateLiteralInvalidEscape.ts @@ -0,0 +1,27 @@ +function raw(arr: TemplateStringsArray, ...args: unknown[]) { + return arr.raw; +} + +raw`\x`; +raw`\x0`; +raw`\u11`; +raw`\u{}`; +raw`\0123`; + +`\x`; +`\x0`; +`\u11`; +`\u{}`; +`\0123`; + +raw`${0}\x`; +raw`${0}\x0`; +raw`${0}\u11`; +raw`${0}\u{}`; +raw`${0}\0123`; + +`${0}\x`; +`${0}\x0`; +`${0}\u11`; +`${0}\u{}`; +`${0}\0123`; From 602d4e1737c4ba7fa4ff30c4459138df6890cd96 Mon Sep 17 00:00:00 2001 From: uhyo Date: Sun, 11 Oct 2020 00:44:18 +0900 Subject: [PATCH 3/6] Emit errors to octal escape sequences in template strings --- src/compiler/diagnosticMessages.json | 5 ++++- src/compiler/parser.ts | 1 - src/compiler/scanner.ts | 3 +++ .../reference/templateLiteralInvalidEscape.errors.txt | 8 +++++++- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b0d3edd52bdb5..a7861513626bf 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1360,7 +1360,10 @@ "category": "Error", "code": 1432 }, - + "Octal escape sequences are not allowed in template strings.": { + "category": "Error", + "code": 1433 + }, "The types of '{0}' are incompatible between these types.": { "category": "Error", "code": 2200 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 303f477d3658d..545d5f2d9817a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2633,7 +2633,6 @@ namespace ts { function parseTemplateExpression(isTaggedTemplate: boolean, containsInvalidEscape: boolean): TemplateExpression { const pos = getNodePos(); - console.log({ isTaggedTemplate, containsInvalidEscape }); return finishNode( factory.createTemplateExpression( parseTemplateHead(isTaggedTemplate, containsInvalidEscape), diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 46308fcac86f4..2bd3461e82fdc 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1312,6 +1312,9 @@ namespace ts { pos++; return text.substring(start, pos); } + if (shouldEmitInvalidEscapeError) { + error(Diagnostics.Octal_escape_sequences_are_not_allowed_in_template_strings); + } } return "\0"; case CharacterCodes.b: diff --git a/tests/baselines/reference/templateLiteralInvalidEscape.errors.txt b/tests/baselines/reference/templateLiteralInvalidEscape.errors.txt index 9e4a8fea63a93..22e63535a44ea 100644 --- a/tests/baselines/reference/templateLiteralInvalidEscape.errors.txt +++ b/tests/baselines/reference/templateLiteralInvalidEscape.errors.txt @@ -2,13 +2,15 @@ tests/cases/compiler/templateLiteralInvalidEscape.ts(11,4): error TS1125: Hexade tests/cases/compiler/templateLiteralInvalidEscape.ts(12,5): error TS1125: Hexadecimal digit expected. tests/cases/compiler/templateLiteralInvalidEscape.ts(13,6): error TS1125: Hexadecimal digit expected. tests/cases/compiler/templateLiteralInvalidEscape.ts(14,5): error TS1125: Hexadecimal digit expected. +tests/cases/compiler/templateLiteralInvalidEscape.ts(15,4): error TS1433: Octal escape sequences are not allowed in template strings. tests/cases/compiler/templateLiteralInvalidEscape.ts(23,8): error TS1125: Hexadecimal digit expected. tests/cases/compiler/templateLiteralInvalidEscape.ts(24,9): error TS1125: Hexadecimal digit expected. tests/cases/compiler/templateLiteralInvalidEscape.ts(25,10): error TS1125: Hexadecimal digit expected. tests/cases/compiler/templateLiteralInvalidEscape.ts(26,9): error TS1125: Hexadecimal digit expected. +tests/cases/compiler/templateLiteralInvalidEscape.ts(27,8): error TS1433: Octal escape sequences are not allowed in template strings. -==== tests/cases/compiler/templateLiteralInvalidEscape.ts (8 errors) ==== +==== tests/cases/compiler/templateLiteralInvalidEscape.ts (10 errors) ==== function raw(arr: TemplateStringsArray, ...args: unknown[]) { return arr.raw; } @@ -32,6 +34,8 @@ tests/cases/compiler/templateLiteralInvalidEscape.ts(26,9): error TS1125: Hexade !!! error TS1125: Hexadecimal digit expected. `\0123`; + +!!! error TS1433: Octal escape sequences are not allowed in template strings. raw`${0}\x`; raw`${0}\x0`; @@ -52,4 +56,6 @@ tests/cases/compiler/templateLiteralInvalidEscape.ts(26,9): error TS1125: Hexade !!! error TS1125: Hexadecimal digit expected. `${0}\0123`; + +!!! error TS1433: Octal escape sequences are not allowed in template strings. \ No newline at end of file From 250de23c0fe066be8c40a343a2afbe0b2100193f Mon Sep 17 00:00:00 2001 From: uhyo Date: Sun, 11 Oct 2020 00:55:27 +0900 Subject: [PATCH 4/6] accept baseline changes --- src/compiler/scanner.ts | 6 +++--- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- ...mplateEscapeSequences(target=es2015).errors.txt | 14 +------------- ...dTemplateEscapeSequences(target=es5).errors.txt | 14 +------------- ...mplateEscapeSequences(target=esnext).errors.txt | 14 +------------- 6 files changed, 8 insertions(+), 44 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 2bd3461e82fdc..35459628a3766 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -36,7 +36,7 @@ namespace ts { reScanSlashToken(): SyntaxKind; reScanAsteriskEqualsToken(): SyntaxKind; reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind; - reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate: boolean): SyntaxKind; + reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate?: boolean): SyntaxKind; scanJsxIdentifier(): SyntaxKind; scanJsxAttributeValue(): SyntaxKind; reScanJsxAttributeValue(): SyntaxKind; @@ -2235,9 +2235,9 @@ namespace ts { return token = scanTemplateAndSetTokenValue(isTaggedTemplate, true); } - function reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate: boolean): SyntaxKind { + function reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate?: boolean): SyntaxKind { pos = tokenPos; - return token = scanTemplateAndSetTokenValue(isTaggedTemplate, true); + return token = scanTemplateAndSetTokenValue(isTaggedTemplate || false, true); } function reScanJsxToken(allowMultilineJsxText = true): JsxTokenSyntaxKind { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index a2ff8fc1ea29a..3c46dd41c5b0a 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4011,7 +4011,7 @@ declare namespace ts { reScanSlashToken(): SyntaxKind; reScanAsteriskEqualsToken(): SyntaxKind; reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind; - reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind; + reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate: boolean): SyntaxKind; scanJsxIdentifier(): SyntaxKind; scanJsxAttributeValue(): SyntaxKind; reScanJsxAttributeValue(): SyntaxKind; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0b2d291eeddb5..25aef2a5cf0f0 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4011,7 +4011,7 @@ declare namespace ts { reScanSlashToken(): SyntaxKind; reScanAsteriskEqualsToken(): SyntaxKind; reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind; - reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind; + reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate: boolean): SyntaxKind; scanJsxIdentifier(): SyntaxKind; scanJsxAttributeValue(): SyntaxKind; reScanJsxAttributeValue(): SyntaxKind; diff --git a/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=es2015).errors.txt b/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=es2015).errors.txt index c8846ae349714..e03787d7799d5 100644 --- a/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=es2015).errors.txt +++ b/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=es2015).errors.txt @@ -1,13 +1,9 @@ -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(7,18): error TS1125: Hexadecimal digit expected. tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(8,15): error TS1125: Hexadecimal digit expected. tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(8,33): error TS1125: Hexadecimal digit expected. tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(8,75): error TS1125: Hexadecimal digit expected. -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,18): error TS1125: Hexadecimal digit expected. -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,27): error TS1125: Hexadecimal digit expected. -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,51): error TS1125: Hexadecimal digit expected. -==== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts (7 errors) ==== +==== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts (3 errors) ==== function tag (str: any, ...args: any[]): any { return str } @@ -15,8 +11,6 @@ tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,51): er const a = tag`123` const b = tag`123 ${100}` const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; - -!!! error TS1125: Hexadecimal digit expected. const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate !!! error TS1125: Hexadecimal digit expected. @@ -25,12 +19,6 @@ tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,51): er !!! error TS1125: Hexadecimal digit expected. const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate - -!!! error TS1125: Hexadecimal digit expected. - -!!! error TS1125: Hexadecimal digit expected. - -!!! error TS1125: Hexadecimal digit expected. const a1 = tag`${ 100 }\0` // \0 const a2 = tag`${ 100 }\00` // \\00 diff --git a/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=es5).errors.txt b/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=es5).errors.txt index c8846ae349714..e03787d7799d5 100644 --- a/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=es5).errors.txt +++ b/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=es5).errors.txt @@ -1,13 +1,9 @@ -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(7,18): error TS1125: Hexadecimal digit expected. tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(8,15): error TS1125: Hexadecimal digit expected. tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(8,33): error TS1125: Hexadecimal digit expected. tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(8,75): error TS1125: Hexadecimal digit expected. -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,18): error TS1125: Hexadecimal digit expected. -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,27): error TS1125: Hexadecimal digit expected. -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,51): error TS1125: Hexadecimal digit expected. -==== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts (7 errors) ==== +==== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts (3 errors) ==== function tag (str: any, ...args: any[]): any { return str } @@ -15,8 +11,6 @@ tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,51): er const a = tag`123` const b = tag`123 ${100}` const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; - -!!! error TS1125: Hexadecimal digit expected. const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate !!! error TS1125: Hexadecimal digit expected. @@ -25,12 +19,6 @@ tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,51): er !!! error TS1125: Hexadecimal digit expected. const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate - -!!! error TS1125: Hexadecimal digit expected. - -!!! error TS1125: Hexadecimal digit expected. - -!!! error TS1125: Hexadecimal digit expected. const a1 = tag`${ 100 }\0` // \0 const a2 = tag`${ 100 }\00` // \\00 diff --git a/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=esnext).errors.txt b/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=esnext).errors.txt index c8846ae349714..e03787d7799d5 100644 --- a/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=esnext).errors.txt +++ b/tests/baselines/reference/invalidTaggedTemplateEscapeSequences(target=esnext).errors.txt @@ -1,13 +1,9 @@ -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(7,18): error TS1125: Hexadecimal digit expected. tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(8,15): error TS1125: Hexadecimal digit expected. tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(8,33): error TS1125: Hexadecimal digit expected. tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(8,75): error TS1125: Hexadecimal digit expected. -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,18): error TS1125: Hexadecimal digit expected. -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,27): error TS1125: Hexadecimal digit expected. -tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,51): error TS1125: Hexadecimal digit expected. -==== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts (7 errors) ==== +==== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts (3 errors) ==== function tag (str: any, ...args: any[]): any { return str } @@ -15,8 +11,6 @@ tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,51): er const a = tag`123` const b = tag`123 ${100}` const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; - -!!! error TS1125: Hexadecimal digit expected. const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate !!! error TS1125: Hexadecimal digit expected. @@ -25,12 +19,6 @@ tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts(9,51): er !!! error TS1125: Hexadecimal digit expected. const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate - -!!! error TS1125: Hexadecimal digit expected. - -!!! error TS1125: Hexadecimal digit expected. - -!!! error TS1125: Hexadecimal digit expected. const a1 = tag`${ 100 }\0` // \0 const a2 = tag`${ 100 }\00` // \\00 From f3e49910214a120de74dc2742326f80cedf7a860 Mon Sep 17 00:00:00 2001 From: uhyo Date: Sun, 11 Oct 2020 01:00:07 +0900 Subject: [PATCH 5/6] fix lint errors --- src/compiler/parser.ts | 4 ++-- src/compiler/scanner.ts | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 545d5f2d9817a..67d6a400c36f6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5239,7 +5239,7 @@ namespace ts { tag, typeArguments, token() === SyntaxKind.NoSubstitutionTemplateLiteral ? - (reScanTemplateHeadOrNoSubstitutionTemplate(true), parseLiteralNode() as NoSubstitutionTemplateLiteral) : + (reScanTemplateHeadOrNoSubstitutionTemplate(/*isTaggedTemplate*/ true), parseLiteralNode() as NoSubstitutionTemplateLiteral) : parseTemplateExpression(/*isTaggedTemplate*/ true, !!(scanner.getTokenFlags() & TokenFlags.ContainsInvalidEscape)) ); if (questionDotToken || tag.flags & NodeFlags.OptionalChain) { @@ -5375,7 +5375,7 @@ namespace ts { return parseLiteralNode(); case SyntaxKind.NoSubstitutionTemplateLiteral: if (scanner.getTokenFlags() & TokenFlags.ContainsInvalidEscape) { - reScanTemplateHeadOrNoSubstitutionTemplate(/* isTaggedTemplate */ false) + reScanTemplateHeadOrNoSubstitutionTemplate(/* isTaggedTemplate */ false); } return parseLiteralNode(); case SyntaxKind.ThisKeyword: diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 35459628a3766..4ff969555818f 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1208,7 +1208,7 @@ namespace ts { } if (ch === CharacterCodes.backslash && !jsxAttributeString) { result += text.substring(start, pos); - result += scanEscapeSequence(false, true); + result += scanEscapeSequence(/* isTaggedTemplate */ false, /* shouldEmitInvalidEscapeError */ true); start = pos; continue; } @@ -1504,7 +1504,7 @@ namespace ts { if (ch >= 0 && isIdentifierPart(ch, languageVersion)) { pos += 3; tokenFlags |= TokenFlags.ExtendedUnicodeEscape; - result += scanExtendedUnicodeEscape(true); + result += scanExtendedUnicodeEscape(/* shouldEmitInvalidEscapeError */ true); start = pos; continue; } @@ -1689,7 +1689,7 @@ namespace ts { tokenValue = scanString(); return token = SyntaxKind.StringLiteral; case CharacterCodes.backtick: - return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ false, false); + return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ false, /* shouldEmitInvalidEscapeError */ false); case CharacterCodes.percent: if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { return pos += 2, token = SyntaxKind.PercentEqualsToken; @@ -2024,7 +2024,7 @@ namespace ts { if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) { pos += 3; tokenFlags |= TokenFlags.ExtendedUnicodeEscape; - tokenValue = scanExtendedUnicodeEscape(true) + scanIdentifierParts(); + tokenValue = scanExtendedUnicodeEscape(/* shouldEmitInvalidEscapeError */ true) + scanIdentifierParts(); return token = getIdentifierToken(); } @@ -2232,12 +2232,12 @@ namespace ts { function reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind { Debug.assert(token === SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'"); pos = tokenPos; - return token = scanTemplateAndSetTokenValue(isTaggedTemplate, true); + return token = scanTemplateAndSetTokenValue(isTaggedTemplate, /* shouldEmitInvalidEscapeError */ true); } function reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate?: boolean): SyntaxKind { pos = tokenPos; - return token = scanTemplateAndSetTokenValue(isTaggedTemplate || false, true); + return token = scanTemplateAndSetTokenValue(isTaggedTemplate || false, /* shouldEmitInvalidEscapeError */ true); } function reScanJsxToken(allowMultilineJsxText = true): JsxTokenSyntaxKind { @@ -2445,7 +2445,7 @@ namespace ts { if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) { pos += 3; tokenFlags |= TokenFlags.ExtendedUnicodeEscape; - tokenValue = scanExtendedUnicodeEscape(true) + scanIdentifierParts(); + tokenValue = scanExtendedUnicodeEscape(/* shouldEmitInvalidEscapeError */ true) + scanIdentifierParts(); return token = getIdentifierToken(); } From 4e437800e0bac5a34520c5e5b9d7d7317bba6060 Mon Sep 17 00:00:00 2001 From: uhyo Date: Sun, 11 Oct 2020 01:24:53 +0900 Subject: [PATCH 6/6] accept new baseline --- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 3c46dd41c5b0a..baa4cbc421fd5 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4011,7 +4011,7 @@ declare namespace ts { reScanSlashToken(): SyntaxKind; reScanAsteriskEqualsToken(): SyntaxKind; reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind; - reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate: boolean): SyntaxKind; + reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate?: boolean): SyntaxKind; scanJsxIdentifier(): SyntaxKind; scanJsxAttributeValue(): SyntaxKind; reScanJsxAttributeValue(): SyntaxKind; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 25aef2a5cf0f0..e4a40aecb6a61 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4011,7 +4011,7 @@ declare namespace ts { reScanSlashToken(): SyntaxKind; reScanAsteriskEqualsToken(): SyntaxKind; reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind; - reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate: boolean): SyntaxKind; + reScanTemplateHeadOrNoSubstitutionTemplate(isTaggedTemplate?: boolean): SyntaxKind; scanJsxIdentifier(): SyntaxKind; scanJsxAttributeValue(): SyntaxKind; reScanJsxAttributeValue(): SyntaxKind;