add support for Lift Template Literal Restriction (#23801)

* add support for Lift Template Literal Restriction

* rename file and improve comment and tests

* fix NoSubstitutionTemplateLiteral support

* extract tagged template and add more test

* avoid useless parameter

* fix incorrect return node if cannot transform

* accept baseline

* correctly baseline

* accept baseline

* fix merge break

* fix merge break

* inline rescan template head or no subsititution template

* update scan error

* add comment and fix lint

* refactor and fix lint

* avoid blank

* fix merge conflict

* fix again

* fix again

* use multiple target

* fix space lint

Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
This commit is contained in:
Wenlu Wang 2020-02-06 00:59:51 +08:00 committed by GitHub
parent 20471182fc
commit 70399e146e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 1647 additions and 125 deletions

View file

@ -4124,8 +4124,18 @@ namespace ts {
case SyntaxKind.TemplateHead:
case SyntaxKind.TemplateMiddle:
case SyntaxKind.TemplateTail:
case SyntaxKind.TemplateExpression:
if ((<NoSubstitutionTemplateLiteral | TemplateHead | TemplateMiddle | TemplateTail>node).templateFlags) {
transformFlags |= TransformFlags.AssertES2018;
break;
}
// falls through
case SyntaxKind.TaggedTemplateExpression:
if (hasInvalidEscape((<TaggedTemplateExpression>node).template)) {
transformFlags |= TransformFlags.AssertES2018;
break;
}
// falls through
case SyntaxKind.TemplateExpression:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.StaticKeyword:
case SyntaxKind.MetaProperty:

View file

@ -1486,7 +1486,7 @@ namespace ts {
let token = rawTextScanner.scan();
if (token === SyntaxKind.CloseBracketToken) {
token = rawTextScanner.reScanTemplateToken();
token = rawTextScanner.reScanTemplateToken(/* isTaggedTemplate */ false);
}
if (rawTextScanner.isUnterminated()) {

View file

@ -1137,8 +1137,12 @@ namespace ts {
return currentToken = scanner.reScanSlashToken();
}
function reScanTemplateToken(): SyntaxKind {
return currentToken = scanner.reScanTemplateToken();
function reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind {
return currentToken = scanner.reScanTemplateToken(isTaggedTemplate);
}
function reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind {
return currentToken = scanner.reScanTemplateHeadOrNoSubstitutionTemplate();
}
function reScanLessThanToken(): SyntaxKind {
@ -2329,17 +2333,17 @@ namespace ts {
return allowIdentifierNames ? parseIdentifierName() : parseIdentifier();
}
function parseTemplateExpression(): TemplateExpression {
function parseTemplateExpression(isTaggedTemplate: boolean): TemplateExpression {
const template = <TemplateExpression>createNode(SyntaxKind.TemplateExpression);
template.head = parseTemplateHead();
template.head = parseTemplateHead(isTaggedTemplate);
Debug.assert(template.head.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
const list = [];
const listPos = getNodePos();
do {
list.push(parseTemplateSpan());
list.push(parseTemplateSpan(isTaggedTemplate));
}
while (last(list).literal.kind === SyntaxKind.TemplateMiddle);
@ -2348,13 +2352,13 @@ namespace ts {
return finishNode(template);
}
function parseTemplateSpan(): TemplateSpan {
function parseTemplateSpan(isTaggedTemplate: boolean): TemplateSpan {
const span = <TemplateSpan>createNode(SyntaxKind.TemplateSpan);
span.expression = allowInAnd(parseExpression);
let literal: TemplateMiddle | TemplateTail;
if (token() === SyntaxKind.CloseBraceToken) {
reScanTemplateToken();
reScanTemplateToken(isTaggedTemplate);
literal = parseTemplateMiddleOrTemplateTail();
}
else {
@ -2369,7 +2373,10 @@ namespace ts {
return <LiteralExpression>parseLiteralLikeNode(token());
}
function parseTemplateHead(): TemplateHead {
function parseTemplateHead(isTaggedTemplate: boolean): TemplateHead {
if (isTaggedTemplate) {
reScanTemplateHeadOrNoSubstitutionTemplate();
}
const fragment = parseLiteralLikeNode(token());
Debug.assert(fragment.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
return <TemplateHead>fragment;
@ -2413,6 +2420,10 @@ namespace ts {
(<NumericLiteral>node).numericLiteralFlags = scanner.getTokenFlags() & TokenFlags.NumericLiteralFlags;
}
if (isTemplateLiteralKind(node.kind)) {
(<TemplateHead | TemplateMiddle | TemplateTail | NoSubstitutionTemplateLiteral>node).templateFlags = scanner.getTokenFlags() & TokenFlags.ContainsInvalidEscape;
}
nextToken();
finishNode(node);
@ -4772,8 +4783,8 @@ namespace ts {
tagExpression.questionDotToken = questionDotToken;
tagExpression.typeArguments = typeArguments;
tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral
? <NoSubstitutionTemplateLiteral>parseLiteralNode()
: parseTemplateExpression();
? (reScanTemplateHeadOrNoSubstitutionTemplate(), <NoSubstitutionTemplateLiteral>parseLiteralNode())
: parseTemplateExpression(/*isTaggedTemplate*/ true);
if (questionDotToken || tag.flags & NodeFlags.OptionalChain) {
tagExpression.flags |= NodeFlags.OptionalChain;
}
@ -4945,7 +4956,7 @@ namespace ts {
}
break;
case SyntaxKind.TemplateHead:
return parseTemplateExpression();
return parseTemplateExpression(/* isTaggedTemplate */ false);
}
return parseIdentifier(Diagnostics.Expression_expected);

View file

@ -28,7 +28,8 @@ namespace ts {
getTokenFlags(): TokenFlags;
reScanGreaterToken(): SyntaxKind;
reScanSlashToken(): SyntaxKind;
reScanTemplateToken(): SyntaxKind;
reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind;
reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind;
scanJsxIdentifier(): SyntaxKind;
scanJsxAttributeValue(): SyntaxKind;
reScanJsxAttributeValue(): SyntaxKind;
@ -468,6 +469,14 @@ namespace ts {
return ch >= CharacterCodes._0 && ch <= CharacterCodes._9;
}
function isHexDigit(ch: number): boolean {
return isDigit(ch) || ch >= CharacterCodes.A && ch <= CharacterCodes.F || ch >= CharacterCodes.a && ch <= CharacterCodes.f;
}
function isCodePoint(code: number): boolean {
return code <= 0x10FFFF;
}
/* @internal */
export function isOctalDigit(ch: number): boolean {
return ch >= CharacterCodes._0 && ch <= CharacterCodes._7;
@ -901,6 +910,7 @@ namespace ts {
reScanGreaterToken,
reScanSlashToken,
reScanTemplateToken,
reScanTemplateHeadOrNoSubstitutionTemplate,
scanJsxIdentifier,
scanJsxAttributeValue,
reScanJsxAttributeValue,
@ -1164,7 +1174,7 @@ namespace ts {
* Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or
* a literal component of a TemplateExpression.
*/
function scanTemplateAndSetTokenValue(): SyntaxKind {
function scanTemplateAndSetTokenValue(isTaggedTemplate: boolean): SyntaxKind {
const startedWithBacktick = text.charCodeAt(pos) === CharacterCodes.backtick;
pos++;
@ -1202,7 +1212,7 @@ namespace ts {
// Escape character
if (currChar === CharacterCodes.backslash) {
contents += text.substring(start, pos);
contents += scanEscapeSequence();
contents += scanEscapeSequence(isTaggedTemplate);
start = pos;
continue;
}
@ -1231,7 +1241,8 @@ namespace ts {
return resultingToken;
}
function scanEscapeSequence(): string {
function scanEscapeSequence(isTaggedTemplate?: boolean): string {
const start = pos;
pos++;
if (pos >= end) {
error(Diagnostics.Unexpected_end_of_text);
@ -1241,6 +1252,12 @@ namespace ts {
pos++;
switch (ch) {
case CharacterCodes._0:
// '\01'
if (isTaggedTemplate && pos < end && isDigit(text.charCodeAt(pos))) {
pos++;
tokenFlags |= TokenFlags.ContainsInvalidEscape;
return text.substring(start, pos);
}
return "\0";
case CharacterCodes.b:
return "\b";
@ -1259,10 +1276,41 @@ 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) {
pos = escapePos;
tokenFlags |= TokenFlags.ContainsInvalidEscape;
return text.substring(start, pos);
}
}
}
// '\u{DDDDDDDD}'
if (pos < end && text.charCodeAt(pos) === CharacterCodes.openBrace) {
tokenFlags |= TokenFlags.ExtendedUnicodeEscape;
pos++;
// '\u{'
if (isTaggedTemplate && !isHexDigit(text.charCodeAt(pos))) {
tokenFlags |= TokenFlags.ContainsInvalidEscape;
return text.substring(start, pos);
}
if (isTaggedTemplate) {
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;
return text.substring(start, pos);
}
else {
pos = savePos;
}
}
tokenFlags |= TokenFlags.ExtendedUnicodeEscape;
return scanExtendedUnicodeEscape();
}
@ -1271,6 +1319,17 @@ namespace ts {
return scanHexadecimalEscape(/*numDigits*/ 4);
case CharacterCodes.x:
if (isTaggedTemplate) {
if (!isHexDigit(text.charCodeAt(pos))) {
tokenFlags |= TokenFlags.ContainsInvalidEscape;
return text.substring(start, pos);
}
else if (!isHexDigit(text.charCodeAt(pos + 1))) {
pos++;
tokenFlags |= TokenFlags.ContainsInvalidEscape;
return text.substring(start, pos);
}
}
// '\xDD'
return scanHexadecimalEscape(/*numDigits*/ 2);
@ -1561,7 +1620,7 @@ namespace ts {
tokenValue = scanString();
return token = SyntaxKind.StringLiteral;
case CharacterCodes.backtick:
return token = scanTemplateAndSetTokenValue();
return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ false);
case CharacterCodes.percent:
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.PercentEqualsToken;
@ -2019,10 +2078,15 @@ namespace ts {
/**
* Unconditionally back up and scan a template expression portion.
*/
function reScanTemplateToken(): SyntaxKind {
function reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind {
Debug.assert(token === SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'");
pos = tokenPos;
return token = scanTemplateAndSetTokenValue();
return token = scanTemplateAndSetTokenValue(isTaggedTemplate);
}
function reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind {
pos = tokenPos;
return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ true);
}
function reScanJsxToken(): JsxTokenSyntaxKind {

View file

@ -3951,78 +3951,14 @@ namespace ts {
* @param node A TaggedTemplateExpression node.
*/
function visitTaggedTemplateExpression(node: TaggedTemplateExpression) {
// Visit the tag expression
const tag = visitNode(node.tag, visitor, isExpression);
// Build up the template arguments and the raw and cooked strings for the template.
// We start out with 'undefined' for the first argument and revisit later
// to avoid walking over the template string twice and shifting all our arguments over after the fact.
const templateArguments: Expression[] = [undefined!];
const cookedStrings: Expression[] = [];
const rawStrings: Expression[] = [];
const template = node.template;
if (isNoSubstitutionTemplateLiteral(template)) {
cookedStrings.push(createLiteral(template.text));
rawStrings.push(getRawLiteral(template));
}
else {
cookedStrings.push(createLiteral(template.head.text));
rawStrings.push(getRawLiteral(template.head));
for (const templateSpan of template.templateSpans) {
cookedStrings.push(createLiteral(templateSpan.literal.text));
rawStrings.push(getRawLiteral(templateSpan.literal));
templateArguments.push(visitNode(templateSpan.expression, visitor, isExpression));
}
}
const helperCall = createTemplateObjectHelper(context, createArrayLiteral(cookedStrings), createArrayLiteral(rawStrings));
// Create a variable to cache the template object if we're in a module.
// Do not do this in the global scope, as any variable we currently generate could conflict with
// variables from outside of the current compilation. In the future, we can revisit this behavior.
if (isExternalModule(currentSourceFile)) {
const tempVar = createUniqueName("templateObject");
recordTaggedTemplateString(tempVar);
templateArguments[0] = createLogicalOr(
tempVar,
createAssignment(
tempVar,
helperCall)
);
}
else {
templateArguments[0] = helperCall;
}
return createCall(tag, /*typeArguments*/ undefined, templateArguments);
}
/**
* Creates an ES5 compatible literal from an ES6 template literal.
*
* @param node The ES6 template literal.
*/
function getRawLiteral(node: TemplateLiteralLikeNode) {
// Find original source text, since we need to emit the raw strings of the tagged template.
// The raw strings contain the (escaped) strings of what the user wrote.
// Examples: `\n` is converted to "\\n", a template string with a newline to "\n".
let text = node.rawText;
if (text === undefined) {
text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
// text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
// thus we need to remove those characters.
// First template piece starts with "`", others with "}"
// Last template piece ends with "`", others with "${"
const isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail;
text = text.substring(1, text.length - (isLast ? 1 : 2));
}
// Newline normalization:
// ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's
// <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for both TV and TRV.
text = text.replace(/\r\n?/g, "\n");
return setTextRange(createLiteral(text), node);
return processTaggedTemplateExpression(
context,
node,
visitor,
currentSourceFile,
recordTaggedTemplateString,
ProcessLevel.All
);
}
/**
@ -4358,18 +4294,6 @@ namespace ts {
);
}
function createTemplateObjectHelper(context: TransformationContext, cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) {
context.requestEmitHelper(templateObjectHelper);
return createCall(
getUnscopedHelperName("__makeTemplateObject"),
/*typeArguments*/ undefined,
[
cooked,
raw
]
);
}
export const extendsHelper: UnscopedEmitHelper = {
name: "typescript:extends",
importName: "__extends",
@ -4391,17 +4315,4 @@ namespace ts {
};
})();`
};
export const templateObjectHelper: UnscopedEmitHelper = {
name: "typescript:makeTemplateObject",
importName: "__makeTemplateObject",
scoped: false,
priority: 0,
text: `
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};`
};
}

View file

@ -28,6 +28,9 @@ namespace ts {
let enclosingSuperContainerFlags: NodeCheckFlags = 0;
let hasLexicalThis: boolean;
let currentSourceFile: SourceFile;
let taggedTemplateStringDeclarations: VariableDeclaration[];
/** Keeps track of property names accessed on super (`super.x`) within async functions. */
let capturedSuperProperties: UnderscoreEscapedMap<true>;
/** Whether the async function contains an element access on super (`super[x]`). */
@ -37,15 +40,23 @@ namespace ts {
return chainBundle(transformSourceFile);
function recordTaggedTemplateString(temp: Identifier) {
taggedTemplateStringDeclarations = append(
taggedTemplateStringDeclarations,
createVariableDeclaration(temp));
}
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
return node;
}
exportedVariableStatement = false;
hasLexicalThis = !isEffectiveStrictModeSourceFile(node, compilerOptions);
const visited = visitEachChild(node, visitor, context);
currentSourceFile = node;
const visited = visitSourceFile(node);
addEmitHelpers(visited, context.readEmitHelpers());
currentSourceFile = undefined!;
taggedTemplateStringDeclarations = undefined!;
return visited;
}
@ -127,6 +138,8 @@ namespace ts {
return visitExpressionStatement(node as ExpressionStatement);
case SyntaxKind.ParenthesizedExpression:
return visitParenthesizedExpression(node as ParenthesizedExpression, noDestructuringValue);
case SyntaxKind.TaggedTemplateExpression:
return visitTaggedTemplateExpression(node as TaggedTemplateExpression);
case SyntaxKind.PropertyAccessExpression:
if (capturedSuperProperties && isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.SuperKeyword) {
capturedSuperProperties.set(node.name.escapedText, true);
@ -297,6 +310,28 @@ namespace ts {
return visitEachChild(node, noDestructuringValue ? visitorNoDestructuringValue : visitor, context);
}
function visitSourceFile(node: SourceFile): SourceFile {
exportedVariableStatement = false;
hasLexicalThis = !isEffectiveStrictModeSourceFile(node, compilerOptions);
const visited = visitEachChild(node, visitor, context);
const statement = concatenate(visited.statements, taggedTemplateStringDeclarations && [
createVariableStatement(/*modifiers*/ undefined,
createVariableDeclarationList(taggedTemplateStringDeclarations))
]);
return updateSourceFileNode(visited, setTextRange(createNodeArray(statement), node.statements));
}
function visitTaggedTemplateExpression(node: TaggedTemplateExpression) {
return processTaggedTemplateExpression(
context,
node,
visitor,
currentSourceFile,
recordTaggedTemplateString,
ProcessLevel.LiftRestriction
);
}
/**
* Visits a BinaryExpression that contains a destructuring assignment.
*

View file

@ -0,0 +1,117 @@
/*@internal*/
namespace ts {
export enum ProcessLevel {
LiftRestriction,
All
}
export function processTaggedTemplateExpression(
context: TransformationContext,
node: TaggedTemplateExpression,
visitor: ((node: Node) => VisitResult<Node>) | undefined,
currentSourceFile: SourceFile,
recordTaggedTemplateString: (temp: Identifier) => void,
level: ProcessLevel) {
// Visit the tag expression
const tag = visitNode(node.tag, visitor, isExpression);
// Build up the template arguments and the raw and cooked strings for the template.
// We start out with 'undefined' for the first argument and revisit later
// to avoid walking over the template string twice and shifting all our arguments over after the fact.
const templateArguments: Expression[] = [undefined!];
const cookedStrings: Expression[] = [];
const rawStrings: Expression[] = [];
const template = node.template;
if (level === ProcessLevel.LiftRestriction && !hasInvalidEscape(template)) return node;
if (isNoSubstitutionTemplateLiteral(template)) {
cookedStrings.push(createTemplateCooked(template));
rawStrings.push(getRawLiteral(template, currentSourceFile));
}
else {
cookedStrings.push(createTemplateCooked(template.head));
rawStrings.push(getRawLiteral(template.head, currentSourceFile));
for (const templateSpan of template.templateSpans) {
cookedStrings.push(createTemplateCooked(templateSpan.literal));
rawStrings.push(getRawLiteral(templateSpan.literal, currentSourceFile));
templateArguments.push(visitNode(templateSpan.expression, visitor, isExpression));
}
}
const helperCall = createTemplateObjectHelper(context, createArrayLiteral(cookedStrings), createArrayLiteral(rawStrings));
// Create a variable to cache the template object if we're in a module.
// Do not do this in the global scope, as any variable we currently generate could conflict with
// variables from outside of the current compilation. In the future, we can revisit this behavior.
if (isExternalModule(currentSourceFile)) {
const tempVar = createUniqueName("templateObject");
recordTaggedTemplateString(tempVar);
templateArguments[0] = createLogicalOr(
tempVar,
createAssignment(
tempVar,
helperCall)
);
}
else {
templateArguments[0] = helperCall;
}
return createCall(tag, /*typeArguments*/ undefined, templateArguments);
}
function createTemplateCooked(template: TemplateHead | TemplateMiddle | TemplateTail | NoSubstitutionTemplateLiteral) {
return template.templateFlags ? createIdentifier("undefined") : createLiteral(template.text);
}
/**
* Creates an ES5 compatible literal from an ES6 template literal.
*
* @param node The ES6 template literal.
*/
function getRawLiteral(node: LiteralLikeNode, currentSourceFile: SourceFile) {
// Find original source text, since we need to emit the raw strings of the tagged template.
// The raw strings contain the (escaped) strings of what the user wrote.
// Examples: `\n` is converted to "\\n", a template string with a newline to "\n".
let text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
// text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
// thus we need to remove those characters.
// First template piece starts with "`", others with "}"
// Last template piece ends with "`", others with "${"
const isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail;
text = text.substring(1, text.length - (isLast ? 1 : 2));
// Newline normalization:
// ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's
// <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for both TV and TRV.
text = text.replace(/\r\n?/g, "\n");
return setTextRange(createLiteral(text), node);
}
function createTemplateObjectHelper(context: TransformationContext, cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) {
context.requestEmitHelper(templateObjectHelper);
return createCall(
getUnscopedHelperName("__makeTemplateObject"),
/*typeArguments*/ undefined,
[
cooked,
raw
]
);
}
export const templateObjectHelper: UnscopedEmitHelper = {
name: "typescript:makeTemplateObject",
importName: "__makeTemplateObject",
scoped: false,
priority: 0,
text: `
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};`
};
}

View file

@ -38,6 +38,7 @@
"sourcemap.ts",
"transformers/utilities.ts",
"transformers/destructuring.ts",
"transformers/taggedTemplate.ts",
"transformers/ts.ts",
"transformers/classFields.ts",
"transformers/es2017.ts",

View file

@ -1735,6 +1735,8 @@ namespace ts {
export interface NoSubstitutionTemplateLiteral extends LiteralExpression, TemplateLiteralLikeNode, Declaration {
kind: SyntaxKind.NoSubstitutionTemplateLiteral;
/* @internal */
templateFlags?: TokenFlags;
}
export const enum TokenFlags {
@ -1757,6 +1759,8 @@ namespace ts {
/* @internal */
UnicodeEscape = 1 << 10,
/* @internal */
ContainsInvalidEscape = 1 << 11, // e.g. `\uhello`
/* @internal */
BinaryOrOctalSpecifier = BinarySpecifier | OctalSpecifier,
/* @internal */
NumericLiteralFlags = Scientific | Octal | HexSpecifier | BinaryOrOctalSpecifier | ContainsSeparator
@ -1775,16 +1779,22 @@ namespace ts {
export interface TemplateHead extends TemplateLiteralLikeNode {
kind: SyntaxKind.TemplateHead;
parent: TemplateExpression;
/* @internal */
templateFlags?: TokenFlags;
}
export interface TemplateMiddle extends TemplateLiteralLikeNode {
kind: SyntaxKind.TemplateMiddle;
parent: TemplateSpan;
/* @internal */
templateFlags?: TokenFlags;
}
export interface TemplateTail extends TemplateLiteralLikeNode {
kind: SyntaxKind.TemplateTail;
parent: TemplateSpan;
/* @internal */
templateFlags?: TokenFlags;
}
export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral;

View file

@ -3365,6 +3365,13 @@ namespace ts {
return str.replace(templateSubstitutionRegExp, "\\${");
}
/** @internal */
export function hasInvalidEscape(template: TemplateLiteral): boolean {
return template && !!(isNoSubstitutionTemplateLiteral(template)
? template.templateFlags
: (template.head.templateFlags || some(template.templateSpans, span => !!span.literal.templateFlags)));
}
// This consists of the first 19 unprintable ASCII characters, canonical escapes, lineSeparator,
// paragraphSeparator, and nextLine. The latter three are just desirable to suppress new lines in
// the language service. These characters should be escaped when printing, and if any characters are added,

View file

@ -135,7 +135,7 @@ namespace ts {
const lastTemplateStackToken = lastOrUndefined(templateStack);
if (lastTemplateStackToken === SyntaxKind.TemplateHead) {
token = scanner.reScanTemplateToken();
token = scanner.reScanTemplateToken(/* isTaggedTemplate */ false);
// Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us.
if (token === SyntaxKind.TemplateTail) {

View file

@ -242,7 +242,7 @@ namespace ts.formatting {
case ScanAction.RescanTemplateToken:
if (token === SyntaxKind.CloseBraceToken) {
lastScanAction = ScanAction.RescanTemplateToken;
return scanner.reScanTemplateToken();
return scanner.reScanTemplateToken(/* isTaggedTemplate */ false);
}
break;
case ScanAction.RescanJsxIdentifier:

View file

@ -3345,7 +3345,8 @@ declare namespace ts {
isUnterminated(): boolean;
reScanGreaterToken(): SyntaxKind;
reScanSlashToken(): SyntaxKind;
reScanTemplateToken(): SyntaxKind;
reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind;
reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind;
scanJsxIdentifier(): SyntaxKind;
scanJsxAttributeValue(): SyntaxKind;
reScanJsxAttributeValue(): SyntaxKind;

View file

@ -3345,7 +3345,8 @@ declare namespace ts {
isUnterminated(): boolean;
reScanGreaterToken(): SyntaxKind;
reScanSlashToken(): SyntaxKind;
reScanTemplateToken(): SyntaxKind;
reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind;
reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind;
scanJsxIdentifier(): SyntaxKind;
scanJsxAttributeValue(): SyntaxKind;
reScanJsxAttributeValue(): SyntaxKind;

View file

@ -0,0 +1,49 @@
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) ====
function tag (str: any, ...args: any[]): any {
return str
}
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.
!!! error TS1125: Hexadecimal digit expected.
!!! 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
const a3 = tag`${ 100 }\u` // \\u
const a4 = tag`${ 100 }\u0` // \\u0
const a5 = tag`${ 100 }\u00` // \\u00
const a6 = tag`${ 100 }\u000` // \\u000
const a7 = tag`${ 100 }\u0000` // \u0000
const a8 = tag`${ 100 }\u{` // \\u{
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
const a12 = tag`${ 100 }\x` // \\x
const a13 = tag`${ 100 }\x0` // \\x0
const a14 = tag`${ 100 }\x00` // \x00

View file

@ -0,0 +1,54 @@
//// [invalidTaggedTemplateEscapeSequences.ts]
function tag (str: any, ...args: any[]): any {
return str
}
const a = tag`123`
const b = tag`123 ${100}`
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
const a1 = tag`${ 100 }\0` // \0
const a2 = tag`${ 100 }\00` // \\00
const a3 = tag`${ 100 }\u` // \\u
const a4 = tag`${ 100 }\u0` // \\u0
const a5 = tag`${ 100 }\u00` // \\u00
const a6 = tag`${ 100 }\u000` // \\u000
const a7 = tag`${ 100 }\u0000` // \u0000
const a8 = tag`${ 100 }\u{` // \\u{
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
const a12 = tag`${ 100 }\x` // \\x
const a13 = tag`${ 100 }\x0` // \\x0
const a14 = tag`${ 100 }\x00` // \x00
//// [invalidTaggedTemplateEscapeSequences.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 tag(str, ...args) {
return str;
}
const a = tag `123`;
const b = tag `123 ${100}`;
const x = tag(__makeTemplateObject([undefined, undefined, " wonderful ", undefined], ["\\u{hello} ", " \\xtraordinary ", " wonderful ", " \\uworld"]), 100, 200, 300);
const y = `\u{hello} ${100} \xtraordinary ${200} wonderful ${300} \uworld`; // should error with NoSubstitutionTemplate
const z = tag(__makeTemplateObject([undefined], ["\\u{hello} \\xtraordinary wonderful \\uworld"])); // should work with Tagged NoSubstitutionTemplate
const a1 = tag `${100}\0`; // \0
const a2 = tag(__makeTemplateObject(["", undefined], ["", "\\00"]), 100); // \\00
const a3 = tag(__makeTemplateObject(["", undefined], ["", "\\u"]), 100); // \\u
const a4 = tag(__makeTemplateObject(["", undefined], ["", "\\u0"]), 100); // \\u0
const a5 = tag(__makeTemplateObject(["", undefined], ["", "\\u00"]), 100); // \\u00
const a6 = tag(__makeTemplateObject(["", undefined], ["", "\\u000"]), 100); // \\u000
const a7 = tag `${100}\u0000`; // \u0000
const a8 = tag(__makeTemplateObject(["", undefined], ["", "\\u{"]), 100); // \\u{
const a9 = tag `${100}\u{10FFFF}`; // \\u{10FFFF
const a10 = tag(__makeTemplateObject(["", undefined], ["", "\\u{1f622"]), 100); // \\u{1f622
const a11 = tag `${100}\u{1f622}`; // \u{1f622}
const a12 = tag(__makeTemplateObject(["", undefined], ["", "\\x"]), 100); // \\x
const a13 = tag(__makeTemplateObject(["", undefined], ["", "\\x0"]), 100); // \\x0
const a14 = tag `${100}\x00`; // \x00

View file

@ -0,0 +1,85 @@
=== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts ===
function tag (str: any, ...args: any[]): any {
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
>str : Symbol(str, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 14))
>args : Symbol(args, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 23))
return str
>str : Symbol(str, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 14))
}
const a = tag`123`
>a : Symbol(a, Decl(invalidTaggedTemplateEscapeSequences.ts, 4, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const b = tag`123 ${100}`
>b : Symbol(b, Decl(invalidTaggedTemplateEscapeSequences.ts, 5, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
>x : Symbol(x, Decl(invalidTaggedTemplateEscapeSequences.ts, 6, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
>y : Symbol(y, Decl(invalidTaggedTemplateEscapeSequences.ts, 7, 5))
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
>z : Symbol(z, Decl(invalidTaggedTemplateEscapeSequences.ts, 8, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a1 = tag`${ 100 }\0` // \0
>a1 : Symbol(a1, Decl(invalidTaggedTemplateEscapeSequences.ts, 10, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a2 = tag`${ 100 }\00` // \\00
>a2 : Symbol(a2, Decl(invalidTaggedTemplateEscapeSequences.ts, 11, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a3 = tag`${ 100 }\u` // \\u
>a3 : Symbol(a3, Decl(invalidTaggedTemplateEscapeSequences.ts, 12, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a4 = tag`${ 100 }\u0` // \\u0
>a4 : Symbol(a4, Decl(invalidTaggedTemplateEscapeSequences.ts, 13, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a5 = tag`${ 100 }\u00` // \\u00
>a5 : Symbol(a5, Decl(invalidTaggedTemplateEscapeSequences.ts, 14, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a6 = tag`${ 100 }\u000` // \\u000
>a6 : Symbol(a6, Decl(invalidTaggedTemplateEscapeSequences.ts, 15, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a7 = tag`${ 100 }\u0000` // \u0000
>a7 : Symbol(a7, Decl(invalidTaggedTemplateEscapeSequences.ts, 16, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a8 = tag`${ 100 }\u{` // \\u{
>a8 : Symbol(a8, Decl(invalidTaggedTemplateEscapeSequences.ts, 17, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
>a9 : Symbol(a9, Decl(invalidTaggedTemplateEscapeSequences.ts, 18, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
>a10 : Symbol(a10, Decl(invalidTaggedTemplateEscapeSequences.ts, 19, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
>a11 : Symbol(a11, Decl(invalidTaggedTemplateEscapeSequences.ts, 20, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a12 = tag`${ 100 }\x` // \\x
>a12 : Symbol(a12, Decl(invalidTaggedTemplateEscapeSequences.ts, 21, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a13 = tag`${ 100 }\x0` // \\x0
>a13 : Symbol(a13, Decl(invalidTaggedTemplateEscapeSequences.ts, 22, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a14 = tag`${ 100 }\x00` // \x00
>a14 : Symbol(a14, Decl(invalidTaggedTemplateEscapeSequences.ts, 23, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))

View file

@ -0,0 +1,143 @@
=== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts ===
function tag (str: any, ...args: any[]): any {
>tag : (str: any, ...args: any[]) => any
>str : any
>args : any[]
return str
>str : any
}
const a = tag`123`
>a : any
>tag`123` : any
>tag : (str: any, ...args: any[]) => any
>`123` : "123"
const b = tag`123 ${100}`
>b : any
>tag`123 ${100}` : any
>tag : (str: any, ...args: any[]) => any
>`123 ${100}` : string
>100 : 100
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
>x : any
>tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : any
>tag : (str: any, ...args: any[]) => any
>`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : string
>100 : 100
>200 : 200
>300 : 300
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
>y : string
>`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : string
>100 : 100
>200 : 200
>300 : 300
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
>z : any
>tag`\u{hello} \xtraordinary wonderful \uworld` : any
>tag : (str: any, ...args: any[]) => any
>`\u{hello} \xtraordinary wonderful \uworld` : "\\u{hello} \\xtraordinary wonderful \\uworld"
const a1 = tag`${ 100 }\0` // \0
>a1 : any
>tag`${ 100 }\0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\0` : string
>100 : 100
const a2 = tag`${ 100 }\00` // \\00
>a2 : any
>tag`${ 100 }\00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\00` : string
>100 : 100
const a3 = tag`${ 100 }\u` // \\u
>a3 : any
>tag`${ 100 }\u` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u` : string
>100 : 100
const a4 = tag`${ 100 }\u0` // \\u0
>a4 : any
>tag`${ 100 }\u0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u0` : string
>100 : 100
const a5 = tag`${ 100 }\u00` // \\u00
>a5 : any
>tag`${ 100 }\u00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u00` : string
>100 : 100
const a6 = tag`${ 100 }\u000` // \\u000
>a6 : any
>tag`${ 100 }\u000` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u000` : string
>100 : 100
const a7 = tag`${ 100 }\u0000` // \u0000
>a7 : any
>tag`${ 100 }\u0000` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u0000` : string
>100 : 100
const a8 = tag`${ 100 }\u{` // \\u{
>a8 : any
>tag`${ 100 }\u{` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{` : string
>100 : 100
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
>a9 : any
>tag`${ 100 }\u{10FFFF}` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{10FFFF}` : string
>100 : 100
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
>a10 : any
>tag`${ 100 }\u{1f622` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{1f622` : string
>100 : 100
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
>a11 : any
>tag`${ 100 }\u{1f622}` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{1f622}` : string
>100 : 100
const a12 = tag`${ 100 }\x` // \\x
>a12 : any
>tag`${ 100 }\x` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x` : string
>100 : 100
const a13 = tag`${ 100 }\x0` // \\x0
>a13 : any
>tag`${ 100 }\x0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x0` : string
>100 : 100
const a14 = tag`${ 100 }\x00` // \x00
>a14 : any
>tag`${ 100 }\x00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x00` : string
>100 : 100

View file

@ -0,0 +1,49 @@
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) ====
function tag (str: any, ...args: any[]): any {
return str
}
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.
!!! error TS1125: Hexadecimal digit expected.
!!! 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
const a3 = tag`${ 100 }\u` // \\u
const a4 = tag`${ 100 }\u0` // \\u0
const a5 = tag`${ 100 }\u00` // \\u00
const a6 = tag`${ 100 }\u000` // \\u000
const a7 = tag`${ 100 }\u0000` // \u0000
const a8 = tag`${ 100 }\u{` // \\u{
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
const a12 = tag`${ 100 }\x` // \\x
const a13 = tag`${ 100 }\x0` // \\x0
const a14 = tag`${ 100 }\x00` // \x00

View file

@ -0,0 +1,58 @@
//// [invalidTaggedTemplateEscapeSequences.ts]
function tag (str: any, ...args: any[]): any {
return str
}
const a = tag`123`
const b = tag`123 ${100}`
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
const a1 = tag`${ 100 }\0` // \0
const a2 = tag`${ 100 }\00` // \\00
const a3 = tag`${ 100 }\u` // \\u
const a4 = tag`${ 100 }\u0` // \\u0
const a5 = tag`${ 100 }\u00` // \\u00
const a6 = tag`${ 100 }\u000` // \\u000
const a7 = tag`${ 100 }\u0000` // \u0000
const a8 = tag`${ 100 }\u{` // \\u{
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
const a12 = tag`${ 100 }\x` // \\x
const a13 = tag`${ 100 }\x0` // \\x0
const a14 = tag`${ 100 }\x00` // \x00
//// [invalidTaggedTemplateEscapeSequences.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 tag(str) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
return str;
}
var a = tag(__makeTemplateObject(["123"], ["123"]));
var b = tag(__makeTemplateObject(["123 ", ""], ["123 ", ""]), 100);
var x = tag(__makeTemplateObject([undefined, undefined, " wonderful ", undefined], ["\\u{hello} ", " \\xtraordinary ", " wonderful ", " \\uworld"]), 100, 200, 300);
var y = "hello} " + 100 + " traordinary " + 200 + " wonderful " + 300 + " world"; // should error with NoSubstitutionTemplate
var z = tag(__makeTemplateObject([undefined], ["\\u{hello} \\xtraordinary wonderful \\uworld"])); // should work with Tagged NoSubstitutionTemplate
var a1 = tag(__makeTemplateObject(["", "\0"], ["", "\\0"]), 100); // \0
var a2 = tag(__makeTemplateObject(["", undefined], ["", "\\00"]), 100); // \\00
var a3 = tag(__makeTemplateObject(["", undefined], ["", "\\u"]), 100); // \\u
var a4 = tag(__makeTemplateObject(["", undefined], ["", "\\u0"]), 100); // \\u0
var a5 = tag(__makeTemplateObject(["", undefined], ["", "\\u00"]), 100); // \\u00
var a6 = tag(__makeTemplateObject(["", undefined], ["", "\\u000"]), 100); // \\u000
var a7 = tag(__makeTemplateObject(["", "\0"], ["", "\\u0000"]), 100); // \u0000
var a8 = tag(__makeTemplateObject(["", undefined], ["", "\\u{"]), 100); // \\u{
var a9 = tag(__makeTemplateObject(["", "\uDBFF\uDFFF"], ["", "\\u{10FFFF}"]), 100); // \\u{10FFFF
var a10 = tag(__makeTemplateObject(["", undefined], ["", "\\u{1f622"]), 100); // \\u{1f622
var a11 = tag(__makeTemplateObject(["", "\uD83D\uDE22"], ["", "\\u{1f622}"]), 100); // \u{1f622}
var a12 = tag(__makeTemplateObject(["", undefined], ["", "\\x"]), 100); // \\x
var a13 = tag(__makeTemplateObject(["", undefined], ["", "\\x0"]), 100); // \\x0
var a14 = tag(__makeTemplateObject(["", "\0"], ["", "\\x00"]), 100); // \x00

View file

@ -0,0 +1,85 @@
=== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts ===
function tag (str: any, ...args: any[]): any {
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
>str : Symbol(str, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 14))
>args : Symbol(args, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 23))
return str
>str : Symbol(str, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 14))
}
const a = tag`123`
>a : Symbol(a, Decl(invalidTaggedTemplateEscapeSequences.ts, 4, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const b = tag`123 ${100}`
>b : Symbol(b, Decl(invalidTaggedTemplateEscapeSequences.ts, 5, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
>x : Symbol(x, Decl(invalidTaggedTemplateEscapeSequences.ts, 6, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
>y : Symbol(y, Decl(invalidTaggedTemplateEscapeSequences.ts, 7, 5))
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
>z : Symbol(z, Decl(invalidTaggedTemplateEscapeSequences.ts, 8, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a1 = tag`${ 100 }\0` // \0
>a1 : Symbol(a1, Decl(invalidTaggedTemplateEscapeSequences.ts, 10, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a2 = tag`${ 100 }\00` // \\00
>a2 : Symbol(a2, Decl(invalidTaggedTemplateEscapeSequences.ts, 11, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a3 = tag`${ 100 }\u` // \\u
>a3 : Symbol(a3, Decl(invalidTaggedTemplateEscapeSequences.ts, 12, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a4 = tag`${ 100 }\u0` // \\u0
>a4 : Symbol(a4, Decl(invalidTaggedTemplateEscapeSequences.ts, 13, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a5 = tag`${ 100 }\u00` // \\u00
>a5 : Symbol(a5, Decl(invalidTaggedTemplateEscapeSequences.ts, 14, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a6 = tag`${ 100 }\u000` // \\u000
>a6 : Symbol(a6, Decl(invalidTaggedTemplateEscapeSequences.ts, 15, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a7 = tag`${ 100 }\u0000` // \u0000
>a7 : Symbol(a7, Decl(invalidTaggedTemplateEscapeSequences.ts, 16, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a8 = tag`${ 100 }\u{` // \\u{
>a8 : Symbol(a8, Decl(invalidTaggedTemplateEscapeSequences.ts, 17, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
>a9 : Symbol(a9, Decl(invalidTaggedTemplateEscapeSequences.ts, 18, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
>a10 : Symbol(a10, Decl(invalidTaggedTemplateEscapeSequences.ts, 19, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
>a11 : Symbol(a11, Decl(invalidTaggedTemplateEscapeSequences.ts, 20, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a12 = tag`${ 100 }\x` // \\x
>a12 : Symbol(a12, Decl(invalidTaggedTemplateEscapeSequences.ts, 21, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a13 = tag`${ 100 }\x0` // \\x0
>a13 : Symbol(a13, Decl(invalidTaggedTemplateEscapeSequences.ts, 22, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a14 = tag`${ 100 }\x00` // \x00
>a14 : Symbol(a14, Decl(invalidTaggedTemplateEscapeSequences.ts, 23, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))

View file

@ -0,0 +1,143 @@
=== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts ===
function tag (str: any, ...args: any[]): any {
>tag : (str: any, ...args: any[]) => any
>str : any
>args : any[]
return str
>str : any
}
const a = tag`123`
>a : any
>tag`123` : any
>tag : (str: any, ...args: any[]) => any
>`123` : "123"
const b = tag`123 ${100}`
>b : any
>tag`123 ${100}` : any
>tag : (str: any, ...args: any[]) => any
>`123 ${100}` : string
>100 : 100
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
>x : any
>tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : any
>tag : (str: any, ...args: any[]) => any
>`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : string
>100 : 100
>200 : 200
>300 : 300
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
>y : string
>`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : string
>100 : 100
>200 : 200
>300 : 300
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
>z : any
>tag`\u{hello} \xtraordinary wonderful \uworld` : any
>tag : (str: any, ...args: any[]) => any
>`\u{hello} \xtraordinary wonderful \uworld` : "\\u{hello} \\xtraordinary wonderful \\uworld"
const a1 = tag`${ 100 }\0` // \0
>a1 : any
>tag`${ 100 }\0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\0` : string
>100 : 100
const a2 = tag`${ 100 }\00` // \\00
>a2 : any
>tag`${ 100 }\00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\00` : string
>100 : 100
const a3 = tag`${ 100 }\u` // \\u
>a3 : any
>tag`${ 100 }\u` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u` : string
>100 : 100
const a4 = tag`${ 100 }\u0` // \\u0
>a4 : any
>tag`${ 100 }\u0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u0` : string
>100 : 100
const a5 = tag`${ 100 }\u00` // \\u00
>a5 : any
>tag`${ 100 }\u00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u00` : string
>100 : 100
const a6 = tag`${ 100 }\u000` // \\u000
>a6 : any
>tag`${ 100 }\u000` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u000` : string
>100 : 100
const a7 = tag`${ 100 }\u0000` // \u0000
>a7 : any
>tag`${ 100 }\u0000` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u0000` : string
>100 : 100
const a8 = tag`${ 100 }\u{` // \\u{
>a8 : any
>tag`${ 100 }\u{` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{` : string
>100 : 100
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
>a9 : any
>tag`${ 100 }\u{10FFFF}` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{10FFFF}` : string
>100 : 100
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
>a10 : any
>tag`${ 100 }\u{1f622` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{1f622` : string
>100 : 100
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
>a11 : any
>tag`${ 100 }\u{1f622}` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{1f622}` : string
>100 : 100
const a12 = tag`${ 100 }\x` // \\x
>a12 : any
>tag`${ 100 }\x` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x` : string
>100 : 100
const a13 = tag`${ 100 }\x0` // \\x0
>a13 : any
>tag`${ 100 }\x0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x0` : string
>100 : 100
const a14 = tag`${ 100 }\x00` // \x00
>a14 : any
>tag`${ 100 }\x00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x00` : string
>100 : 100

View file

@ -0,0 +1,49 @@
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) ====
function tag (str: any, ...args: any[]): any {
return str
}
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.
!!! error TS1125: Hexadecimal digit expected.
!!! 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
const a3 = tag`${ 100 }\u` // \\u
const a4 = tag`${ 100 }\u0` // \\u0
const a5 = tag`${ 100 }\u00` // \\u00
const a6 = tag`${ 100 }\u000` // \\u000
const a7 = tag`${ 100 }\u0000` // \u0000
const a8 = tag`${ 100 }\u{` // \\u{
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
const a12 = tag`${ 100 }\x` // \\x
const a13 = tag`${ 100 }\x0` // \\x0
const a14 = tag`${ 100 }\x00` // \x00

View file

@ -0,0 +1,50 @@
//// [invalidTaggedTemplateEscapeSequences.ts]
function tag (str: any, ...args: any[]): any {
return str
}
const a = tag`123`
const b = tag`123 ${100}`
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
const a1 = tag`${ 100 }\0` // \0
const a2 = tag`${ 100 }\00` // \\00
const a3 = tag`${ 100 }\u` // \\u
const a4 = tag`${ 100 }\u0` // \\u0
const a5 = tag`${ 100 }\u00` // \\u00
const a6 = tag`${ 100 }\u000` // \\u000
const a7 = tag`${ 100 }\u0000` // \u0000
const a8 = tag`${ 100 }\u{` // \\u{
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
const a12 = tag`${ 100 }\x` // \\x
const a13 = tag`${ 100 }\x0` // \\x0
const a14 = tag`${ 100 }\x00` // \x00
//// [invalidTaggedTemplateEscapeSequences.js]
function tag(str, ...args) {
return str;
}
const a = tag `123`;
const b = tag `123 ${100}`;
const x = tag `\u{hello} ${100} \xtraordinary ${200} wonderful ${300} \uworld`;
const y = `\u{hello} ${100} \xtraordinary ${200} wonderful ${300} \uworld`; // should error with NoSubstitutionTemplate
const z = tag `\u{hello} \xtraordinary wonderful \uworld`; // should work with Tagged NoSubstitutionTemplate
const a1 = tag `${100}\0`; // \0
const a2 = tag `${100}\00`; // \\00
const a3 = tag `${100}\u`; // \\u
const a4 = tag `${100}\u0`; // \\u0
const a5 = tag `${100}\u00`; // \\u00
const a6 = tag `${100}\u000`; // \\u000
const a7 = tag `${100}\u0000`; // \u0000
const a8 = tag `${100}\u{`; // \\u{
const a9 = tag `${100}\u{10FFFF}`; // \\u{10FFFF
const a10 = tag `${100}\u{1f622`; // \\u{1f622
const a11 = tag `${100}\u{1f622}`; // \u{1f622}
const a12 = tag `${100}\x`; // \\x
const a13 = tag `${100}\x0`; // \\x0
const a14 = tag `${100}\x00`; // \x00

View file

@ -0,0 +1,85 @@
=== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts ===
function tag (str: any, ...args: any[]): any {
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
>str : Symbol(str, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 14))
>args : Symbol(args, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 23))
return str
>str : Symbol(str, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 14))
}
const a = tag`123`
>a : Symbol(a, Decl(invalidTaggedTemplateEscapeSequences.ts, 4, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const b = tag`123 ${100}`
>b : Symbol(b, Decl(invalidTaggedTemplateEscapeSequences.ts, 5, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
>x : Symbol(x, Decl(invalidTaggedTemplateEscapeSequences.ts, 6, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
>y : Symbol(y, Decl(invalidTaggedTemplateEscapeSequences.ts, 7, 5))
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
>z : Symbol(z, Decl(invalidTaggedTemplateEscapeSequences.ts, 8, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a1 = tag`${ 100 }\0` // \0
>a1 : Symbol(a1, Decl(invalidTaggedTemplateEscapeSequences.ts, 10, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a2 = tag`${ 100 }\00` // \\00
>a2 : Symbol(a2, Decl(invalidTaggedTemplateEscapeSequences.ts, 11, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a3 = tag`${ 100 }\u` // \\u
>a3 : Symbol(a3, Decl(invalidTaggedTemplateEscapeSequences.ts, 12, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a4 = tag`${ 100 }\u0` // \\u0
>a4 : Symbol(a4, Decl(invalidTaggedTemplateEscapeSequences.ts, 13, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a5 = tag`${ 100 }\u00` // \\u00
>a5 : Symbol(a5, Decl(invalidTaggedTemplateEscapeSequences.ts, 14, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a6 = tag`${ 100 }\u000` // \\u000
>a6 : Symbol(a6, Decl(invalidTaggedTemplateEscapeSequences.ts, 15, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a7 = tag`${ 100 }\u0000` // \u0000
>a7 : Symbol(a7, Decl(invalidTaggedTemplateEscapeSequences.ts, 16, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a8 = tag`${ 100 }\u{` // \\u{
>a8 : Symbol(a8, Decl(invalidTaggedTemplateEscapeSequences.ts, 17, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
>a9 : Symbol(a9, Decl(invalidTaggedTemplateEscapeSequences.ts, 18, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
>a10 : Symbol(a10, Decl(invalidTaggedTemplateEscapeSequences.ts, 19, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
>a11 : Symbol(a11, Decl(invalidTaggedTemplateEscapeSequences.ts, 20, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a12 = tag`${ 100 }\x` // \\x
>a12 : Symbol(a12, Decl(invalidTaggedTemplateEscapeSequences.ts, 21, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a13 = tag`${ 100 }\x0` // \\x0
>a13 : Symbol(a13, Decl(invalidTaggedTemplateEscapeSequences.ts, 22, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a14 = tag`${ 100 }\x00` // \x00
>a14 : Symbol(a14, Decl(invalidTaggedTemplateEscapeSequences.ts, 23, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))

View file

@ -0,0 +1,143 @@
=== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts ===
function tag (str: any, ...args: any[]): any {
>tag : (str: any, ...args: any[]) => any
>str : any
>args : any[]
return str
>str : any
}
const a = tag`123`
>a : any
>tag`123` : any
>tag : (str: any, ...args: any[]) => any
>`123` : "123"
const b = tag`123 ${100}`
>b : any
>tag`123 ${100}` : any
>tag : (str: any, ...args: any[]) => any
>`123 ${100}` : string
>100 : 100
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
>x : any
>tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : any
>tag : (str: any, ...args: any[]) => any
>`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : string
>100 : 100
>200 : 200
>300 : 300
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
>y : string
>`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : string
>100 : 100
>200 : 200
>300 : 300
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
>z : any
>tag`\u{hello} \xtraordinary wonderful \uworld` : any
>tag : (str: any, ...args: any[]) => any
>`\u{hello} \xtraordinary wonderful \uworld` : "\\u{hello} \\xtraordinary wonderful \\uworld"
const a1 = tag`${ 100 }\0` // \0
>a1 : any
>tag`${ 100 }\0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\0` : string
>100 : 100
const a2 = tag`${ 100 }\00` // \\00
>a2 : any
>tag`${ 100 }\00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\00` : string
>100 : 100
const a3 = tag`${ 100 }\u` // \\u
>a3 : any
>tag`${ 100 }\u` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u` : string
>100 : 100
const a4 = tag`${ 100 }\u0` // \\u0
>a4 : any
>tag`${ 100 }\u0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u0` : string
>100 : 100
const a5 = tag`${ 100 }\u00` // \\u00
>a5 : any
>tag`${ 100 }\u00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u00` : string
>100 : 100
const a6 = tag`${ 100 }\u000` // \\u000
>a6 : any
>tag`${ 100 }\u000` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u000` : string
>100 : 100
const a7 = tag`${ 100 }\u0000` // \u0000
>a7 : any
>tag`${ 100 }\u0000` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u0000` : string
>100 : 100
const a8 = tag`${ 100 }\u{` // \\u{
>a8 : any
>tag`${ 100 }\u{` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{` : string
>100 : 100
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
>a9 : any
>tag`${ 100 }\u{10FFFF}` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{10FFFF}` : string
>100 : 100
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
>a10 : any
>tag`${ 100 }\u{1f622` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{1f622` : string
>100 : 100
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
>a11 : any
>tag`${ 100 }\u{1f622}` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{1f622}` : string
>100 : 100
const a12 = tag`${ 100 }\x` // \\x
>a12 : any
>tag`${ 100 }\x` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x` : string
>100 : 100
const a13 = tag`${ 100 }\x0` // \\x0
>a13 : any
>tag`${ 100 }\x0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x0` : string
>100 : 100
const a14 = tag`${ 100 }\x00` // \x00
>a14 : any
>tag`${ 100 }\x00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x00` : string
>100 : 100

View file

@ -0,0 +1,49 @@
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) ====
function tag (str: any, ...args: any[]): any {
return str
}
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.
!!! error TS1125: Hexadecimal digit expected.
!!! 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
const a3 = tag`${ 100 }\u` // \\u
const a4 = tag`${ 100 }\u0` // \\u0
const a5 = tag`${ 100 }\u00` // \\u00
const a6 = tag`${ 100 }\u000` // \\u000
const a7 = tag`${ 100 }\u0000` // \u0000
const a8 = tag`${ 100 }\u{` // \\u{
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
const a12 = tag`${ 100 }\x` // \\x
const a13 = tag`${ 100 }\x0` // \\x0
const a14 = tag`${ 100 }\x00` // \x00

View file

@ -0,0 +1,58 @@
//// [invalidTaggedTemplateEscapeSequences.ts]
function tag (str: any, ...args: any[]): any {
return str
}
const a = tag`123`
const b = tag`123 ${100}`
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
const a1 = tag`${ 100 }\0` // \0
const a2 = tag`${ 100 }\00` // \\00
const a3 = tag`${ 100 }\u` // \\u
const a4 = tag`${ 100 }\u0` // \\u0
const a5 = tag`${ 100 }\u00` // \\u00
const a6 = tag`${ 100 }\u000` // \\u000
const a7 = tag`${ 100 }\u0000` // \u0000
const a8 = tag`${ 100 }\u{` // \\u{
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
const a12 = tag`${ 100 }\x` // \\x
const a13 = tag`${ 100 }\x0` // \\x0
const a14 = tag`${ 100 }\x00` // \x00
//// [invalidTaggedTemplateEscapeSequences.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 tag(str) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
return str;
}
var a = tag(__makeTemplateObject(["123"], ["123"]));
var b = tag(__makeTemplateObject(["123 ", ""], ["123 ", ""]), 100);
var x = tag(__makeTemplateObject([undefined, undefined, " wonderful ", undefined], ["\\u{hello} ", " \\xtraordinary ", " wonderful ", " \\uworld"]), 100, 200, 300);
var y = "hello} " + 100 + " traordinary " + 200 + " wonderful " + 300 + " world"; // should error with NoSubstitutionTemplate
var z = tag(__makeTemplateObject([undefined], ["\\u{hello} \\xtraordinary wonderful \\uworld"])); // should work with Tagged NoSubstitutionTemplate
var a1 = tag(__makeTemplateObject(["", "\0"], ["", "\\0"]), 100); // \0
var a2 = tag(__makeTemplateObject(["", undefined], ["", "\\00"]), 100); // \\00
var a3 = tag(__makeTemplateObject(["", undefined], ["", "\\u"]), 100); // \\u
var a4 = tag(__makeTemplateObject(["", undefined], ["", "\\u0"]), 100); // \\u0
var a5 = tag(__makeTemplateObject(["", undefined], ["", "\\u00"]), 100); // \\u00
var a6 = tag(__makeTemplateObject(["", undefined], ["", "\\u000"]), 100); // \\u000
var a7 = tag(__makeTemplateObject(["", "\0"], ["", "\\u0000"]), 100); // \u0000
var a8 = tag(__makeTemplateObject(["", undefined], ["", "\\u{"]), 100); // \\u{
var a9 = tag(__makeTemplateObject(["", "\uDBFF\uDFFF"], ["", "\\u{10FFFF}"]), 100); // \\u{10FFFF
var a10 = tag(__makeTemplateObject(["", undefined], ["", "\\u{1f622"]), 100); // \\u{1f622
var a11 = tag(__makeTemplateObject(["", "\uD83D\uDE22"], ["", "\\u{1f622}"]), 100); // \u{1f622}
var a12 = tag(__makeTemplateObject(["", undefined], ["", "\\x"]), 100); // \\x
var a13 = tag(__makeTemplateObject(["", undefined], ["", "\\x0"]), 100); // \\x0
var a14 = tag(__makeTemplateObject(["", "\0"], ["", "\\x00"]), 100); // \x00

View file

@ -0,0 +1,85 @@
=== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts ===
function tag (str: any, ...args: any[]): any {
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
>str : Symbol(str, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 14))
>args : Symbol(args, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 23))
return str
>str : Symbol(str, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 14))
}
const a = tag`123`
>a : Symbol(a, Decl(invalidTaggedTemplateEscapeSequences.ts, 4, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const b = tag`123 ${100}`
>b : Symbol(b, Decl(invalidTaggedTemplateEscapeSequences.ts, 5, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
>x : Symbol(x, Decl(invalidTaggedTemplateEscapeSequences.ts, 6, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
>y : Symbol(y, Decl(invalidTaggedTemplateEscapeSequences.ts, 7, 5))
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
>z : Symbol(z, Decl(invalidTaggedTemplateEscapeSequences.ts, 8, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a1 = tag`${ 100 }\0` // \0
>a1 : Symbol(a1, Decl(invalidTaggedTemplateEscapeSequences.ts, 10, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a2 = tag`${ 100 }\00` // \\00
>a2 : Symbol(a2, Decl(invalidTaggedTemplateEscapeSequences.ts, 11, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a3 = tag`${ 100 }\u` // \\u
>a3 : Symbol(a3, Decl(invalidTaggedTemplateEscapeSequences.ts, 12, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a4 = tag`${ 100 }\u0` // \\u0
>a4 : Symbol(a4, Decl(invalidTaggedTemplateEscapeSequences.ts, 13, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a5 = tag`${ 100 }\u00` // \\u00
>a5 : Symbol(a5, Decl(invalidTaggedTemplateEscapeSequences.ts, 14, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a6 = tag`${ 100 }\u000` // \\u000
>a6 : Symbol(a6, Decl(invalidTaggedTemplateEscapeSequences.ts, 15, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a7 = tag`${ 100 }\u0000` // \u0000
>a7 : Symbol(a7, Decl(invalidTaggedTemplateEscapeSequences.ts, 16, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a8 = tag`${ 100 }\u{` // \\u{
>a8 : Symbol(a8, Decl(invalidTaggedTemplateEscapeSequences.ts, 17, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
>a9 : Symbol(a9, Decl(invalidTaggedTemplateEscapeSequences.ts, 18, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
>a10 : Symbol(a10, Decl(invalidTaggedTemplateEscapeSequences.ts, 19, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
>a11 : Symbol(a11, Decl(invalidTaggedTemplateEscapeSequences.ts, 20, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a12 = tag`${ 100 }\x` // \\x
>a12 : Symbol(a12, Decl(invalidTaggedTemplateEscapeSequences.ts, 21, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a13 = tag`${ 100 }\x0` // \\x0
>a13 : Symbol(a13, Decl(invalidTaggedTemplateEscapeSequences.ts, 22, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))
const a14 = tag`${ 100 }\x00` // \x00
>a14 : Symbol(a14, Decl(invalidTaggedTemplateEscapeSequences.ts, 23, 5))
>tag : Symbol(tag, Decl(invalidTaggedTemplateEscapeSequences.ts, 0, 0))

View file

@ -0,0 +1,143 @@
=== tests/cases/conformance/es2018/invalidTaggedTemplateEscapeSequences.ts ===
function tag (str: any, ...args: any[]): any {
>tag : (str: any, ...args: any[]) => any
>str : any
>args : any[]
return str
>str : any
}
const a = tag`123`
>a : any
>tag`123` : any
>tag : (str: any, ...args: any[]) => any
>`123` : "123"
const b = tag`123 ${100}`
>b : any
>tag`123 ${100}` : any
>tag : (str: any, ...args: any[]) => any
>`123 ${100}` : string
>100 : 100
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
>x : any
>tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : any
>tag : (str: any, ...args: any[]) => any
>`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : string
>100 : 100
>200 : 200
>300 : 300
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
>y : string
>`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld` : string
>100 : 100
>200 : 200
>300 : 300
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
>z : any
>tag`\u{hello} \xtraordinary wonderful \uworld` : any
>tag : (str: any, ...args: any[]) => any
>`\u{hello} \xtraordinary wonderful \uworld` : "\\u{hello} \\xtraordinary wonderful \\uworld"
const a1 = tag`${ 100 }\0` // \0
>a1 : any
>tag`${ 100 }\0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\0` : string
>100 : 100
const a2 = tag`${ 100 }\00` // \\00
>a2 : any
>tag`${ 100 }\00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\00` : string
>100 : 100
const a3 = tag`${ 100 }\u` // \\u
>a3 : any
>tag`${ 100 }\u` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u` : string
>100 : 100
const a4 = tag`${ 100 }\u0` // \\u0
>a4 : any
>tag`${ 100 }\u0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u0` : string
>100 : 100
const a5 = tag`${ 100 }\u00` // \\u00
>a5 : any
>tag`${ 100 }\u00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u00` : string
>100 : 100
const a6 = tag`${ 100 }\u000` // \\u000
>a6 : any
>tag`${ 100 }\u000` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u000` : string
>100 : 100
const a7 = tag`${ 100 }\u0000` // \u0000
>a7 : any
>tag`${ 100 }\u0000` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u0000` : string
>100 : 100
const a8 = tag`${ 100 }\u{` // \\u{
>a8 : any
>tag`${ 100 }\u{` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{` : string
>100 : 100
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
>a9 : any
>tag`${ 100 }\u{10FFFF}` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{10FFFF}` : string
>100 : 100
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
>a10 : any
>tag`${ 100 }\u{1f622` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{1f622` : string
>100 : 100
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
>a11 : any
>tag`${ 100 }\u{1f622}` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\u{1f622}` : string
>100 : 100
const a12 = tag`${ 100 }\x` // \\x
>a12 : any
>tag`${ 100 }\x` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x` : string
>100 : 100
const a13 = tag`${ 100 }\x0` // \\x0
>a13 : any
>tag`${ 100 }\x0` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x0` : string
>100 : 100
const a14 = tag`${ 100 }\x00` // \x00
>a14 : any
>tag`${ 100 }\x00` : any
>tag : (str: any, ...args: any[]) => any
>`${ 100 }\x00` : string
>100 : 100

View file

@ -0,0 +1,26 @@
// @target: ES5, ES2015, esnext
function tag (str: any, ...args: any[]): any {
return str
}
const a = tag`123`
const b = tag`123 ${100}`
const x = tag`\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`;
const y = `\u{hello} ${ 100 } \xtraordinary ${ 200 } wonderful ${ 300 } \uworld`; // should error with NoSubstitutionTemplate
const z = tag`\u{hello} \xtraordinary wonderful \uworld` // should work with Tagged NoSubstitutionTemplate
const a1 = tag`${ 100 }\0` // \0
const a2 = tag`${ 100 }\00` // \\00
const a3 = tag`${ 100 }\u` // \\u
const a4 = tag`${ 100 }\u0` // \\u0
const a5 = tag`${ 100 }\u00` // \\u00
const a6 = tag`${ 100 }\u000` // \\u000
const a7 = tag`${ 100 }\u0000` // \u0000
const a8 = tag`${ 100 }\u{` // \\u{
const a9 = tag`${ 100 }\u{10FFFF}` // \\u{10FFFF
const a10 = tag`${ 100 }\u{1f622` // \\u{1f622
const a11 = tag`${ 100 }\u{1f622}` // \u{1f622}
const a12 = tag`${ 100 }\x` // \\x
const a13 = tag`${ 100 }\x0` // \\x0
const a14 = tag`${ 100 }\x00` // \x00