Diff
Modified: trunk/JSTests/ChakraCore/test/es6/unicode_6_identifier_Blue524737.baseline-jsc (211318 => 211319)
--- trunk/JSTests/ChakraCore/test/es6/unicode_6_identifier_Blue524737.baseline-jsc 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/JSTests/ChakraCore/test/es6/unicode_6_identifier_Blue524737.baseline-jsc 2017-01-28 03:09:12 UTC (rev 211319)
@@ -1,2 +1,2 @@
-Exception: SyntaxError: Invalid unicode escape in identifier: '\u{13407'
+Exception: SyntaxError: Invalid unicode escape in identifier: '\u{134071'
at unicode_6_identifier_Blue524737.js:6
Modified: trunk/JSTests/ChangeLog (211318 => 211319)
--- trunk/JSTests/ChangeLog 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/JSTests/ChangeLog 2017-01-28 03:09:12 UTC (rev 211319)
@@ -1,3 +1,19 @@
+2017-01-27 Yusuke Suzuki <utatane....@gmail.com>
+
+ Lift template escape sequence restrictions in tagged templates
+ https://bugs.webkit.org/show_bug.cgi?id=166871
+
+ Reviewed by Saam Barati.
+
+ Update the error messages and add new tests.
+
+ * ChakraCore/test/es6/unicode_6_identifier_Blue524737.baseline-jsc:
+ * stress/lift-template-literal.js: Added.
+ (dump):
+ (testTag.return.tag):
+ (testTag):
+ * stress/template-literal-syntax.js:
+
2017-01-26 Mark Lam <mark....@apple.com>
Fix missing exception check in genericTypedArrayViewProtoFuncSet().
Added: trunk/JSTests/stress/lift-template-literal.js (0 => 211319)
--- trunk/JSTests/stress/lift-template-literal.js (rev 0)
+++ trunk/JSTests/stress/lift-template-literal.js 2017-01-28 03:09:12 UTC (rev 211319)
@@ -0,0 +1,69 @@
+function dump(callSite)
+{
+ return JSON.stringify({ cooked: callSite, raw: callSite.raw });
+}
+
+function shouldBe(actual, expected)
+{
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+shouldBe(dump`\newcommand{\fun}{\textbf{Fun!}}`, `{"cooked":["\\newcommand{\\fun}{\\textbf{Fun!}}"],"raw":["\\\\newcommand{\\\\fun}{\\\\textbf{Fun!}}"]}`);
+shouldBe(dump`\newcommand{\unicode}{\textbf{Unicode!}}`, `{"cooked":[null],"raw":["\\\\newcommand{\\\\unicode}{\\\\textbf{Unicode!}}"]}`);
+shouldBe(dump`\newcommand{\xerxes}{\textbf{King!}}`, `{"cooked":[null],"raw":["\\\\newcommand{\\\\xerxes}{\\\\textbf{King!}}"]}`);
+shouldBe(dump`Breve over the h goes \u{h}ere`, `{"cooked":[null],"raw":["Breve over the h goes \\\\u{h}ere"]}`);
+
+function testTag(expected) {
+ return function tag(callSite) {
+ shouldBe(callSite.length, expected.cooked.length);
+ shouldBe(callSite.raw.length, expected.raw.length);
+ expected.cooked.forEach((value, index) => shouldBe(callSite[index], value));
+ expected.raw.forEach((value, index) => shouldBe(callSite.raw[index], value));
+ }
+}
+
+testTag({
+ cooked: [ undefined ],
+ raw: [ "\\unicode and \\u{55}" ],
+})`\unicode and \u{55}`;
+
+testTag({
+ cooked: [ undefined, "test" ],
+ raw: [ "\\unicode and \\u{55}", "test" ],
+})`\unicode and \u{55}${42}test`;
+
+testTag({
+ cooked: [ undefined, undefined, "Cocoa" ],
+ raw: [ "\\unicode and \\u{55}", "\\uhello", "Cocoa" ],
+})`\unicode and \u{55}${42}\uhello${42}Cocoa`;
+
+testTag({
+ cooked: [ "Cocoa", undefined, undefined, "Cocoa" ],
+ raw: [ "Cocoa", "\\unicode and \\u{55}", "\\uhello", "Cocoa" ],
+})`Cocoa${42}\unicode and \u{55}${42}\uhello${42}Cocoa`;
+
+testTag({
+ cooked: [ "Cocoa", undefined, undefined, "Cocoa" ],
+ raw: [ "Cocoa", "\\unicode and \\u{55}", "\\uhello", "Cocoa" ],
+})`Cocoa${42}\unicode and \u{55}${42}\uhello${42}Cocoa`;
+
+testTag({
+ cooked: [ undefined, undefined, undefined ],
+ raw: [ "\\00", "\\01", "\\1" ]
+})`\00${42}\01${42}\1`;
+
+testTag({
+ cooked: [ undefined, undefined ],
+ raw: [ "\\xo", "\\x0o" ]
+})`\xo${42}\x0o`;
+
+testTag({
+ cooked: [ undefined, undefined, undefined, undefined ],
+ raw: [ "\\uo", "\\u0o", "\\u00o", "\\u000o" ]
+})`\uo${42}\u0o${42}\u00o${42}\u000o`;
+
+testTag({
+ cooked: [ undefined, undefined, undefined ],
+ raw: [ "\\u{o", "\\u{0o", "\\u{110000o" ]
+})`\u{o${42}\u{0o${42}\u{110000o`;
Modified: trunk/JSTests/stress/template-literal-syntax.js (211318 => 211319)
--- trunk/JSTests/stress/template-literal-syntax.js 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/JSTests/stress/template-literal-syntax.js 2017-01-28 03:09:12 UTC (rev 211319)
@@ -46,6 +46,19 @@
testSyntax("`\\\n`");
testSyntax("`\\\r\n`");
testSyntax("`\\\r`");
+testSyntax("Hello`bad escape sequence: \\unicode`");
+testSyntax("Hello`\\00`");
+testSyntax("Hello`\\01`");
+testSyntax("Hello`\\1`");
+testSyntax("Hello`\\xo`");
+testSyntax("Hello`\\x0o`");
+testSyntax("Hello`\\uo`");
+testSyntax("Hello`\\u0o`");
+testSyntax("Hello`\\u00o`");
+testSyntax("Hello`\\u000o`");
+testSyntax("Hello`\\u{o`");
+testSyntax("Hello`\\u{0o`");
+testSyntax("Hello`\\u{110000o`");
testSyntaxError("`Hello", "SyntaxError: Unexpected EOF");
testSyntaxError("`Hello${expr}", "SyntaxError: Unexpected EOF");
@@ -81,3 +94,18 @@
testSyntaxError("`${expr}\\u20`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
testSyntaxError("`\\u202`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
testSyntaxError("`${expr}\\u202`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+
+testSyntaxError("`bad escape sequence: \\unicode`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+
+testSyntaxError("`\\00`", "SyntaxError: The only valid numeric escape in strict mode is '\\0'");
+testSyntaxError("`\\01`", "SyntaxError: The only valid numeric escape in strict mode is '\\0'");
+testSyntaxError("`\\1`", "SyntaxError: The only valid numeric escape in strict mode is '\\0'");
+testSyntaxError("`\\xo`", "SyntaxError: \\x can only be followed by a hex character sequence");
+testSyntaxError("`\\x0o`", "SyntaxError: \\x can only be followed by a hex character sequence");
+testSyntaxError("`\\uo`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`\\u0o`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`\\u00o`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`\\u000o`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`\\u{o`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`\\u{0o`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`\\u{110000o`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
Modified: trunk/LayoutTests/ChangeLog (211318 => 211319)
--- trunk/LayoutTests/ChangeLog 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/LayoutTests/ChangeLog 2017-01-28 03:09:12 UTC (rev 211319)
@@ -1,5 +1,17 @@
2017-01-27 Yusuke Suzuki <utatane....@gmail.com>
+ Lift template escape sequence restrictions in tagged templates
+ https://bugs.webkit.org/show_bug.cgi?id=166871
+
+ Reviewed by Saam Barati.
+
+ Update the error messages.
+
+ * inspector/runtime/parse-expected.txt:
+ * js/unicode-escape-sequences-expected.txt:
+
+2017-01-27 Yusuke Suzuki <utatane....@gmail.com>
+
setTimeout / setInterval's string execution should inherit SourceOrigin correctly
https://bugs.webkit.org/show_bug.cgi?id=167097
Modified: trunk/LayoutTests/inspector/runtime/parse-expected.txt (211318 => 211319)
--- trunk/LayoutTests/inspector/runtime/parse-expected.txt 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/LayoutTests/inspector/runtime/parse-expected.txt 2017-01-28 03:09:12 UTC (rev 211319)
@@ -67,9 +67,9 @@
PASS: Should be SyntaxErrorType UnterminatedLiteral.
Source: var \u007
- ^~
-Error Message: Incomplete unicode escape in identifier: '\u'
-Range: {"startOffset":4,"endOffset":6}
+ ^~~~~
+Error Message: Incomplete unicode escape in identifier: '\u007'
+Range: {"startOffset":4,"endOffset":9}
-- Running test case: SyntaxErrorType.Recoverable
Modified: trunk/LayoutTests/js/unicode-escape-sequences-expected.txt (211318 => 211319)
--- trunk/LayoutTests/js/unicode-escape-sequences-expected.txt 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/LayoutTests/js/unicode-escape-sequences-expected.txt 2017-01-28 03:09:12 UTC (rev 211319)
@@ -58,9 +58,9 @@
PASS codeUnits(function \u{}(){}.name) threw exception SyntaxError: Invalid unicode escape in identifier: '\u{'.
PASS codeUnits(function \u{G}(){}.name) threw exception SyntaxError: Invalid unicode escape in identifier: '\u{'.
PASS codeUnits(function \u{1G}(){}.name) threw exception SyntaxError: Invalid unicode escape in identifier: '\u{1'.
-PASS codeUnits(function \u{110000}(){}.name) threw exception SyntaxError: Invalid unicode escape in identifier: '\u{11000'.
-PASS codeUnits(function \u{1000000}(){}.name) threw exception SyntaxError: Invalid unicode escape in identifier: '\u{100000'.
-PASS codeUnits(function \u{100000000000000000000000}(){}.name) threw exception SyntaxError: Invalid unicode escape in identifier: '\u{100000'.
+PASS codeUnits(function \u{110000}(){}.name) threw exception SyntaxError: Invalid unicode escape in identifier: '\u{110000'.
+PASS codeUnits(function \u{1000000}(){}.name) threw exception SyntaxError: Invalid unicode escape in identifier: '\u{1000000'.
+PASS codeUnits(function \u{100000000000000000000000}(){}.name) threw exception SyntaxError: Invalid unicode escape in identifier: '\u{100000000000000000000000'.
PASS codeUnits(function x\u{41}(){}.name.substring(1)) is "0041"
PASS codeUnits(function x\u{10000}(){}.name.substring(1)) is "D800,DC00"
PASS codeUnits(function x\u{10001}(){}.name.substring(1)) is "D800,DC01"
@@ -87,9 +87,9 @@
PASS codeUnits(function x\u{}(){}.name.substring(1)) threw exception SyntaxError: Invalid unicode escape in identifier: 'x\u{'.
PASS codeUnits(function x\u{G}(){}.name.substring(1)) threw exception SyntaxError: Invalid unicode escape in identifier: 'x\u{'.
PASS codeUnits(function x\u{1G}(){}.name.substring(1)) threw exception SyntaxError: Invalid unicode escape in identifier: 'x\u{1'.
-PASS codeUnits(function x\u{110000}(){}.name.substring(1)) threw exception SyntaxError: Invalid unicode escape in identifier: 'x\u{11000'.
-PASS codeUnits(function x\u{1000000}(){}.name.substring(1)) threw exception SyntaxError: Invalid unicode escape in identifier: 'x\u{100000'.
-PASS codeUnits(function x\u{100000000000000000000000}(){}.name.substring(1)) threw exception SyntaxError: Invalid unicode escape in identifier: 'x\u{100000'.
+PASS codeUnits(function x\u{110000}(){}.name.substring(1)) threw exception SyntaxError: Invalid unicode escape in identifier: 'x\u{110000'.
+PASS codeUnits(function x\u{1000000}(){}.name.substring(1)) threw exception SyntaxError: Invalid unicode escape in identifier: 'x\u{1000000'.
+PASS codeUnits(function x\u{100000000000000000000000}(){}.name.substring(1)) threw exception SyntaxError: Invalid unicode escape in identifier: 'x\u{100000000000000000000000'.
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/Source/_javascript_Core/ChangeLog (211318 => 211319)
--- trunk/Source/_javascript_Core/ChangeLog 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-01-28 03:09:12 UTC (rev 211319)
@@ -1,3 +1,68 @@
+2017-01-27 Yusuke Suzuki <utatane....@gmail.com>
+
+ Lift template escape sequence restrictions in tagged templates
+ https://bugs.webkit.org/show_bug.cgi?id=166871
+
+ Reviewed by Saam Barati.
+
+ This patch implements stage 3 Lifting Template Literal Restriction[1].
+ Prior to this patch, template literal becomes syntax error if it contains
+ invalid escape sequences. But it is too restricted; Template literal
+ can have cooked and raw representations and only cooked representation
+ can escape sequences. So even if invalid escape sequences are included,
+ the raw representation can be valid.
+
+ Lifting Template Literal Restriction relaxes the above restriction.
+ When invalid escape sequence is included, if target template literals
+ are used as tagged templates, we make the result of the template including
+ the invalid escape sequence `undefined` instead of making it SyntaxError
+ immediately. It allows us to accept the templates including invalid
+ escape sequences in the raw representations in tagged templates.
+
+ On the other hand, the raw representation is only used in tagged templates.
+ So if invalid escape sequences are included in the usual template literals,
+ we just make it SyntaxError as before.
+
+ [1]: https://github.com/tc39/proposal-template-literal-revision
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitGetTemplateObject):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::TemplateStringNode::emitBytecode):
+ (JSC::TemplateLiteralNode::emitBytecode):
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createTemplateString):
+ * parser/Lexer.cpp:
+ (JSC::Lexer<CharacterType>::parseUnicodeEscape):
+ (JSC::Lexer<T>::parseTemplateLiteral):
+ (JSC::Lexer<T>::lex):
+ (JSC::Lexer<T>::scanTemplateString):
+ (JSC::Lexer<T>::scanTrailingTemplateString): Deleted.
+ * parser/Lexer.h:
+ * parser/NodeConstructors.h:
+ (JSC::TemplateStringNode::TemplateStringNode):
+ * parser/Nodes.h:
+ (JSC::TemplateStringNode::cooked):
+ (JSC::TemplateStringNode::raw):
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseAssignmentElement):
+ (JSC::Parser<LexerType>::parseTemplateString):
+ (JSC::Parser<LexerType>::parseTemplateLiteral):
+ (JSC::Parser<LexerType>::parsePrimaryExpression):
+ (JSC::Parser<LexerType>::parseMemberExpression):
+ * parser/ParserTokens.h:
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::createTemplateString):
+ * runtime/TemplateRegistry.cpp:
+ (JSC::TemplateRegistry::getTemplateObject):
+ * runtime/TemplateRegistryKey.h:
+ (JSC::TemplateRegistryKey::cookedStrings):
+ (JSC::TemplateRegistryKey::create):
+ (JSC::TemplateRegistryKey::TemplateRegistryKey):
+ * runtime/TemplateRegistryKeyTable.cpp:
+ (JSC::TemplateRegistryKeyTable::createKey):
+ * runtime/TemplateRegistryKeyTable.h:
+
2017-01-27 Saam Barati <sbar...@apple.com>
Make the CLI for the sampling profiler better for inlined call site indices
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (211318 => 211319)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2017-01-28 03:09:12 UTC (rev 211319)
@@ -4253,17 +4253,22 @@
RegisterID* BytecodeGenerator::emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode* taggedTemplate)
{
TemplateRegistryKey::StringVector rawStrings;
- TemplateRegistryKey::StringVector cookedStrings;
+ TemplateRegistryKey::OptionalStringVector cookedStrings;
TemplateStringListNode* templateString = taggedTemplate->templateLiteral()->templateStrings();
for (; templateString; templateString = templateString->next()) {
- rawStrings.append(templateString->value()->raw().impl());
- cookedStrings.append(templateString->value()->cooked().impl());
+ auto* string = templateString->value();
+ ASSERT(string->raw());
+ rawStrings.append(string->raw()->impl());
+ if (!string->cooked())
+ cookedStrings.append(std::nullopt);
+ else
+ cookedStrings.append(string->cooked()->impl());
}
RefPtr<RegisterID> getTemplateObject = emitGetGlobalPrivate(newTemporary(), propertyNames().builtinNames().getTemplateObjectPrivateName());
CallArguments arguments(*this, nullptr);
- emitLoad(arguments.thisRegister(), JSValue(addTemplateRegistryKeyConstant(m_vm->templateRegistryKeyTable().createKey(rawStrings, cookedStrings))));
+ emitLoad(arguments.thisRegister(), JSValue(addTemplateRegistryKeyConstant(m_vm->templateRegistryKeyTable().createKey(WTFMove(rawStrings), WTFMove(cookedStrings)))));
return emitCall(dst, getTemplateObject.get(), NoExpectedFunction, arguments, taggedTemplate->divot(), taggedTemplate->divotStart(), taggedTemplate->divotEnd(), DebuggableCall::No);
}
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (211318 => 211319)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2017-01-28 03:09:12 UTC (rev 211319)
@@ -246,7 +246,8 @@
{
if (dst == generator.ignoredResult())
return nullptr;
- return generator.emitLoad(dst, JSValue(generator.addStringConstant(cooked())));
+ ASSERT(cooked());
+ return generator.emitLoad(dst, JSValue(generator.addStringConstant(*cooked())));
}
// ------------------------------ TemplateLiteralNode -----------------------------------
@@ -265,7 +266,8 @@
TemplateExpressionListNode* templateExpression = m_templateExpressions;
for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
// Evaluate TemplateString.
- if (!templateString->value()->cooked().isEmpty()) {
+ ASSERT(templateString->value()->cooked());
+ if (!templateString->value()->cooked()->isEmpty()) {
temporaryRegisters.append(generator.newTemporary());
generator.emitNode(temporaryRegisters.last().get(), templateString->value());
}
@@ -277,7 +279,8 @@
}
// Evaluate tail TemplateString.
- if (!templateString->value()->cooked().isEmpty()) {
+ ASSERT(templateString->value()->cooked());
+ if (!templateString->value()->cooked()->isEmpty()) {
temporaryRegisters.append(generator.newTemporary());
generator.emitNode(temporaryRegisters.last().get(), templateString->value());
}
Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (211318 => 211319)
--- trunk/Source/_javascript_Core/parser/ASTBuilder.h 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h 2017-01-28 03:09:12 UTC (rev 211319)
@@ -275,7 +275,7 @@
return node;
}
- TemplateStringNode* createTemplateString(const JSTokenLocation& location, const Identifier& cooked, const Identifier& raw)
+ TemplateStringNode* createTemplateString(const JSTokenLocation& location, const Identifier* cooked, const Identifier* raw)
{
return new (m_parserArena) TemplateStringNode(location, cooked, raw);
}
Modified: trunk/Source/_javascript_Core/parser/Lexer.cpp (211318 => 211319)
--- trunk/Source/_javascript_Core/parser/Lexer.cpp 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/parser/Lexer.cpp 2017-01-28 03:09:12 UTC (rev 211319)
@@ -633,7 +633,8 @@
UChar32 m_value;
};
-template<typename CharacterType> ParsedUnicodeEscapeValue Lexer<CharacterType>::parseUnicodeEscape()
+template<typename CharacterType>
+ParsedUnicodeEscapeValue Lexer<CharacterType>::parseUnicodeEscape()
{
if (m_current == '{') {
shift();
@@ -642,8 +643,26 @@
if (!isASCIIHexDigit(m_current))
return m_current ? ParsedUnicodeEscapeValue::Invalid : ParsedUnicodeEscapeValue::Incomplete;
codePoint = (codePoint << 4) | toASCIIHexValue(m_current);
- if (codePoint > UCHAR_MAX_VALUE)
- return ParsedUnicodeEscapeValue::Invalid;
+ if (codePoint > UCHAR_MAX_VALUE) {
+ // For raw template literal syntax, we consume `NotEscapeSequence`.
+ // Here, we consume NotCodePoint's HexDigits.
+ //
+ // NotEscapeSequence ::
+ // u { [lookahread not one of HexDigit]
+ // u { NotCodePoint
+ // u { CodePoint [lookahead != }]
+ //
+ // NotCodePoint ::
+ // HexDigits but not if MV of HexDigits <= 0x10FFFF
+ //
+ // CodePoint ::
+ // HexDigits but not if MV of HexDigits > 0x10FFFF
+ shift();
+ while (isASCIIHexDigit(m_current))
+ shift();
+
+ return atEnd() ? ParsedUnicodeEscapeValue::Incomplete : ParsedUnicodeEscapeValue::Invalid;
+ }
shift();
} while (m_current != '}');
shift();
@@ -653,8 +672,22 @@
auto character2 = peek(1);
auto character3 = peek(2);
auto character4 = peek(3);
- if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(character2) || !isASCIIHexDigit(character3) || !isASCIIHexDigit(character4)))
- return (m_code + 4) >= m_codeEnd ? ParsedUnicodeEscapeValue::Incomplete : ParsedUnicodeEscapeValue::Invalid;
+ if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(character2) || !isASCIIHexDigit(character3) || !isASCIIHexDigit(character4))) {
+ auto result = (m_code + 4) >= m_codeEnd ? ParsedUnicodeEscapeValue::Incomplete : ParsedUnicodeEscapeValue::Invalid;
+
+ // For raw template literal syntax, we consume `NotEscapeSequence`.
+ //
+ // NotEscapeSequence ::
+ // u [lookahead not one of HexDigit][lookahead != {]
+ // u HexDigit [lookahead not one of HexDigit]
+ // u HexDigit HexDigit [lookahead not one of HexDigit]
+ // u HexDigit HexDigit HexDigit [lookahead not one of HexDigit]
+ while (isASCIIHexDigit(m_current))
+ shift();
+
+ return result;
+ }
+
auto result = convertUnicode(m_current, character2, character3, character4);
shift();
shift();
@@ -1181,19 +1214,30 @@
}
template <typename T>
-template <bool shouldBuildStrings> ALWAYS_INLINE auto Lexer<T>::parseComplexEscape(EscapeParseMode escapeParseMode, bool strictMode, T stringQuoteCharacter) -> StringParseResult
+template <bool shouldBuildStrings, LexerEscapeParseMode escapeParseMode> ALWAYS_INLINE auto Lexer<T>::parseComplexEscape(bool strictMode, T stringQuoteCharacter) -> StringParseResult
{
if (m_current == 'x') {
shift();
if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) {
+ // For raw template literal syntax, we consume `NotEscapeSequence`.
+ //
+ // NotEscapeSequence ::
+ // x [lookahread not one of HexDigit]
+ // x HexDigit [lookahread not one of HexDigit]
+ if (isASCIIHexDigit(m_current))
+ shift();
+ ASSERT(!isASCIIHexDigit(m_current));
+
m_lexErrorMessage = ASCIILiteral("\\x can only be followed by a hex character sequence");
- return StringCannotBeParsed;
+ return atEnd() ? StringUnterminated : StringCannotBeParsed;
}
+
T prev = m_current;
shift();
if (shouldBuildStrings)
record16(convertHex(prev, m_current));
shift();
+
return StringParsedSuccessfully;
}
@@ -1200,7 +1244,7 @@
if (m_current == 'u') {
shift();
- if (escapeParseMode == EscapeParseMode::String && m_current == stringQuoteCharacter) {
+ if (escapeParseMode == LexerEscapeParseMode::String && m_current == stringQuoteCharacter) {
if (shouldBuildStrings)
record16('u');
return StringParsedSuccessfully;
@@ -1214,7 +1258,7 @@
}
m_lexErrorMessage = ASCIILiteral("\\u can only be followed by a Unicode character sequence");
- return character.isIncomplete() ? StringUnterminated : StringCannotBeParsed;
+ return atEnd() ? StringUnterminated : StringCannotBeParsed;
}
if (strictMode) {
@@ -1223,8 +1267,16 @@
int character1 = m_current;
shift();
if (character1 != '0' || isASCIIDigit(m_current)) {
+ // For raw template literal syntax, we consume `NotEscapeSequence`.
+ //
+ // NotEscapeSequence ::
+ // 0 DecimalDigit
+ // DecimalDigit but not 0
+ if (character1 == '0')
+ shift();
+
m_lexErrorMessage = ASCIILiteral("The only valid numeric escape in strict mode is '\\0'");
- return StringCannotBeParsed;
+ return atEnd() ? StringUnterminated : StringCannotBeParsed;
}
if (shouldBuildStrings)
record16(0);
@@ -1290,7 +1342,7 @@
} else if (UNLIKELY(isLineTerminator(m_current)))
shiftLineTerminator();
else {
- StringParseResult result = parseComplexEscape<shouldBuildStrings>(EscapeParseMode::String, strictMode, stringQuoteCharacter);
+ StringParseResult result = parseComplexEscape<shouldBuildStrings, LexerEscapeParseMode::String>(strictMode, stringQuoteCharacter);
if (result != StringParsedSuccessfully)
return result;
}
@@ -1372,8 +1424,9 @@
};
template <typename T>
-template <bool shouldBuildStrings> typename Lexer<T>::StringParseResult Lexer<T>::parseTemplateLiteral(JSTokenData* tokenData, RawStringsBuildMode rawStringsBuildMode)
+typename Lexer<T>::StringParseResult Lexer<T>::parseTemplateLiteral(JSTokenData* tokenData, RawStringsBuildMode rawStringsBuildMode)
{
+ bool parseCookedFailed = false;
const T* stringStart = currentSourcePtr();
const T* rawStringStart = currentSourcePtr();
@@ -1382,7 +1435,7 @@
while (m_current != '`') {
if (UNLIKELY(m_current == '\\')) {
lineNumberAdder.clear();
- if (stringStart != currentSourcePtr() && shouldBuildStrings)
+ if (stringStart != currentSourcePtr())
append16(stringStart, currentSourcePtr() - stringStart);
shift();
@@ -1390,19 +1443,16 @@
// Most common escape sequences first.
if (escape) {
- if (shouldBuildStrings)
- record16(escape);
+ record16(escape);
shift();
} else if (UNLIKELY(isLineTerminator(m_current))) {
// Normalize <CR>, <CR><LF> to <LF>.
if (m_current == '\r') {
- if (shouldBuildStrings) {
- ASSERT_WITH_MESSAGE(rawStringStart != currentSourcePtr(), "We should have at least shifted the escape.");
+ ASSERT_WITH_MESSAGE(rawStringStart != currentSourcePtr(), "We should have at least shifted the escape.");
- if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) {
- m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart);
- m_bufferForRawTemplateString16.append('\n');
- }
+ if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings) {
+ m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart);
+ m_bufferForRawTemplateString16.append('\n');
}
lineNumberAdder.add(m_current);
@@ -1419,9 +1469,13 @@
}
} else {
bool strictMode = true;
- StringParseResult result = parseComplexEscape<shouldBuildStrings>(EscapeParseMode::Template, strictMode, '`');
- if (result != StringParsedSuccessfully)
- return result;
+ StringParseResult result = parseComplexEscape<true, LexerEscapeParseMode::Template>(strictMode, '`');
+ if (result != StringParsedSuccessfully) {
+ if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings && result == StringCannotBeParsed)
+ parseCookedFailed = true;
+ else
+ return result;
+ }
}
stringStart = currentSourcePtr();
@@ -1445,16 +1499,14 @@
if (isLineTerminator(m_current)) {
if (m_current == '\r') {
// Normalize <CR>, <CR><LF> to <LF>.
- if (shouldBuildStrings) {
- if (stringStart != currentSourcePtr())
- append16(stringStart, currentSourcePtr() - stringStart);
- if (rawStringStart != currentSourcePtr() && rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings)
- m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart);
+ if (stringStart != currentSourcePtr())
+ append16(stringStart, currentSourcePtr() - stringStart);
+ if (rawStringStart != currentSourcePtr() && rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings)
+ m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart);
- record16('\n');
- if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings)
- m_bufferForRawTemplateString16.append('\n');
- }
+ record16('\n');
+ if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings)
+ m_bufferForRawTemplateString16.append('\n');
lineNumberAdder.add(m_current);
shift();
if (m_current == '\n') {
@@ -1478,24 +1530,22 @@
bool isTail = m_current == '`';
- if (shouldBuildStrings) {
- if (currentSourcePtr() != stringStart)
- append16(stringStart, currentSourcePtr() - stringStart);
- if (rawStringStart != currentSourcePtr() && rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings)
- m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart);
- }
+ if (currentSourcePtr() != stringStart)
+ append16(stringStart, currentSourcePtr() - stringStart);
+ if (rawStringStart != currentSourcePtr() && rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings)
+ m_bufferForRawTemplateString16.append(rawStringStart, currentSourcePtr() - rawStringStart);
- if (shouldBuildStrings) {
+ if (!parseCookedFailed)
tokenData->cooked = makeIdentifier(m_buffer16.data(), m_buffer16.size());
- // Line terminator normalization (e.g. <CR> => <LF>) should be applied to both the raw and cooked representations.
- if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings)
- tokenData->raw = makeIdentifier(m_bufferForRawTemplateString16.data(), m_bufferForRawTemplateString16.size());
- else
- tokenData->raw = makeEmptyIdentifier();
- } else {
- tokenData->cooked = makeEmptyIdentifier();
- tokenData->raw = makeEmptyIdentifier();
- }
+ else
+ tokenData->cooked = nullptr;
+
+ // Line terminator normalization (e.g. <CR> => <LF>) should be applied to both the raw and cooked representations.
+ if (rawStringsBuildMode == RawStringsBuildMode::BuildRawStrings)
+ tokenData->raw = makeIdentifier(m_bufferForRawTemplateString16.data(), m_bufferForRawTemplateString16.size());
+ else
+ tokenData->raw = nullptr;
+
tokenData->isTail = isTail;
m_buffer16.shrink(0);
@@ -2082,6 +2132,10 @@
shift();
token = SEMICOLON;
break;
+ case CharacterBackQuote:
+ shift();
+ token = BACKQUOTE;
+ break;
case CharacterOpenBrace:
tokenData->line = lineNumber();
tokenData->offset = currentOffset();
@@ -2234,22 +2288,6 @@
token = STRING;
break;
}
- case CharacterBackQuote: {
- // Skip backquote.
- shift();
- StringParseResult result = StringCannotBeParsed;
- if (lexerFlags & LexerFlagsDontBuildStrings)
- result = parseTemplateLiteral<false>(tokenData, RawStringsBuildMode::BuildRawStrings);
- else
- result = parseTemplateLiteral<true>(tokenData, RawStringsBuildMode::BuildRawStrings);
-
- if (UNLIKELY(result != StringParsedSuccessfully)) {
- token = result == StringUnterminated ? UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK : INVALID_TEMPLATE_LITERAL_ERRORTOK;
- goto returnError;
- }
- token = TEMPLATE;
- break;
- }
case CharacterIdentifierStart:
ASSERT(isIdentStart(m_current));
FALLTHROUGH;
@@ -2420,15 +2458,15 @@
}
template <typename T>
-JSTokenType Lexer<T>::scanTrailingTemplateString(JSToken* tokenRecord, RawStringsBuildMode rawStringsBuildMode)
+JSTokenType Lexer<T>::scanTemplateString(JSToken* tokenRecord, RawStringsBuildMode rawStringsBuildMode)
{
JSTokenData* tokenData = &tokenRecord->m_data;
ASSERT(!m_error);
ASSERT(m_buffer16.isEmpty());
- // Leading closing brace } is already shifted in the previous token scan.
+ // Leading backquote ` (for template head) or closing brace } (for template trailing) are already shifted in the previous token scan.
// So in this re-scan phase, shift() is not needed here.
- StringParseResult result = parseTemplateLiteral<true>(tokenData, rawStringsBuildMode);
+ StringParseResult result = parseTemplateLiteral(tokenData, rawStringsBuildMode);
JSTokenType token = ERRORTOK;
if (UNLIKELY(result != StringParsedSuccessfully)) {
token = result == StringUnterminated ? UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK : INVALID_TEMPLATE_LITERAL_ERRORTOK;
Modified: trunk/Source/_javascript_Core/parser/Lexer.h (211318 => 211319)
--- trunk/Source/_javascript_Core/parser/Lexer.h 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/parser/Lexer.h 2017-01-28 03:09:12 UTC (rev 211319)
@@ -37,6 +37,8 @@
LexexFlagsDontBuildKeywords = 4
};
+enum class LexerEscapeParseMode { Template, String };
+
struct ParsedUnicodeEscapeValue;
bool isLexerKeyword(const Identifier&);
@@ -77,7 +79,7 @@
bool prevTerminator() const { return m_terminator; }
JSTokenType scanRegExp(JSToken*, UChar patternPrefix = 0);
enum class RawStringsBuildMode { BuildRawStrings, DontBuildRawStrings };
- JSTokenType scanTrailingTemplateString(JSToken*, RawStringsBuildMode);
+ JSTokenType scanTemplateString(JSToken*, RawStringsBuildMode);
// Functions for use after parsing.
bool sawError() const { return m_error; }
@@ -170,9 +172,8 @@
template <bool shouldBuildStrings> ALWAYS_INLINE StringParseResult parseString(JSTokenData*, bool strictMode);
template <bool shouldBuildStrings> NEVER_INLINE StringParseResult parseStringSlowCase(JSTokenData*, bool strictMode);
- enum class EscapeParseMode { Template, String };
- template <bool shouldBuildStrings> ALWAYS_INLINE StringParseResult parseComplexEscape(EscapeParseMode, bool strictMode, T stringQuoteCharacter);
- template <bool shouldBuildStrings> ALWAYS_INLINE StringParseResult parseTemplateLiteral(JSTokenData*, RawStringsBuildMode);
+ template <bool shouldBuildStrings, LexerEscapeParseMode escapeParseMode> ALWAYS_INLINE StringParseResult parseComplexEscape(bool strictMode, T stringQuoteCharacter);
+ ALWAYS_INLINE StringParseResult parseTemplateLiteral(JSTokenData*, RawStringsBuildMode);
ALWAYS_INLINE void parseHex(double& returnValue);
ALWAYS_INLINE bool parseBinary(double& returnValue);
ALWAYS_INLINE bool parseOctal(double& returnValue);
Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (211318 => 211319)
--- trunk/Source/_javascript_Core/parser/NodeConstructors.h 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h 2017-01-28 03:09:12 UTC (rev 211319)
@@ -111,7 +111,7 @@
previous->m_next = this;
}
- inline TemplateStringNode::TemplateStringNode(const JSTokenLocation& location, const Identifier& cooked, const Identifier& raw)
+ inline TemplateStringNode::TemplateStringNode(const JSTokenLocation& location, const Identifier* cooked, const Identifier* raw)
: ExpressionNode(location)
, m_cooked(cooked)
, m_raw(raw)
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (211318 => 211319)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2017-01-28 03:09:12 UTC (rev 211319)
@@ -490,16 +490,16 @@
class TemplateStringNode : public ExpressionNode {
public:
- TemplateStringNode(const JSTokenLocation&, const Identifier& cooked, const Identifier& raw);
+ TemplateStringNode(const JSTokenLocation&, const Identifier* cooked, const Identifier* raw);
- const Identifier& cooked() { return m_cooked; }
- const Identifier& raw() { return m_raw; }
+ const Identifier* cooked() { return m_cooked; }
+ const Identifier* raw() { return m_raw; }
private:
RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
- const Identifier& m_cooked;
- const Identifier& m_raw;
+ const Identifier* m_cooked;
+ const Identifier* m_raw;
};
class TemplateStringListNode : public ParserArenaFreeable {
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (211318 => 211319)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2017-01-28 03:09:12 UTC (rev 211319)
@@ -904,7 +904,7 @@
if (match(OPENBRACE) || match(OPENBRACKET)) {
SavePoint savePoint = createSavePoint();
assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
- if (assignmentTarget && !match(DOT) && !match(OPENBRACKET) && !match(OPENPAREN) && !match(TEMPLATE))
+ if (assignmentTarget && !match(DOT) && !match(OPENBRACKET) && !match(OPENPAREN) && !match(BACKQUOTE))
return assignmentTarget;
restoreSavePoint(savePoint);
}
@@ -4089,11 +4089,13 @@
template <typename LexerType>
template <class TreeBuilder> typename TreeBuilder::TemplateString Parser<LexerType>::parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode rawStringsBuildMode, bool& elementIsTail)
{
- if (!isTemplateHead) {
+ if (isTemplateHead)
+ ASSERT(match(BACKQUOTE));
+ else
matchOrFail(CLOSEBRACE, "Expected a closing '}' following an _expression_ in template literal");
- // Re-scan the token to recognize it as Template Element.
- m_token.m_type = m_lexer->scanTrailingTemplateString(&m_token, rawStringsBuildMode);
- }
+
+ // Re-scan the token to recognize it as Template Element.
+ m_token.m_type = m_lexer->scanTemplateString(&m_token, rawStringsBuildMode);
matchOrFail(TEMPLATE, "Expected an template element");
const Identifier* cooked = m_token.m_data.cooked;
const Identifier* raw = m_token.m_data.raw;
@@ -4100,12 +4102,13 @@
elementIsTail = m_token.m_data.isTail;
JSTokenLocation location(tokenLocation());
next();
- return context.createTemplateString(location, *cooked, *raw);
+ return context.createTemplateString(location, cooked, raw);
}
template <typename LexerType>
template <class TreeBuilder> typename TreeBuilder::TemplateLiteral Parser<LexerType>::parseTemplateLiteral(TreeBuilder& context, typename LexerType::RawStringsBuildMode rawStringsBuildMode)
{
+ ASSERT(match(BACKQUOTE));
JSTokenLocation location(tokenLocation());
bool elementIsTail = false;
@@ -4268,7 +4271,7 @@
}
return re;
}
- case TEMPLATE:
+ case BACKQUOTE:
return parseTemplateLiteral(context, LexerType::RawStringsBuildMode::DontBuildRawStrings);
case YIELD:
if (!strictMode() && !currentScope()->isGenerator())
@@ -4505,7 +4508,7 @@
next();
break;
}
- case TEMPLATE: {
+ case BACKQUOTE: {
semanticFailIfTrue(baseIsSuper, "Cannot use super as tag for tagged templates");
JSTextPosition expressionEnd = lastTokenEndPosition();
int nonLHSCount = m_parserState.nonLHSCount;
Modified: trunk/Source/_javascript_Core/parser/ParserTokens.h (211318 => 211319)
--- trunk/Source/_javascript_Core/parser/ParserTokens.h 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/parser/ParserTokens.h 2017-01-28 03:09:12 UTC (rev 211319)
@@ -109,6 +109,7 @@
CLOSEBRACKET,
COMMA,
QUESTION,
+ BACKQUOTE,
INTEGER,
DOUBLE,
IDENT,
Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (211318 => 211319)
--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2017-01-28 03:09:12 UTC (rev 211319)
@@ -194,7 +194,7 @@
int createArguments() { return ArgumentsResult; }
int createArguments(int) { return ArgumentsResult; }
ExpressionType createSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return SpreadExpr; }
- TemplateString createTemplateString(const JSTokenLocation&, const Identifier&, const Identifier&) { return TemplateStringResult; }
+ TemplateString createTemplateString(const JSTokenLocation&, const Identifier*, const Identifier*) { return TemplateStringResult; }
TemplateStringList createTemplateStringList(TemplateString) { return TemplateStringListResult; }
TemplateStringList createTemplateStringList(TemplateStringList, TemplateString) { return TemplateStringListResult; }
TemplateExpressionList createTemplateExpressionList(_expression_) { return TemplateExpressionListResult; }
Modified: trunk/Source/_javascript_Core/runtime/TemplateRegistry.cpp (211318 => 211319)
--- trunk/Source/_javascript_Core/runtime/TemplateRegistry.cpp 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistry.cpp 2017-01-28 03:09:12 UTC (rev 211319)
@@ -58,8 +58,13 @@
RETURN_IF_EXCEPTION(scope, nullptr);
for (unsigned index = 0; index < count; ++index) {
- templateObject->putDirectIndex(exec, index, jsString(exec, templateKey.cookedStrings()[index]), ReadOnly | DontDelete, PutDirectIndexLikePutDirect);
+ auto cooked = templateKey.cookedStrings()[index];
+ if (cooked)
+ templateObject->putDirectIndex(exec, index, jsString(exec, cooked.value()), ReadOnly | DontDelete, PutDirectIndexLikePutDirect);
+ else
+ templateObject->putDirectIndex(exec, index, jsUndefined(), ReadOnly | DontDelete, PutDirectIndexLikePutDirect);
RETURN_IF_EXCEPTION(scope, nullptr);
+
rawObject->putDirectIndex(exec, index, jsString(exec, templateKey.rawStrings()[index]), ReadOnly | DontDelete, PutDirectIndexLikePutDirect);
RETURN_IF_EXCEPTION(scope, nullptr);
}
Modified: trunk/Source/_javascript_Core/runtime/TemplateRegistryKey.h (211318 => 211319)
--- trunk/Source/_javascript_Core/runtime/TemplateRegistryKey.h 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistryKey.h 2017-01-28 03:09:12 UTC (rev 211319)
@@ -38,6 +38,7 @@
public:
friend class TemplateRegistryKeyTable;
typedef Vector<String, 4> StringVector;
+ typedef Vector<std::optional<String>, 4> OptionalStringVector;
enum DeletedValueTag { DeletedValue };
TemplateRegistryKey(DeletedValueTag);
@@ -51,7 +52,7 @@
unsigned hash() const { return m_hash; }
const StringVector& rawStrings() const { return m_rawStrings; }
- const StringVector& cookedStrings() const { return m_cookedStrings; }
+ const OptionalStringVector& cookedStrings() const { return m_cookedStrings; }
bool operator==(const TemplateRegistryKey& other) const { return m_hash == other.m_hash && m_rawStrings == other.m_rawStrings; }
bool operator!=(const TemplateRegistryKey& other) const { return m_hash != other.m_hash || m_rawStrings != other.m_rawStrings; }
@@ -66,22 +67,22 @@
~TemplateRegistryKey();
private:
- static Ref<TemplateRegistryKey> create(const StringVector& rawStrings, const StringVector& cookedStrings)
+ static Ref<TemplateRegistryKey> create(StringVector&& rawStrings, OptionalStringVector&& cookedStrings)
{
- return adoptRef(*new TemplateRegistryKey(rawStrings, cookedStrings));
+ return adoptRef(*new TemplateRegistryKey(WTFMove(rawStrings), WTFMove(cookedStrings)));
}
- TemplateRegistryKey(const StringVector& rawStrings, const StringVector& cookedStrings);
+ TemplateRegistryKey(StringVector&& rawStrings, OptionalStringVector&& cookedStrings);
TemplateRegistryKeyTable* m_table { nullptr };
StringVector m_rawStrings;
- StringVector m_cookedStrings;
+ OptionalStringVector m_cookedStrings;
unsigned m_hash { 0 };
};
-inline TemplateRegistryKey::TemplateRegistryKey(const StringVector& rawStrings, const StringVector& cookedStrings)
- : m_rawStrings(rawStrings)
- , m_cookedStrings(cookedStrings)
+inline TemplateRegistryKey::TemplateRegistryKey(StringVector&& rawStrings, OptionalStringVector&& cookedStrings)
+ : m_rawStrings(WTFMove(rawStrings))
+ , m_cookedStrings(WTFMove(cookedStrings))
, m_hash(calculateHash(rawStrings))
{
}
Modified: trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.cpp (211318 => 211319)
--- trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.cpp 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.cpp 2017-01-28 03:09:12 UTC (rev 211319)
@@ -42,9 +42,9 @@
key->m_table = nullptr;
}
-Ref<TemplateRegistryKey> TemplateRegistryKeyTable::createKey(const TemplateRegistryKey::StringVector& rawStrings, const TemplateRegistryKey::StringVector& cookedStrings)
+Ref<TemplateRegistryKey> TemplateRegistryKeyTable::createKey(TemplateRegistryKey::StringVector&& rawStrings, TemplateRegistryKey::OptionalStringVector&& cookedStrings)
{
- auto key = TemplateRegistryKey::create(rawStrings, cookedStrings);
+ auto key = TemplateRegistryKey::create(WTFMove(rawStrings), WTFMove(cookedStrings));
auto addResult = m_atomicTable.add<TemplateRegistryKeyTranslator>(key.ptr());
if (addResult.isNewEntry)
(*addResult.iterator)->m_table = this;
Modified: trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.h (211318 => 211319)
--- trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.h 2017-01-28 02:27:56 UTC (rev 211318)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.h 2017-01-28 03:09:12 UTC (rev 211319)
@@ -36,10 +36,11 @@
WTF_MAKE_NONCOPYABLE(TemplateRegistryKeyTable);
public:
using StringVector = Vector<String, 4>;
+ using OptionalStringVector = Vector<std::optional<String>, 4>;
TemplateRegistryKeyTable() = default;
- Ref<TemplateRegistryKey> createKey(const StringVector& rawStrings, const StringVector& cookedStrings);
+ Ref<TemplateRegistryKey> createKey(StringVector&& rawStrings, OptionalStringVector&& cookedStrings);
void unregister(TemplateRegistryKey&);