baa74e89b6
A previous patch lifting the restriction on invalid escape sequences in tagged templates had a bug when two template tokens appeared immediately adject to each other. This moves invalid escape information from the tokenizer state proper into the TokenDesc, preventing the overwriting which caused this issue. Previous CL is at https://codereview.chromium.org/2665513002 BUG=v8:6029,v8:5546 Review-Url: https://codereview.chromium.org/2724003006 Cr-Commit-Position: refs/heads/master@{#43596}
873 lines
8.9 KiB
JavaScript
873 lines
8.9 KiB
JavaScript
// Copyright 2016 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Flags: --harmony-template-escapes
|
|
|
|
function check({cooked, raw, exprs}) {
|
|
return function(strs, ...args) {
|
|
assertArrayEquals(cooked, strs);
|
|
assertArrayEquals(raw, strs.raw);
|
|
assertArrayEquals(exprs, args);
|
|
};
|
|
}
|
|
|
|
// clang-format off
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\01'
|
|
],
|
|
'exprs': []
|
|
})`\01`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\01',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\01${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\01'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\01`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\01',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\01${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\1'
|
|
],
|
|
'exprs': []
|
|
})`\1`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\1',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\1${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\1'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\1`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\1',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\1${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\xg'
|
|
],
|
|
'exprs': []
|
|
})`\xg`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\xg',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\xg${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\xg'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\xg`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\xg',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\xg${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\xAg'
|
|
],
|
|
'exprs': []
|
|
})`\xAg`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\xAg',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\xAg${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\xAg'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\xAg`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\xAg',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\xAg${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u0'
|
|
],
|
|
'exprs': []
|
|
})`\u0`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u0',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u0${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u0'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u0`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u0',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u0${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u0g'
|
|
],
|
|
'exprs': []
|
|
})`\u0g`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u0g',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u0g${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u0g'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u0g`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u0g',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u0g${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u00g'
|
|
],
|
|
'exprs': []
|
|
})`\u00g`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u00g',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u00g${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u00g'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u00g`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u00g',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u00g${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u000g'
|
|
],
|
|
'exprs': []
|
|
})`\u000g`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u000g',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u000g${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u000g'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u000g`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u000g',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u000g${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u{}'
|
|
],
|
|
'exprs': []
|
|
})`\u{}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u{}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u{}${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{}'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u{}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u{}${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u{-0}'
|
|
],
|
|
'exprs': []
|
|
})`\u{-0}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u{-0}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u{-0}${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{-0}'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u{-0}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{-0}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u{-0}${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u{g}'
|
|
],
|
|
'exprs': []
|
|
})`\u{g}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u{g}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u{g}${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{g}'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u{g}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{g}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u{g}${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u{0'
|
|
],
|
|
'exprs': []
|
|
})`\u{0`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u{0',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u{0${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{0'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u{0`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{0',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u{0${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u{\\u{0}'
|
|
],
|
|
'exprs': []
|
|
})`\u{\u{0}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u{\\u{0}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u{\u{0}${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{\\u{0}'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u{\u{0}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{\\u{0}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u{\u{0}${1}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u{110000}'
|
|
],
|
|
'exprs': []
|
|
})`\u{110000}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'\\u{110000}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`\u{110000}${0}right`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{110000}'
|
|
],
|
|
'exprs': [
|
|
0
|
|
]
|
|
})`left${0}\u{110000}`;
|
|
|
|
check({
|
|
'cooked': [
|
|
'left',
|
|
undefined,
|
|
'right'
|
|
],
|
|
'raw': [
|
|
'left',
|
|
'\\u{110000}',
|
|
'right'
|
|
],
|
|
'exprs': [
|
|
0,
|
|
1
|
|
]
|
|
})`left${0}\u{110000}${1}right`;
|
|
|
|
|
|
|
|
function checkMultiple(expectedArray) {
|
|
let results = [];
|
|
return function consume(strs, ...args) {
|
|
if (typeof strs === 'undefined') {
|
|
assertArrayEquals(expectedArray, results);
|
|
} else {
|
|
results.push({cooked: strs, raw: strs.raw, exprs: args});
|
|
return consume;
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
checkMultiple([{
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u',
|
|
],
|
|
'exprs': []
|
|
}, {
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u',
|
|
],
|
|
'exprs': []
|
|
}])`\u``\u`();
|
|
|
|
checkMultiple([{
|
|
'cooked': [
|
|
' '
|
|
],
|
|
'raw': [
|
|
' ',
|
|
],
|
|
'exprs': []
|
|
}, {
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u',
|
|
],
|
|
'exprs': []
|
|
}])` ``\u`();
|
|
|
|
checkMultiple([{
|
|
'cooked': [
|
|
undefined
|
|
],
|
|
'raw': [
|
|
'\\u',
|
|
],
|
|
'exprs': []
|
|
}, {
|
|
'cooked': [
|
|
' '
|
|
],
|
|
'raw': [
|
|
' ',
|
|
],
|
|
'exprs': []
|
|
}])`\u`` `();
|
|
|
|
checkMultiple([{
|
|
'cooked': [
|
|
' '
|
|
],
|
|
'raw': [
|
|
' ',
|
|
],
|
|
'exprs': []
|
|
}, {
|
|
'cooked': [
|
|
' '
|
|
],
|
|
'raw': [
|
|
' ',
|
|
],
|
|
'exprs': []
|
|
}])` `` `();
|