[ES6] Implement ES6 template literals
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Apr 2015 00:27:28 +0000 (00:27 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Apr 2015 00:27:28 +0000 (00:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=142691

Reviewed by Darin Adler.

.:

Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.

* Source/cmake/WebKitFeatures.cmake:
* Source/cmakeconfig.h.cmake:

Source/JavaScriptCore:

This patch implements TemplateLiteral.
Since TaggedTemplate requires some global states and
primitive operations like GetTemplateObject,
we separate the patch. It will be implemented in a subsequent patch.

Template Literal Syntax is guarded by ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.
By disabling it, we can disable Template Literal support.

To implement template literals, in this patch,
we newly introduces bytecode op_to_string.
In template literals, we alternately evaluate the expression and
perform ToString onto the result of evaluation.
For example,

`${f1()} ${f2()}`

In this template literal, execution order is the following,
1. calling f1()
2. ToString(the result of f1())
3. calling f2()
4. ToString(the result of f2())

op_strcat also performs ToString. However, performing ToString
onto expressions are batched in op_strcat, it's not the same to the
template literal spec. In the above example,
ToString(f1()) should be called before calling f2().

* Configurations/FeatureDefines.xcconfig:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitToString):
(JSC::BytecodeGenerator::emitToNumber): Deleted.
* bytecompiler/NodesCodegen.cpp:
(JSC::TemplateStringNode::emitBytecode):
(JSC::TemplateLiteralNode::emitBytecode):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_to_string):
(JSC::JIT::emitSlow_op_to_string):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_to_string):
(JSC::JIT::emitSlow_op_to_string):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createTemplateString):
(JSC::ASTBuilder::createTemplateStringList):
(JSC::ASTBuilder::createTemplateExpressionList):
(JSC::ASTBuilder::createTemplateLiteral):
* parser/Lexer.cpp:
(JSC::Lexer<T>::Lexer):
(JSC::Lexer<T>::parseIdentifierSlowCase):
(JSC::Lexer<T>::parseString):
(JSC::LineNumberAdder::LineNumberAdder):
(JSC::LineNumberAdder::clear):
(JSC::LineNumberAdder::add):
(JSC::Lexer<T>::parseTemplateLiteral):
(JSC::Lexer<T>::lex):
(JSC::Lexer<T>::scanRegExp):
(JSC::Lexer<T>::scanTrailingTemplateString):
(JSC::Lexer<T>::parseStringSlowCase): Deleted.
* parser/Lexer.h:
* parser/NodeConstructors.h:
(JSC::TemplateExpressionListNode::TemplateExpressionListNode):
(JSC::TemplateStringNode::TemplateStringNode):
(JSC::TemplateStringListNode::TemplateStringListNode):
(JSC::TemplateLiteralNode::TemplateLiteralNode):
* parser/Nodes.h:
(JSC::TemplateExpressionListNode::value):
(JSC::TemplateExpressionListNode::next):
(JSC::TemplateStringNode::cooked):
(JSC::TemplateStringNode::raw):
(JSC::TemplateStringListNode::value):
(JSC::TemplateStringListNode::next):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseTemplateString):
(JSC::Parser<LexerType>::parseTemplateLiteral):
(JSC::Parser<LexerType>::parsePrimaryExpression):
* parser/Parser.h:
* parser/ParserTokens.h:
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createTemplateString):
(JSC::SyntaxChecker::createTemplateStringList):
(JSC::SyntaxChecker::createTemplateExpressionList):
(JSC::SyntaxChecker::createTemplateLiteral):
(JSC::SyntaxChecker::createSpreadExpression): Deleted.
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
* tests/stress/template-literal-line-terminators.js: Added.
(test):
(testEval):
(testEvalLineNumber):
* tests/stress/template-literal-syntax.js: Added.
(testSyntax):
(testSyntaxError):
* tests/stress/template-literal.js: Added.
(test):
(testEval):
(testEmbedded):

Source/WebCore:

Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.

* Configurations/FeatureDefines.xcconfig:

Source/WebKit/mac:

Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.

* Configurations/FeatureDefines.xcconfig:

Source/WebKit2:

Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.

* Configurations/FeatureDefines.xcconfig:

Tools:

Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.

* Scripts/webkitperl/FeatureList.pm:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@183373 268f45cc-cd09-0410-ab3c-d52691b4dbfc

40 files changed:
ChangeLog
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
Source/JavaScriptCore/bytecode/BytecodeList.json
Source/JavaScriptCore/bytecode/BytecodeUseDef.h
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.cpp
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/Lexer.cpp
Source/JavaScriptCore/parser/Lexer.h
Source/JavaScriptCore/parser/NodeConstructors.h
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/ParserTokens.h
Source/JavaScriptCore/parser/SyntaxChecker.h
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.h
Source/JavaScriptCore/tests/stress/template-literal-line-terminators.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/template-literal-syntax.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/template-literal.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Configurations/FeatureDefines.xcconfig
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/Configurations/FeatureDefines.xcconfig
Source/WebKit2/ChangeLog
Source/WebKit2/Configurations/FeatureDefines.xcconfig
Source/cmake/WebKitFeatures.cmake
Source/cmakeconfig.h.cmake
Tools/ChangeLog
Tools/Scripts/webkitperl/FeatureList.pm

index 7d82c0a..179a6d2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2015-04-26  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement ES6 template literals
+        https://bugs.webkit.org/show_bug.cgi?id=142691
+
+        Reviewed by Darin Adler.
+
+        Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.
+
+        * Source/cmake/WebKitFeatures.cmake:
+        * Source/cmakeconfig.h.cmake:
+
 2015-04-25  Martin Robinson  <mrobinson@igalia.com>
 
         Rename ENABLE_3D_RENDERING to ENABLE_3D_TRANSFORMS
index 5e1fd4f..8b051da 100644 (file)
@@ -1,3 +1,123 @@
+2015-04-26  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement ES6 template literals
+        https://bugs.webkit.org/show_bug.cgi?id=142691
+
+        Reviewed by Darin Adler.
+
+        This patch implements TemplateLiteral.
+        Since TaggedTemplate requires some global states and
+        primitive operations like GetTemplateObject,
+        we separate the patch. It will be implemented in a subsequent patch.
+
+        Template Literal Syntax is guarded by ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.
+        By disabling it, we can disable Template Literal support.
+
+        To implement template literals, in this patch,
+        we newly introduces bytecode op_to_string.
+        In template literals, we alternately evaluate the expression and
+        perform ToString onto the result of evaluation.
+        For example,
+
+        `${f1()} ${f2()}`
+
+        In this template literal, execution order is the following,
+        1. calling f1()
+        2. ToString(the result of f1())
+        3. calling f2()
+        4. ToString(the result of f2())
+
+        op_strcat also performs ToString. However, performing ToString
+        onto expressions are batched in op_strcat, it's not the same to the
+        template literal spec. In the above example,
+        ToString(f1()) should be called before calling f2().
+
+        * Configurations/FeatureDefines.xcconfig:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitToString):
+        (JSC::BytecodeGenerator::emitToNumber): Deleted.
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::TemplateStringNode::emitBytecode):
+        (JSC::TemplateLiteralNode::emitBytecode):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_to_string):
+        (JSC::JIT::emitSlow_op_to_string):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_to_string):
+        (JSC::JIT::emitSlow_op_to_string):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createTemplateString):
+        (JSC::ASTBuilder::createTemplateStringList):
+        (JSC::ASTBuilder::createTemplateExpressionList):
+        (JSC::ASTBuilder::createTemplateLiteral):
+        * parser/Lexer.cpp:
+        (JSC::Lexer<T>::Lexer):
+        (JSC::Lexer<T>::parseIdentifierSlowCase):
+        (JSC::Lexer<T>::parseString):
+        (JSC::LineNumberAdder::LineNumberAdder):
+        (JSC::LineNumberAdder::clear):
+        (JSC::LineNumberAdder::add):
+        (JSC::Lexer<T>::parseTemplateLiteral):
+        (JSC::Lexer<T>::lex):
+        (JSC::Lexer<T>::scanRegExp):
+        (JSC::Lexer<T>::scanTrailingTemplateString):
+        (JSC::Lexer<T>::parseStringSlowCase): Deleted.
+        * parser/Lexer.h:
+        * parser/NodeConstructors.h:
+        (JSC::TemplateExpressionListNode::TemplateExpressionListNode):
+        (JSC::TemplateStringNode::TemplateStringNode):
+        (JSC::TemplateStringListNode::TemplateStringListNode):
+        (JSC::TemplateLiteralNode::TemplateLiteralNode):
+        * parser/Nodes.h:
+        (JSC::TemplateExpressionListNode::value):
+        (JSC::TemplateExpressionListNode::next):
+        (JSC::TemplateStringNode::cooked):
+        (JSC::TemplateStringNode::raw):
+        (JSC::TemplateStringListNode::value):
+        (JSC::TemplateStringListNode::next):
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseTemplateString):
+        (JSC::Parser<LexerType>::parseTemplateLiteral):
+        (JSC::Parser<LexerType>::parsePrimaryExpression):
+        * parser/Parser.h:
+        * parser/ParserTokens.h:
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createTemplateString):
+        (JSC::SyntaxChecker::createTemplateStringList):
+        (JSC::SyntaxChecker::createTemplateExpressionList):
+        (JSC::SyntaxChecker::createTemplateLiteral):
+        (JSC::SyntaxChecker::createSpreadExpression): Deleted.
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+        * tests/stress/template-literal-line-terminators.js: Added.
+        (test):
+        (testEval):
+        (testEvalLineNumber):
+        * tests/stress/template-literal-syntax.js: Added.
+        (testSyntax):
+        (testSyntaxError):
+        * tests/stress/template-literal.js: Added.
+        (test):
+        (testEval):
+        (testEmbedded):
+
 2015-04-26  Jordan Harband  <ljharb@gmail.com>
 
         Set#forEach does not pass "key" or "set" arguments to callback.
index efc3205..f5b45d9 100644 (file)
@@ -45,6 +45,7 @@ ENABLE_CANVAS_PATH = ENABLE_CANVAS_PATH;
 ENABLE_CANVAS_PROXY = ;
 ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING;
 ENABLE_ES6_CLASS_SYNTAX = ENABLE_ES6_CLASS_SYNTAX;
+ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX = ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX;
 ENABLE_CONTENT_FILTERING = ENABLE_CONTENT_FILTERING;
 ENABLE_CSP_NEXT = ;
 ENABLE_CSS_ANIMATIONS_LEVEL_2 = ENABLE_CSS_ANIMATIONS_LEVEL_2;
@@ -214,4 +215,4 @@ ENABLE_LLINT_C_LOOP = ;
 
 ENABLE_SATURATED_LAYOUT_ARITHMETIC = ENABLE_SATURATED_LAYOUT_ARITHMETIC;
 
-FEATURE_DEFINES = $(ENABLE_3D_TRANSFORMS) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) $(ENABLE_AVF_CAPTIONS) $(ENABLE_ATTACHMENT_ELEMENT) $(ENABLE_CACHE_PARTITIONING) $(ENABLE_CANVAS_PATH) $(ENABLE_CANVAS_PROXY) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_ES6_CLASS_SYNTAX) $(ENABLE_CONTENT_FILTERING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_ANIMATIONS_LEVEL_2) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_DEVICE_ADAPTATION) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SELECTORS_LEVEL4) $(ENABLE_CSS_SHAPES) $(ENABLE_CSS3_TEXT) $(ENABLE_CSS3_TEXT_LINE_BREAK) $(ENABLE_CURSOR_VISIBILITY) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM4_EVENTS_CONSTRUCTOR) $(ENABLE_ENCRYPTED_MEDIA) $(ENABLE_ENCRYPTED_MEDIA_V2) $(ENABLE_FILTERS_LEVEL_2) $(ENABLE_FONT_LOAD_EVENTS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GAMEPAD_DEPRECATED) $(ENABLE_GEOLOCATION) $(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) $(ENABLE_ICONDATABASE) $(ENABLE_SERVICE_CONTROLS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INDEXED_DATABASE_IN_WORKERS) $(ENABLE_INDIE_UI) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_COLOR_POPOVER) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_WIRELESS_PLAYBACK_TARGET) $(ENABLE_IOS_GESTURE_EVENTS) $(ENABLE_IOS_TEXT_AUTOSIZING) $(ENABLE_IOS_TOUCH_EVENTS) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LEGACY_VENDOR_PREFIXES) $(ENABLE_LEGACY_WEB_AUDIO) $(ENABLE_LETTERPRESS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_CONTROLS_SCRIPT) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MOUSE_CURSOR_SCALE) $(ENABLE_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NAVIGATOR_HWCONCURRENCY) $(ENABLE_NOTIFICATIONS) $(ENABLE_PDFKIT_PLUGIN) $(ENABLE_POINTER_LOCK) $(ENABLE_PROMISES) $(ENABLE_PROXIMITY_EVENTS) $(ENABLE_PUBLIC_SUFFIX_LIST) $(ENABLE_QUOTA) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_REQUEST_AUTOCOMPLETE) $(ENABLE_REMOTE_INSPECTOR) $(ENABLE_RESOLUTION_MEDIA_QUERY) $(ENABLE_RUBBER_BANDING) $(ENABLE_CSS_SCROLL_SNAP) $(ENABLE_SPEECH_SYNTHESIS) $(ENABLE_STREAMS_API) $(ENABLE_SUBTLE_CRYPTO) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_OTF_CONVERTER) $(ENABLE_TELEPHONE_NUMBER_DETECTION) $(ENABLE_TEMPLATE_ELEMENT) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TOUCH_EVENTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_CSS_TRAILING_WORD) $(ENABLE_USERSELECT_ALL) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_DATACUE_VALUE) $(ENABLE_VIEW_MODE_CSS_MEDIA) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_REPLAY) $(ENABLE_WEB_SOCKETS) $(ENABLE_PICTURE_SIZES) $(ENABLE_WEB_TIMING) $(ENABLE_WEBVTT_REGIONS) $(ENABLE_XHR_TIMEOUT) $(ENABLE_XSLT) $(ENABLE_FTL_JIT) $(ENABLE_LLINT_C_LOOP) $(ENABLE_SATURATED_LAYOUT_ARITHMETIC) $(ENABLE_VIDEO_PRESENTATION_MODE);
+FEATURE_DEFINES = $(ENABLE_3D_TRANSFORMS) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) $(ENABLE_AVF_CAPTIONS) $(ENABLE_ATTACHMENT_ELEMENT) $(ENABLE_CACHE_PARTITIONING) $(ENABLE_CANVAS_PATH) $(ENABLE_CANVAS_PROXY) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_ES6_CLASS_SYNTAX) $(ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX) $(ENABLE_CONTENT_FILTERING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_ANIMATIONS_LEVEL_2) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_DEVICE_ADAPTATION) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SELECTORS_LEVEL4) $(ENABLE_CSS_SHAPES) $(ENABLE_CSS3_TEXT) $(ENABLE_CSS3_TEXT_LINE_BREAK) $(ENABLE_CURSOR_VISIBILITY) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM4_EVENTS_CONSTRUCTOR) $(ENABLE_ENCRYPTED_MEDIA) $(ENABLE_ENCRYPTED_MEDIA_V2) $(ENABLE_FILTERS_LEVEL_2) $(ENABLE_FONT_LOAD_EVENTS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GAMEPAD_DEPRECATED) $(ENABLE_GEOLOCATION) $(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) $(ENABLE_ICONDATABASE) $(ENABLE_SERVICE_CONTROLS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INDEXED_DATABASE_IN_WORKERS) $(ENABLE_INDIE_UI) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_COLOR_POPOVER) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_WIRELESS_PLAYBACK_TARGET) $(ENABLE_IOS_GESTURE_EVENTS) $(ENABLE_IOS_TEXT_AUTOSIZING) $(ENABLE_IOS_TOUCH_EVENTS) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LEGACY_VENDOR_PREFIXES) $(ENABLE_LEGACY_WEB_AUDIO) $(ENABLE_LETTERPRESS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_CONTROLS_SCRIPT) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MOUSE_CURSOR_SCALE) $(ENABLE_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NAVIGATOR_HWCONCURRENCY) $(ENABLE_NOTIFICATIONS) $(ENABLE_PDFKIT_PLUGIN) $(ENABLE_POINTER_LOCK) $(ENABLE_PROMISES) $(ENABLE_PROXIMITY_EVENTS) $(ENABLE_PUBLIC_SUFFIX_LIST) $(ENABLE_QUOTA) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_REQUEST_AUTOCOMPLETE) $(ENABLE_REMOTE_INSPECTOR) $(ENABLE_RESOLUTION_MEDIA_QUERY) $(ENABLE_RUBBER_BANDING) $(ENABLE_CSS_SCROLL_SNAP) $(ENABLE_SPEECH_SYNTHESIS) $(ENABLE_STREAMS_API) $(ENABLE_SUBTLE_CRYPTO) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_OTF_CONVERTER) $(ENABLE_TELEPHONE_NUMBER_DETECTION) $(ENABLE_TEMPLATE_ELEMENT) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TOUCH_EVENTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_CSS_TRAILING_WORD) $(ENABLE_USERSELECT_ALL) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_DATACUE_VALUE) $(ENABLE_VIEW_MODE_CSS_MEDIA) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_REPLAY) $(ENABLE_WEB_SOCKETS) $(ENABLE_PICTURE_SIZES) $(ENABLE_WEB_TIMING) $(ENABLE_WEBVTT_REGIONS) $(ENABLE_XHR_TIMEOUT) $(ENABLE_XSLT) $(ENABLE_FTL_JIT) $(ENABLE_LLINT_C_LOOP) $(ENABLE_SATURATED_LAYOUT_ARITHMETIC) $(ENABLE_VIDEO_PRESENTATION_MODE);
index 2514126..e3ed1dc 100644 (file)
@@ -32,6 +32,7 @@
             { "name" : "op_inc", "length" : 2 },
             { "name" : "op_dec", "length" : 2 },
             { "name" : "op_to_number", "length" : 3 },
+            { "name" : "op_to_string", "length" : 3 },
             { "name" : "op_negate", "length" : 3 },
             { "name" : "op_add", "length" : 5 },
             { "name" : "op_mul", "length" : 5 },
index f207139..7667e68 100644 (file)
@@ -135,6 +135,7 @@ void computeUsesForBytecodeOffset(
     case op_is_object_or_null:
     case op_is_function:
     case op_to_number:
+    case op_to_string:
     case op_negate:
     case op_neq_null:
     case op_eq_null:
@@ -328,6 +329,7 @@ void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset,
     case op_is_function:
     case op_in:
     case op_to_number:
+    case op_to_string:
     case op_negate:
     case op_add:
     case op_mul:
index 22f004e..90138f9 100644 (file)
@@ -939,6 +939,10 @@ void CodeBlock::dumpBytecode(
             printUnaryOp(out, exec, location, it, "to_number");
             break;
         }
+        case op_to_string: {
+            printUnaryOp(out, exec, location, it, "to_string");
+            break;
+        }
         case op_negate: {
             printUnaryOp(out, exec, location, it, "negate");
             break;
index 95002af..4bf9bc6 100644 (file)
@@ -463,6 +463,7 @@ namespace JSC {
         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
 
         RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_number, dst, src); }
+        RegisterID* emitToString(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_string, dst, src); }
         RegisterID* emitInc(RegisterID* srcDst);
         RegisterID* emitDec(RegisterID* srcDst);
 
index 64c3e9a..2b1d0aa 100644 (file)
@@ -215,6 +215,53 @@ RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
     return result;
 }
 
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+// ------------------------------ TemplateStringNode -----------------------------------
+
+RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult())
+        return nullptr;
+    return generator.emitLoad(dst, JSValue(generator.addStringConstant(cooked())));
+}
+
+// ------------------------------ TemplateLiteralNode -----------------------------------
+
+RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (!m_templateExpressions) {
+        TemplateStringNode* templateString = m_templateStrings->value();
+        ASSERT_WITH_MESSAGE(!m_templateStrings->next(), "Only one template element exists because there's no expression in a given template literal.");
+        return generator.emitNode(dst, templateString);
+    }
+
+    Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
+
+    TemplateStringListNode* templateString = m_templateStrings;
+    TemplateExpressionListNode* templateExpression = m_templateExpressions;
+    for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
+        // Evaluate TemplateString.
+        if (!templateString->value()->cooked().isEmpty()) {
+            temporaryRegisters.append(generator.newTemporary());
+            generator.emitNode(temporaryRegisters.last().get(), templateString->value());
+        }
+
+        // Evaluate Expression.
+        temporaryRegisters.append(generator.newTemporary());
+        generator.emitNode(temporaryRegisters.last().get(), templateExpression->value());
+        generator.emitToString(temporaryRegisters.last().get(), temporaryRegisters.last().get());
+    }
+
+    // Evaluate tail TemplateString.
+    if (!templateString->value()->cooked().isEmpty()) {
+        temporaryRegisters.append(generator.newTemporary());
+        generator.emitNode(temporaryRegisters.last().get(), templateString->value());
+    }
+
+    return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
+}
+#endif
+
 // ------------------------------ ArrayNode ------------------------------------
 
 RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
index 579b3ce..4c6bbdd 100644 (file)
@@ -3778,7 +3778,13 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             set(VirtualRegister(currentInstruction[1].u.operand), node);
             NEXT_OPCODE(op_to_number);
         }
-            
+
+        case op_to_string: {
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ToString, value));
+            NEXT_OPCODE(op_to_string);
+        }
+
         case op_in: {
             set(VirtualRegister(currentInstruction[1].u.operand),
                 addToGraph(In, get(VirtualRegister(currentInstruction[2].u.operand)), get(VirtualRegister(currentInstruction[3].u.operand))));
index 32220dd..ef4c247 100644 (file)
@@ -190,6 +190,7 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruc
     case op_jneq_ptr:
     case op_typeof:
     case op_to_number:
+    case op_to_string:
     case op_switch_imm:
     case op_switch_char:
     case op_in:
index 8cd9fb1..b4113c4 100644 (file)
@@ -300,6 +300,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_throw)
         DEFINE_OP(op_throw_static_error)
         DEFINE_OP(op_to_number)
+        DEFINE_OP(op_to_string)
         DEFINE_OP(op_to_primitive)
 
         DEFINE_OP(op_resolve_scope)
@@ -429,6 +430,7 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_stricteq)
         DEFINE_SLOWCASE_OP(op_sub)
         DEFINE_SLOWCASE_OP(op_to_number)
+        DEFINE_SLOWCASE_OP(op_to_string)
         DEFINE_SLOWCASE_OP(op_to_primitive)
         DEFINE_SLOWCASE_OP(op_has_indexed_property)
         DEFINE_SLOWCASE_OP(op_has_structure_property)
index 01a4129..d7225ea 100644 (file)
@@ -551,6 +551,7 @@ namespace JSC {
         void emit_op_throw(Instruction*);
         void emit_op_throw_static_error(Instruction*);
         void emit_op_to_number(Instruction*);
+        void emit_op_to_string(Instruction*);
         void emit_op_to_primitive(Instruction*);
         void emit_op_unexpected_load(Instruction*);
         void emit_op_unsigned(Instruction*);
@@ -613,6 +614,7 @@ namespace JSC {
         void emitSlow_op_stricteq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_number(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_to_string(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_unsigned(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
index 577e426..5d4d0b9 100644 (file)
@@ -488,6 +488,17 @@ void JIT::emit_op_to_number(Instruction* currentInstruction)
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
+void JIT::emit_op_to_string(Instruction* currentInstruction)
+{
+    int srcVReg = currentInstruction[2].u.operand;
+    emitGetVirtualRegister(srcVReg, regT0);
+
+    addSlowCase(emitJumpIfNotJSCell(regT0));
+    addSlowCase(branch8(NotEqual, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType)));
+
+    emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
 void JIT::emit_op_push_name_scope(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
@@ -881,6 +892,15 @@ void JIT::emitSlow_op_to_number(Instruction* currentInstruction, Vector<SlowCase
     slowPathCall.call();
 }
 
+void JIT::emitSlow_op_to_string(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter); // Not JSCell.
+    linkSlowCase(iter); // Not JSString.
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_string);
+    slowPathCall.call();
+}
+
 #endif // USE(JSVALUE64)
 
 void JIT::emit_op_loop_hint(Instruction*)
index 910c21c..acd460b 100644 (file)
@@ -782,6 +782,29 @@ void JIT::emitSlow_op_to_number(Instruction* currentInstruction, Vector<SlowCase
     slowPathCall.call();
 }
 
+void JIT::emit_op_to_string(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int src = currentInstruction[2].u.operand;
+
+    emitLoad(src, regT1, regT0);
+
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+    addSlowCase(branch8(NotEqual, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType)));
+
+    if (src != dst)
+        emitStore(dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_to_string(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter); // Not JSCell.
+    linkSlowCase(iter); // Not JSString.
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_string);
+    slowPathCall.call();
+}
+
 void JIT::emit_op_push_name_scope(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
index 3b47f0b..7ced21a 100644 (file)
@@ -994,6 +994,23 @@ _llint_op_to_number:
     dispatch(3)
 
 
+_llint_op_to_string:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    loadConstantOrVariable(t0, t2, t3)
+    bineq t2, CellTag, .opToStringSlow
+    bbneq JSCell::m_type[t3], StringType, .opToStringSlow
+.opToStringIsString:
+    storei t2, TagOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t1, 8]
+    dispatch(3)
+
+.opToStringSlow:
+    callSlowPath(_slow_path_to_string)
+    dispatch(3)
+
+
 _llint_op_negate:
     traceExecution()
     loadi 8[PC], t0
index 0d08438..68a9c62 100644 (file)
@@ -855,6 +855,22 @@ _llint_op_to_number:
     dispatch(3)
 
 
+_llint_op_to_string:
+    traceExecution()
+    loadisFromInstruction(2, t1)
+    loadisFromInstruction(1, t2)
+    loadConstantOrVariable(t1, t0)
+    btqnz t0, tagMask, .opToStringSlow
+    bbneq JSCell::m_type[t0], StringType, .opToStringSlow
+.opToStringIsString:
+    storeq t0, [cfr, t2, 8]
+    dispatch(3)
+
+.opToStringSlow:
+    callSlowPath(_slow_path_to_string)
+    dispatch(3)
+
+
 _llint_op_negate:
     traceExecution()
     loadisFromInstruction(2, t0)
index 06c19e2..aa73705 100644 (file)
@@ -103,6 +103,12 @@ public:
     typedef PropertyListNode* PropertyList;
     typedef ElementNode* ElementList;
     typedef ArgumentListNode* ArgumentsList;
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    typedef TemplateExpressionListNode* TemplateExpressionList;
+    typedef TemplateStringNode* TemplateString;
+    typedef TemplateStringListNode* TemplateStringList;
+    typedef TemplateLiteralNode* TemplateLiteral;
+#endif
     typedef ParameterNode* FormalParameterList;
     typedef FunctionBodyNode* FunctionBody;
 #if ENABLE(ES6_CLASS_SYNTAX)
@@ -247,6 +253,43 @@ public:
         return node;
     }
 
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    TemplateStringNode* createTemplateString(const JSTokenLocation& location, const Identifier& cooked, const Identifier& raw)
+    {
+        return new (m_parserArena) TemplateStringNode(location, cooked, raw);
+    }
+
+    TemplateStringListNode* createTemplateStringList(TemplateStringNode* templateString)
+    {
+        return new (m_parserArena) TemplateStringListNode(templateString);
+    }
+
+    TemplateStringListNode* createTemplateStringList(TemplateStringListNode* templateStringList, TemplateStringNode* templateString)
+    {
+        return new (m_parserArena) TemplateStringListNode(templateStringList, templateString);
+    }
+
+    TemplateExpressionListNode* createTemplateExpressionList(ExpressionNode* expression)
+    {
+        return new (m_parserArena) TemplateExpressionListNode(expression);
+    }
+
+    TemplateExpressionListNode* createTemplateExpressionList(TemplateExpressionListNode* templateExpressionListNode, ExpressionNode* expression)
+    {
+        return new (m_parserArena) TemplateExpressionListNode(templateExpressionListNode, expression);
+    }
+
+    TemplateLiteralNode* createTemplateLiteral(const JSTokenLocation& location, TemplateStringListNode* templateStringList)
+    {
+        return new (m_parserArena) TemplateLiteralNode(location, templateStringList);
+    }
+
+    TemplateLiteralNode* createTemplateLiteral(const JSTokenLocation& location, TemplateStringListNode* templateStringList, TemplateExpressionListNode* templateExpressionList)
+    {
+        return new (m_parserArena) TemplateLiteralNode(location, templateStringList, templateExpressionList);
+    }
+#endif
+
     ExpressionNode* createRegExp(const JSTokenLocation& location, const Identifier& pattern, const Identifier& flags, const JSTextPosition& start)
     {
         if (Yarr::checkSyntax(pattern.string()))
index 7de1422..5a0c308 100644 (file)
@@ -71,6 +71,7 @@ enum CharacterType {
     CharacterQuestion,
     CharacterTilde,
     CharacterQuote,
+    CharacterBackQuote,
     CharacterDot,
     CharacterSlash,
     CharacterBackSlash,
@@ -192,7 +193,11 @@ static const unsigned short typesOfLatin1Characters[256] = {
 /*  93 - ]                  */ CharacterCloseBracket,
 /*  94 - ^                  */ CharacterXor,
 /*  95 - _                  */ CharacterIdentifierStart,
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+/*  96 - `                  */ CharacterBackQuote,
+#else
 /*  96 - `                  */ CharacterInvalid,
+#endif
 /*  97 - a                  */ CharacterIdentifierStart,
 /*  98 - b                  */ CharacterIdentifierStart,
 /*  99 - c                  */ CharacterIdentifierStart,
@@ -1019,7 +1024,7 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow
         return IDENT;
     }
 
-    m_buffer16.resize(0);
+    m_buffer16.shrink(0);
     return IDENT;
 }
 
@@ -1052,7 +1057,7 @@ template <bool shouldBuildStrings> ALWAYS_INLINE typename Lexer<T>::StringParseR
 
             LChar escape = singleEscape(m_current);
 
-            // Most common escape sequences first
+            // Most common escape sequences first.
             if (escape) {
                 if (shouldBuildStrings)
                     record8(escape);
@@ -1073,7 +1078,7 @@ template <bool shouldBuildStrings> ALWAYS_INLINE typename Lexer<T>::StringParseR
             } else {
                 setOffset(startingOffset, startingLineStartOffset);
                 setLineNumber(startingLineNumber);
-                m_buffer8.resize(0);
+                m_buffer8.shrink(0);
                 return parseStringSlowCase<shouldBuildStrings>(tokenData, strictMode);
             }
             stringStart = currentSourcePtr();
@@ -1083,7 +1088,7 @@ template <bool shouldBuildStrings> ALWAYS_INLINE typename Lexer<T>::StringParseR
         if (UNLIKELY(characterRequiresParseStringSlowCase(m_current))) {
             setOffset(startingOffset, startingLineStartOffset);
             setLineNumber(startingLineNumber);
-            m_buffer8.resize(0);
+            m_buffer8.shrink(0);
             return parseStringSlowCase<shouldBuildStrings>(tokenData, strictMode);
         }
 
@@ -1094,7 +1099,7 @@ template <bool shouldBuildStrings> ALWAYS_INLINE typename Lexer<T>::StringParseR
         append8(stringStart, currentSourcePtr() - stringStart);
     if (shouldBuildStrings) {
         tokenData->ident = makeIdentifier(m_buffer8.data(), m_buffer8.size());
-        m_buffer8.resize(0);
+        m_buffer8.shrink(0);
     } else
         tokenData->ident = 0;
 
@@ -1102,7 +1107,92 @@ template <bool shouldBuildStrings> ALWAYS_INLINE typename Lexer<T>::StringParseR
 }
 
 template <typename T>
-template <bool shouldBuildStrings> typename Lexer<T>::StringParseResult Lexer<T>::parseStringSlowCase(JSTokenData* tokenData, bool strictMode)
+template <bool shouldBuildStrings> ALWAYS_INLINE auto Lexer<T>::parseComplexEscape(EscapeParseMode escapeParseMode, bool strictMode, T stringQuoteCharacter) -> StringParseResult
+{
+    if (m_current == 'x') {
+        shift();
+        if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) {
+            m_lexErrorMessage = ASCIILiteral("\\x can only be followed by a hex character sequence");
+            return StringCannotBeParsed;
+        }
+        T prev = m_current;
+        shift();
+        if (shouldBuildStrings)
+            record16(convertHex(prev, m_current));
+        shift();
+        return StringParsedSuccessfully;
+    }
+
+    if (m_current == 'u') {
+        shift();
+        UnicodeHexValue character = parseFourDigitUnicodeHex();
+        if (character.isValid()) {
+            if (shouldBuildStrings)
+                record16(character.value());
+            return StringParsedSuccessfully;
+        }
+
+        if (escapeParseMode == EscapeParseMode::String && m_current == stringQuoteCharacter) {
+            if (shouldBuildStrings)
+                record16('u');
+            return StringParsedSuccessfully;
+        }
+
+        m_lexErrorMessage = ASCIILiteral("\\u can only be followed by a Unicode character sequence");
+        return character.valueType() == UnicodeHexValue::IncompleteHex ? StringUnterminated : StringCannotBeParsed;
+    }
+
+    if (strictMode) {
+        if (isASCIIDigit(m_current)) {
+            // The only valid numeric escape in strict mode is '\0', and this must not be followed by a decimal digit.
+            int character1 = m_current;
+            shift();
+            if (character1 != '0' || isASCIIDigit(m_current)) {
+                m_lexErrorMessage = ASCIILiteral("The only valid numeric escape in strict mode is '\\0'");
+                return StringCannotBeParsed;
+            }
+            if (shouldBuildStrings)
+                record16(0);
+            return StringParsedSuccessfully;
+        }
+    } else {
+        if (isASCIIOctalDigit(m_current)) {
+            // Octal character sequences
+            T character1 = m_current;
+            shift();
+            if (isASCIIOctalDigit(m_current)) {
+                // Two octal characters
+                T character2 = m_current;
+                shift();
+                if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
+                    if (shouldBuildStrings)
+                        record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0');
+                    shift();
+                } else {
+                    if (shouldBuildStrings)
+                        record16((character1 - '0') * 8 + character2 - '0');
+                }
+            } else {
+                if (shouldBuildStrings)
+                    record16(character1 - '0');
+            }
+            return StringParsedSuccessfully;
+        }
+    }
+
+    if (!atEnd()) {
+        if (shouldBuildStrings)
+            record16(m_current);
+        shift();
+        return StringParsedSuccessfully;
+    }
+
+    m_lexErrorMessage = ASCIILiteral("Unterminated string constant");
+    return StringUnterminated;
+}
+
+template <typename T>
+template <bool shouldBuildStrings> auto Lexer<T>::parseStringSlowCase(JSTokenData* tokenData, bool strictMode) -> StringParseResult
 {
     T stringQuoteCharacter = m_current;
     shift();
@@ -1124,96 +1214,208 @@ template <bool shouldBuildStrings> typename Lexer<T>::StringParseResult Lexer<T>
                 shift();
             } else if (UNLIKELY(isLineTerminator(m_current)))
                 shiftLineTerminator();
-            else if (m_current == 'x') {
-                shift();
-                if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) {
-                    m_lexErrorMessage = ASCIILiteral("\\x can only be followed by a hex character sequence");
-                    return StringCannotBeParsed;
-                }
-                T prev = m_current;
-                shift();
-                if (shouldBuildStrings)
-                    record16(convertHex(prev, m_current));
-                shift();
-            } else if (m_current == 'u') {
-                shift();
-                UnicodeHexValue character = parseFourDigitUnicodeHex();
-                if (character.isValid()) {
-                    if (shouldBuildStrings)
-                        record16(character.value());
-                } else if (m_current == stringQuoteCharacter) {
-                    if (shouldBuildStrings)
-                        record16('u');
-                } else {
-                    m_lexErrorMessage = ASCIILiteral("\\u can only be followed by a Unicode character sequence");
-                    return character.valueType() == UnicodeHexValue::IncompleteHex ? StringUnterminated : StringCannotBeParsed;
-                }
-            } else if (strictMode && isASCIIDigit(m_current)) {
-                // The only valid numeric escape in strict mode is '\0', and this must not be followed by a decimal digit.
-                int character1 = m_current;
-                shift();
-                if (character1 != '0' || isASCIIDigit(m_current)) {
-                    m_lexErrorMessage = ASCIILiteral("The only valid numeric escape in strict mode is '\\0'");
-                    return StringCannotBeParsed;
-                }
+            else {
+                StringParseResult result = parseComplexEscape<shouldBuildStrings>(EscapeParseMode::String, strictMode, stringQuoteCharacter);
+                if (result != StringParsedSuccessfully)
+                    return result;
+            }
+
+            stringStart = currentSourcePtr();
+            continue;
+        }
+        // Fast check for characters that require special handling.
+        // Catches 0, \n, \r, 0x2028, and 0x2029 as efficiently
+        // as possible, and lets through all common ASCII characters.
+        if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
+            // New-line or end of input is not allowed
+            if (atEnd() || isLineTerminator(m_current)) {
+                m_lexErrorMessage = ASCIILiteral("Unexpected EOF");
+                return atEnd() ? StringUnterminated : StringCannotBeParsed;
+            }
+            // Anything else is just a normal character
+        }
+        shift();
+    }
+
+    if (currentSourcePtr() != stringStart && shouldBuildStrings)
+        append16(stringStart, currentSourcePtr() - stringStart);
+    if (shouldBuildStrings)
+        tokenData->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
+    else
+        tokenData->ident = 0;
+
+    m_buffer16.shrink(0);
+    return StringParsedSuccessfully;
+}
+
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+// While the lexer accepts <LF><CR> (not <CR><LF>) sequence
+// as one line terminator and increments one line number,
+// TemplateLiteral considers it as two line terminators <LF> and <CR>.
+//
+// TemplateLiteral normalizes line terminators as follows.
+//
+// <LF> => <LF>
+// <CR> => <LF>
+// <CR><LF> => <LF>
+// <\u2028> => <\u2028>
+// <\u2029> => <\u2029>
+//
+// So, <LF><CR> should be normalized to <LF><LF>.
+// However, the lexer should increment the line number only once for <LF><CR>.
+//
+// To achieve this, LineNumberAdder holds the current status of line terminator sequence.
+// When TemplateLiteral lexer encounters a line terminator, it notifies to LineNumberAdder.
+// LineNumberAdder maintains the status and increments the line number when it's necessary.
+// For example, LineNumberAdder increments the line number only once for <LF><CR> and <CR><LF>.
+template<typename CharacterType>
+class LineNumberAdder {
+public:
+    LineNumberAdder(int& lineNumber)
+        : m_lineNumber(lineNumber)
+    {
+    }
+
+    void clear()
+    {
+        m_previous = 0;
+    }
+
+    void add(CharacterType character)
+    {
+        ASSERT(Lexer<CharacterType>::isLineTerminator(character));
+        if ((character + m_previous) == ('\n' + '\r'))
+            m_previous = 0;
+        else {
+            ++m_lineNumber;
+            m_previous = character;
+        }
+    }
+
+private:
+    int& m_lineNumber;
+    CharacterType m_previous { 0 };
+};
+
+template <typename T>
+template <bool shouldBuildStrings> typename Lexer<T>::StringParseResult Lexer<T>::parseTemplateLiteral(JSTokenData* tokenData)
+{
+    const T* stringStart = currentSourcePtr();
+    const T* rawStringStart = currentSourcePtr();
+
+    LineNumberAdder<T> lineNumberAdder(m_lineNumber);
+
+    while (m_current != '`') {
+        if (UNLIKELY(m_current == '\\')) {
+            lineNumberAdder.clear();
+            if (stringStart != currentSourcePtr() && shouldBuildStrings)
+                append16(stringStart, currentSourcePtr() - stringStart);
+            shift();
+
+            LChar escape = singleEscape(m_current);
+
+            // Most common escape sequences first.
+            if (escape) {
                 if (shouldBuildStrings)
-                    record16(0);
-            } else if (!strictMode && isASCIIOctalDigit(m_current)) {
-                // Octal character sequences
-                T character1 = m_current;
+                    record16(escape);
                 shift();
-                if (isASCIIOctalDigit(m_current)) {
-                    // Two octal characters
-                    T character2 = m_current;
+            } else if (UNLIKELY(isLineTerminator(m_current))) {
+                if (m_current == '\r') {
+                    lineNumberAdder.add(m_current);
                     shift();
-                    if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
-                        if (shouldBuildStrings)
-                            record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0');
+                    if (m_current == '\n') {
+                        lineNumberAdder.add(m_current);
                         shift();
-                    } else {
-                        if (shouldBuildStrings)
-                            record16((character1 - '0') * 8 + character2 - '0');
                     }
                 } else {
-                    if (shouldBuildStrings)
-                        record16(character1 - '0');
+                    lineNumberAdder.add(m_current);
+                    shift();
                 }
-            } else if (!atEnd()) {
-                if (shouldBuildStrings)
-                    record16(m_current);
-                shift();
             } else {
-                m_lexErrorMessage = ASCIILiteral("Unterminated string constant");
-                return StringUnterminated;
+                bool strictMode = true;
+                StringParseResult result = parseComplexEscape<shouldBuildStrings>(EscapeParseMode::Template, strictMode, '`');
+                if (result != StringParsedSuccessfully)
+                    return result;
             }
 
             stringStart = currentSourcePtr();
             continue;
         }
+
+        if (m_current == '$' && peek(1) == '{')
+            break;
+
         // Fast check for characters that require special handling.
         // Catches 0, \n, \r, 0x2028, and 0x2029 as efficiently
         // as possible, and lets through all common ASCII characters.
         if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
-            // New-line or end of input is not allowed
-            if (atEnd() || isLineTerminator(m_current)) {
+            // End of input is not allowed.
+            // Unlike String, line terminator is allowed.
+            if (atEnd()) {
                 m_lexErrorMessage = ASCIILiteral("Unexpected EOF");
                 return atEnd() ? StringUnterminated : StringCannotBeParsed;
             }
+
+            if (isLineTerminator(m_current)) {
+                if (m_current == '\r') {
+                    // Normalize <CR>, <CR><LF> to <LF>.
+                    if (stringStart != currentSourcePtr() && shouldBuildStrings)
+                        append16(stringStart, currentSourcePtr() - stringStart);
+                    if (shouldBuildStrings)
+                        record16('\n');
+                    lineNumberAdder.add(m_current);
+                    shift();
+                    if (m_current == '\n') {
+                        lineNumberAdder.add(m_current);
+                        shift();
+                    }
+                    stringStart = currentSourcePtr();
+                } else {
+                    lineNumberAdder.add(m_current);
+                    shift();
+                }
+                continue;
+            }
             // Anything else is just a normal character
         }
+
+        lineNumberAdder.clear();
         shift();
     }
 
+    bool isTail = m_current == '`';
+
     if (currentSourcePtr() != stringStart && shouldBuildStrings)
         append16(stringStart, currentSourcePtr() - stringStart);
-    if (shouldBuildStrings)
-        tokenData->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
-    else
-        tokenData->ident = 0;
 
-    m_buffer16.resize(0);
+    if (shouldBuildStrings) {
+        tokenData->cooked = makeIdentifier(m_buffer16.data(), m_buffer16.size());
+        // TODO: While line terminator normalization (e.g. <CR> => <LF>) should be applied to both the raw and cooked representations,
+        // this raw implementation just slices the source string. As a result, line terminators appear in the raw representation without normalization.
+        // For example, when parsing `<CR>`, <CR> appears in the raw representation.
+        // While non-tagged template literals don't use the raw representation, tagged templates use the raw representation.
+        // So line terminator normalization should be applied to the raw representation when implementing tagged templates.
+        tokenData->raw = makeIdentifier(rawStringStart, currentSourcePtr() - rawStringStart);
+    } else {
+        tokenData->cooked = nullptr;
+        tokenData->raw = nullptr;
+    }
+    tokenData->isTail = isTail;
+
+    m_buffer16.shrink(0);
+
+    if (isTail) {
+        // Skip `
+        shift();
+    } else {
+        // Skip $ and {
+        shift();
+        shift();
+    }
+
     return StringParsedSuccessfully;
 }
+#endif
 
 template <typename T>
 ALWAYS_INLINE void Lexer<T>::parseHex(double& returnValue)
@@ -1736,7 +1938,7 @@ start:
                 goto returnError;
             }
             token = tokenTypeForIntegerLikeToken(tokenData->doubleValue);
-            m_buffer8.resize(0);
+            m_buffer8.shrink(0);
             break;
         }
         if ((m_current | 0x20) == 'b') {
@@ -1756,7 +1958,7 @@ start:
                 goto returnError;
             }
             token = tokenTypeForIntegerLikeToken(tokenData->doubleValue);
-            m_buffer8.resize(0);
+            m_buffer8.shrink(0);
             break;
         }
 
@@ -1777,7 +1979,7 @@ start:
                 goto returnError;
             }
             token = tokenTypeForIntegerLikeToken(tokenData->doubleValue);
-            m_buffer8.resize(0);
+            m_buffer8.shrink(0);
             break;
         }
 
@@ -1824,25 +2026,41 @@ inNumberAfterDecimalPoint:
             token = atEnd() ? UNTERMINATED_NUMERIC_LITERAL_ERRORTOK : INVALID_NUMERIC_LITERAL_ERRORTOK;
             goto returnError;
         }
-        m_buffer8.resize(0);
+        m_buffer8.shrink(0);
         break;
-    case CharacterQuote:
-        if (lexerFlags & LexerFlagsDontBuildStrings) {
-            StringParseResult result = parseString<false>(tokenData, strictMode);
-            if (UNLIKELY(result != StringParsedSuccessfully)) {
-                token = result == StringUnterminated ? UNTERMINATED_STRING_LITERAL_ERRORTOK : INVALID_STRING_LITERAL_ERRORTOK;
-                goto returnError;
-            }
-        } else {
-            StringParseResult result = parseString<true>(tokenData, strictMode);
-            if (UNLIKELY(result != StringParsedSuccessfully)) {
-                token = result == StringUnterminated ? UNTERMINATED_STRING_LITERAL_ERRORTOK : INVALID_STRING_LITERAL_ERRORTOK;
-                goto returnError;
-            }
+    case CharacterQuote: {
+        StringParseResult result = StringCannotBeParsed;
+        if (lexerFlags & LexerFlagsDontBuildStrings)
+            result = parseString<false>(tokenData, strictMode);
+        else
+            result = parseString<true>(tokenData, strictMode);
+
+        if (UNLIKELY(result != StringParsedSuccessfully)) {
+            token = result == StringUnterminated ? UNTERMINATED_STRING_LITERAL_ERRORTOK : INVALID_STRING_LITERAL_ERRORTOK;
+            goto returnError;
         }
         shift();
         token = STRING;
         break;
+        }
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    case CharacterBackQuote: {
+        // Skip backquote.
+        shift();
+        StringParseResult result = StringCannotBeParsed;
+        if (lexerFlags & LexerFlagsDontBuildStrings)
+            result = parseTemplateLiteral<false>(tokenData);
+        else
+            result = parseTemplateLiteral<true>(tokenData);
+
+        if (UNLIKELY(result != StringParsedSuccessfully)) {
+            token = result == StringUnterminated ? UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK : INVALID_TEMPLATE_LITERAL_ERRORTOK;
+            goto returnError;
+        }
+        token = TEMPLATE;
+        break;
+        }
+#endif
     case CharacterIdentifierStart:
         ASSERT(isIdentStart(m_current));
         FALLTHROUGH;
@@ -1945,7 +2163,7 @@ bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags,
 
     while (true) {
         if (isLineTerminator(m_current) || atEnd()) {
-            m_buffer16.resize(0);
+            m_buffer16.shrink(0);
             return false;
         }
 
@@ -1979,7 +2197,7 @@ bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags,
 
     pattern = makeRightSizedIdentifier(m_buffer16.data(), m_buffer16.size(), charactersOredTogether);
 
-    m_buffer16.resize(0);
+    m_buffer16.shrink(0);
     charactersOredTogether = 0;
 
     while (isIdentPart(m_current)) {
@@ -1989,7 +2207,7 @@ bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags,
     }
 
     flags = makeRightSizedIdentifier(m_buffer16.data(), m_buffer16.size(), charactersOredTogether);
-    m_buffer16.resize(0);
+    m_buffer16.shrink(0);
 
     return true;
 }
@@ -2035,6 +2253,40 @@ bool Lexer<T>::skipRegExp()
     return true;
 }
 
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+template <typename T>
+JSTokenType Lexer<T>::scanTrailingTemplateString(JSToken* tokenRecord)
+{
+    JSTokenData* tokenData = &tokenRecord->m_data;
+    JSTokenLocation* tokenLocation = &tokenRecord->m_location;
+    ASSERT(!m_error);
+    ASSERT(m_buffer16.isEmpty());
+
+    // Leading closing brace } is already shifted in the previous token scan.
+    // So in this re-scan phase, shift() is not needed here.
+    StringParseResult result = parseTemplateLiteral<true>(tokenData);
+    JSTokenType token = ERRORTOK;
+    if (UNLIKELY(result != StringParsedSuccessfully)) {
+        token = result == StringUnterminated ? UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK : INVALID_TEMPLATE_LITERAL_ERRORTOK;
+        m_error = true;
+    } else {
+        token = TEMPLATE;
+        m_lastToken = token;
+    }
+
+    // Since TemplateString always ends with ` or }, m_atLineStart always becomes false.
+    m_atLineStart = false;
+
+    // Adjust current tokenLocation data for TemplateString.
+    tokenLocation->line = m_lineNumber;
+    tokenLocation->endOffset = currentOffset();
+    tokenLocation->lineStartOffset = currentLineStartOffset();
+    ASSERT(tokenLocation->endOffset >= tokenLocation->lineStartOffset);
+    tokenRecord->m_endPosition = currentPosition();
+    return token;
+}
+#endif
+
 template <typename T>
 void Lexer<T>::clear()
 {
index 2df5213..39010a1 100644 (file)
@@ -99,6 +99,9 @@ public:
     int lastLineNumber() const { return m_lastLineNumber; }
     bool prevTerminator() const { return m_terminator; }
     bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0);
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    JSTokenType scanTrailingTemplateString(JSToken*);
+#endif
     bool skipRegExp();
 
     // Functions for use after parsing.
@@ -202,6 +205,12 @@ private:
     };
     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);
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    template <bool shouldBuildStrings> ALWAYS_INLINE StringParseResult parseTemplateLiteral(JSTokenData*);
+#endif
     ALWAYS_INLINE void parseHex(double& returnValue);
     ALWAYS_INLINE bool parseBinary(double& returnValue);
     ALWAYS_INLINE bool parseOctal(double& returnValue);
index 767b852..89b928e 100644 (file)
@@ -100,6 +100,51 @@ namespace JSC {
     {
     }
 
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    inline TemplateExpressionListNode::TemplateExpressionListNode(ExpressionNode* node)
+        : m_node(node)
+    {
+    }
+
+    inline TemplateExpressionListNode::TemplateExpressionListNode(TemplateExpressionListNode* previous, ExpressionNode* node)
+        : m_node(node)
+    {
+        previous->m_next = this;
+    }
+
+    inline TemplateStringNode::TemplateStringNode(const JSTokenLocation& location, const Identifier& cooked, const Identifier& raw)
+        : ExpressionNode(location)
+        , m_cooked(cooked)
+        , m_raw(raw)
+    {
+    }
+
+    inline TemplateStringListNode::TemplateStringListNode(TemplateStringNode* node)
+        : m_node(node)
+    {
+    }
+
+    inline TemplateStringListNode::TemplateStringListNode(TemplateStringListNode* previous, TemplateStringNode* node)
+        : m_node(node)
+    {
+        previous->m_next = this;
+    }
+
+    inline TemplateLiteralNode::TemplateLiteralNode(const JSTokenLocation& location, TemplateStringListNode* templateStrings)
+        : ExpressionNode(location)
+        , m_templateStrings(templateStrings)
+        , m_templateExpressions(nullptr)
+    {
+    }
+
+    inline TemplateLiteralNode::TemplateLiteralNode(const JSTokenLocation& location, TemplateStringListNode* templateStrings, TemplateExpressionListNode* templateExpressions)
+        : ExpressionNode(location)
+        , m_templateStrings(templateStrings)
+        , m_templateExpressions(templateExpressions)
+    {
+    }
+#endif
+
     inline RegExpNode::RegExpNode(const JSTokenLocation& location, const Identifier& pattern, const Identifier& flags)
         : ExpressionNode(location)
         , m_pattern(pattern)
index 859f321..7848184 100644 (file)
@@ -274,7 +274,7 @@ namespace JSC {
 
         const Identifier& m_value;
     };
-    
+
     class ThrowableExpressionData {
     public:
         ThrowableExpressionData()
@@ -427,6 +427,60 @@ namespace JSC {
         uint16_t m_subexpressionLineStartOffset;
     };
 
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    class TemplateExpressionListNode : public ParserArenaFreeable {
+    public:
+        TemplateExpressionListNode(ExpressionNode*);
+        TemplateExpressionListNode(TemplateExpressionListNode*, ExpressionNode*);
+
+        ExpressionNode* value() { return m_node; }
+        TemplateExpressionListNode* next() { return m_next; }
+
+    private:
+        TemplateExpressionListNode* m_next { nullptr };
+        ExpressionNode* m_node { nullptr };
+    };
+
+    class TemplateStringNode : public ExpressionNode {
+    public:
+        TemplateStringNode(const JSTokenLocation&, const Identifier& cooked, const Identifier& raw);
+
+        const Identifier& cooked() { return m_cooked; }
+        const Identifier& raw() { return m_raw; }
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        const Identifier& m_cooked;
+        const Identifier& m_raw;
+    };
+
+    class TemplateStringListNode : public ParserArenaFreeable {
+    public:
+        TemplateStringListNode(TemplateStringNode*);
+        TemplateStringListNode(TemplateStringListNode*, TemplateStringNode*);
+
+        TemplateStringNode* value() { return m_node; }
+        TemplateStringListNode* next() { return m_next; }
+
+    private:
+        TemplateStringListNode* m_next { nullptr };
+        TemplateStringNode* m_node { nullptr };
+    };
+
+    class TemplateLiteralNode : public ExpressionNode {
+    public:
+        TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*);
+        TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*, TemplateExpressionListNode*);
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        TemplateStringListNode* m_templateStrings;
+        TemplateExpressionListNode* m_templateExpressions;
+    };
+#endif
+
     class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
     public:
         RegExpNode(const JSTokenLocation&, const Identifier& pattern, const Identifier& flags);
index c97c8ee..bd799bf 100644 (file)
@@ -2269,6 +2269,66 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral
     return context.createArray(location, elementList);
 }
 
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+template <typename LexerType>
+template <class TreeBuilder> typename TreeBuilder::TemplateString Parser<LexerType>::parseTemplateString(TreeBuilder& context, bool isTemplateHead, bool& elementIsTail)
+{
+    if (!isTemplateHead) {
+        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);
+    }
+    matchOrFail(TEMPLATE, "Expected an template element");
+    const Identifier* cooked = m_token.m_data.cooked;
+    const Identifier* raw = m_token.m_data.raw;
+    elementIsTail = m_token.m_data.isTail;
+    JSTokenLocation location(tokenLocation());
+    next();
+    return context.createTemplateString(location, *cooked, *raw);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> typename TreeBuilder::TemplateLiteral Parser<LexerType>::parseTemplateLiteral(TreeBuilder& context)
+{
+    JSTokenLocation location(tokenLocation());
+    bool elementIsTail = false;
+
+    auto headTemplateString = parseTemplateString(context, true, elementIsTail);
+    failIfFalse(headTemplateString, "Cannot parse head template element");
+
+    typename TreeBuilder::TemplateStringList templateStringList = context.createTemplateStringList(headTemplateString);
+    typename TreeBuilder::TemplateStringList templateStringTail = templateStringList;
+
+    if (elementIsTail)
+        return context.createTemplateLiteral(location, templateStringList);
+
+    failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
+    TreeExpression expression = parseExpression(context);
+    failIfFalse(expression, "Cannot parse expression in template literal");
+
+    typename TreeBuilder::TemplateExpressionList templateExpressionList = context.createTemplateExpressionList(expression);
+    typename TreeBuilder::TemplateExpressionList templateExpressionTail = templateExpressionList;
+
+    auto templateString = parseTemplateString(context, false, elementIsTail);
+    failIfFalse(templateString, "Cannot parse template element");
+    templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
+
+    while (!elementIsTail) {
+        failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
+        TreeExpression expression = parseExpression(context);
+        failIfFalse(expression, "Cannot parse expression in template literal");
+
+        templateExpressionTail = context.createTemplateExpressionList(templateExpressionTail, expression);
+
+        auto templateString = parseTemplateString(context, false, elementIsTail);
+        failIfFalse(templateString, "Cannot parse template element");
+        templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
+    }
+
+    return context.createTemplateLiteral(location, templateStringList, templateExpressionList);
+}
+#endif
+
 template <typename LexerType>
 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
 {
@@ -2370,6 +2430,10 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre
         }
         return re;
     }
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    case TEMPLATE:
+        return parseTemplateLiteral(context);
+#endif
     default:
         failDueToUnexpectedToken();
     }
index 0f2728f..bde4b0e 100644 (file)
@@ -776,6 +776,10 @@ private:
 #if ENABLE(ES6_CLASS_SYNTAX)
     template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionRequirements, ParserClassInfo<TreeBuilder>&);
 #endif
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateString parseTemplateString(TreeBuilder& context, bool isTemplateHead, bool& elementIsTail);
+    template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateLiteral parseTemplateLiteral(TreeBuilder&);
+#endif
 
     ALWAYS_INLINE int isBinaryOperator(JSTokenType);
     bool allowAutomaticSemicolon();
index 8329f82..026e4f8 100644 (file)
@@ -96,6 +96,7 @@ enum JSTokenType {
     DOUBLE,
     IDENT,
     STRING,
+    TEMPLATE,
     SEMICOLON,
     COLON,
     DOT,
@@ -161,7 +162,9 @@ enum JSTokenType {
     INVALID_STRING_LITERAL_ERRORTOK = 9 | ErrorTokenFlag,
     INVALID_PRIVATE_NAME_ERRORTOK = 10 | ErrorTokenFlag,
     INVALID_HEX_NUMBER_ERRORTOK = 11 | ErrorTokenFlag,
-    INVALID_BINARY_NUMBER_ERRORTOK = 12 | ErrorTokenFlag
+    INVALID_BINARY_NUMBER_ERRORTOK = 12 | ErrorTokenFlag,
+    UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK = 13 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
+    INVALID_TEMPLATE_LITERAL_ERRORTOK = 14 | ErrorTokenFlag,
 };
 
 struct JSTextPosition {
@@ -189,6 +192,11 @@ union JSTokenData {
     };
     double doubleValue;
     const Identifier* ident;
+    struct {
+        const Identifier* cooked;
+        const Identifier* raw;
+        bool isTail;
+    };
 };
 
 struct JSTokenLocation {
index 8e4f61b..554e5df 100644 (file)
@@ -81,7 +81,8 @@ public:
         FunctionBodyResult, SpreadExpr, ArgumentsResult,
         PropertyListResult, ArgumentsListResult, ElementsListResult,
         StatementResult, FormalParameterListResult, ClauseResult,
-        ClauseListResult, CommaExpr, DeconstructingAssignment
+        ClauseListResult, CommaExpr, DeconstructingAssignment,
+        TemplateStringResult, TemplateStringListResult, TemplateExpressionListResult, TemplateExpr
     };
     typedef int ExpressionType;
 
@@ -111,6 +112,12 @@ public:
     typedef int PropertyList;
     typedef int ElementList;
     typedef int ArgumentsList;
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    typedef int TemplateExpressionList;
+    typedef int TemplateString;
+    typedef int TemplateStringList;
+    typedef int TemplateLiteral;
+#endif
     typedef int FormalParameterList;
     typedef int FunctionBody;
 #if ENABLE(ES6_CLASS_SYNTAX)
@@ -173,6 +180,16 @@ public:
     int createArguments() { return ArgumentsResult; }
     int createArguments(int) { return ArgumentsResult; }
     ExpressionType createSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return SpreadExpr; }
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    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; }
+    TemplateExpressionList createTemplateExpressionList(TemplateExpressionList, Expression) { return TemplateExpressionListResult; }
+    TemplateLiteral createTemplateLiteral(const JSTokenLocation&, TemplateStringList) { return TemplateExpr; }
+    TemplateLiteral createTemplateLiteral(const JSTokenLocation&, TemplateStringList, TemplateExpressionList) { return TemplateExpr; }
+#endif
+
     int createArgumentsList(const JSTokenLocation&, int) { return ArgumentsListResult; }
     int createArgumentsList(const JSTokenLocation&, int, int) { return ArgumentsListResult; }
     Property createProperty(const Identifier* name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding = SuperBinding::NotNeeded)
index b8fa1ab..009b350 100644 (file)
@@ -337,6 +337,12 @@ SLOW_PATH_DECL(slow_path_to_number)
     RETURN(jsNumber(OP_C(2).jsValue().toNumber(exec)));
 }
 
+SLOW_PATH_DECL(slow_path_to_string)
+{
+    BEGIN();
+    RETURN(OP_C(2).jsValue().toString(exec));
+}
+
 SLOW_PATH_DECL(slow_path_negate)
 {
     BEGIN();
index 0f67e63..4d8e3fc 100644 (file)
@@ -201,6 +201,7 @@ SLOW_PATH_HIDDEN_DECL(slow_path_greatereq);
 SLOW_PATH_HIDDEN_DECL(slow_path_inc);
 SLOW_PATH_HIDDEN_DECL(slow_path_dec);
 SLOW_PATH_HIDDEN_DECL(slow_path_to_number);
+SLOW_PATH_HIDDEN_DECL(slow_path_to_string);
 SLOW_PATH_HIDDEN_DECL(slow_path_negate);
 SLOW_PATH_HIDDEN_DECL(slow_path_add);
 SLOW_PATH_HIDDEN_DECL(slow_path_mul);
diff --git a/Source/JavaScriptCore/tests/stress/template-literal-line-terminators.js b/Source/JavaScriptCore/tests/stress/template-literal-line-terminators.js
new file mode 100644 (file)
index 0000000..9d504be
--- /dev/null
@@ -0,0 +1,56 @@
+function test(actual, expected) {
+    if (actual !== expected)
+        throw new Error("bad value: " + actual);
+}
+
+function testEval(script, expected) {
+    test(eval(script), expected);
+}
+
+function testEvalLineNumber(script, expected, lineNum) {
+    testEval(script, expected);
+
+    var error = null;
+    var actualLine;
+    try {
+        eval(script + ';throw new Error("line");');
+    } catch (error) {
+        actualLine = error.line;
+    }
+    test(actualLine, lineNum);
+}
+
+test(`Hello`, "Hello");
+test(`Hello World`, "Hello World");
+test(`
+`, "\n");
+test(`Hello
+World`, "Hello\nWorld");
+
+testEvalLineNumber("`Hello World`", "Hello World", 1);
+
+testEvalLineNumber("`Hello\rWorld`", "Hello\nWorld", 2);
+testEvalLineNumber("`Hello\nWorld`", "Hello\nWorld", 2);
+
+testEvalLineNumber("`Hello\r\rWorld`", "Hello\n\nWorld", 3);
+testEvalLineNumber("`Hello\r\nWorld`", "Hello\nWorld", 2);
+testEvalLineNumber("`Hello\n\nWorld`", "Hello\n\nWorld", 3);
+testEvalLineNumber("`Hello\n\rWorld`", "Hello\n\nWorld", 2);
+
+testEvalLineNumber("`Hello\n\r\nWorld`", "Hello\n\nWorld", 3);
+testEvalLineNumber("`Hello\r\n\rWorld`", "Hello\n\nWorld", 3);
+testEvalLineNumber("`Hello\n\n\nWorld`", "Hello\n\n\nWorld", 4);
+
+testEvalLineNumber("`Hello\n\r\n\rWorld`", "Hello\n\n\nWorld", 3);
+testEvalLineNumber("`Hello\n\r\n\nWorld`", "Hello\n\n\nWorld", 4);
+testEvalLineNumber("`Hello\r\n\n\nWorld`", "Hello\n\n\nWorld", 4);
+
+testEvalLineNumber("`Hello\\\n\r\rWorld`", "Hello\n\nWorld", 3);
+testEvalLineNumber("`Hello\\\r\n\n\nWorld`", "Hello\n\nWorld", 4);
+testEvalLineNumber("`Hello\\\n\r\n\nWorld`", "Hello\n\nWorld", 4);
+testEvalLineNumber("`Hello\\\n\r\r\nWorld`", "Hello\n\nWorld", 3);
+
+testEvalLineNumber("`\u2028`", "\u2028", 2);
+testEvalLineNumber("`\u2029`", "\u2029", 2);
+testEvalLineNumber("`\\u2028`", "\u2028", 1);
+testEvalLineNumber("`\\u2029`", "\u2029", 1);
diff --git a/Source/JavaScriptCore/tests/stress/template-literal-syntax.js b/Source/JavaScriptCore/tests/stress/template-literal-syntax.js
new file mode 100644 (file)
index 0000000..b444280
--- /dev/null
@@ -0,0 +1,83 @@
+
+function testSyntax(script) {
+    try {
+        eval(script);
+    } catch (error) {
+        if (error instanceof SyntaxError)
+            throw new Error("Bad error: " + String(error));
+    }
+}
+
+function testSyntaxError(script, message) {
+    var error = null;
+    try {
+        eval(script);
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error("Expected syntax error not thrown");
+
+    if (String(error) !== message)
+        throw new Error("Bad error: " + String(error));
+}
+
+testSyntax("`Hello`");
+testSyntax("(`Hello`)");
+testSyntax("(`Hello`) + 42");
+testSyntax("`\nHello\nWorld`");
+testSyntax("`\nHello\n${World}`");
+testSyntax("`${World}`");
+testSyntax("`${World} Hello`");
+testSyntax("`$ {World} Hello`");
+testSyntax("`\\uFEFFtest`");
+testSyntax("`\r\n`");
+testSyntax("`\\r\\n`");
+testSyntax("`\n`");
+testSyntax("`\\n`");
+testSyntax("`\u2028`");
+testSyntax("`\\u2028`");
+testSyntax("`\u2029`");
+testSyntax("`\\u2029`");
+testSyntax("`\\0`");
+testSyntax("`\0`");
+testSyntax("`\\x7f`");
+testSyntax("(`Hello`) + 42");
+testSyntax("`\\\n`");
+testSyntax("`\\\r\n`");
+testSyntax("`\\\r`");
+
+testSyntaxError("`Hello", "SyntaxError: Unexpected EOF");
+testSyntaxError("`Hello${expr}", "SyntaxError: Unexpected EOF");
+testSyntaxError("`Hello${}", "SyntaxError: Unexpected token '}'. Template literal expression cannot be empty.");
+testSyntaxError("`Hello${expr} ${}", "SyntaxError: Unexpected token '}'. Template literal expression cannot be empty.");
+testSyntaxError("`Hello${expr}", "SyntaxError: Unexpected EOF");
+testSyntaxError("`Hello${expr} ${expr}", "SyntaxError: Unexpected EOF");
+testSyntaxError("`Hello${expr`", "SyntaxError: Unexpected EOF");
+testSyntaxError("`Hello${expr} ${expr`", "SyntaxError: Unexpected EOF");
+testSyntaxError("`Hello expr${`", "SyntaxError: Unexpected EOF");
+testSyntaxError("`Hello${expr} expr${`", "SyntaxError: Unexpected EOF");
+testSyntaxError("`Hello ${}`", "SyntaxError: Unexpected token '}'. Template literal expression cannot be empty.");
+testSyntaxError("`Hello${expr} ${}`", "SyntaxError: Unexpected token '}'. Template literal expression cannot be empty.");
+testSyntaxError("`\\07`", "SyntaxError: The only valid numeric escape in strict mode is '\\0'");
+for (var i = 1; i < 7; ++i) {
+    testSyntaxError("`\\" + i + "`", "SyntaxError: The only valid numeric escape in strict mode is '\\0'");
+    testSyntaxError("`${expr}\\" + i + "`", "SyntaxError: The only valid numeric escape in strict mode is '\\0'");
+}
+// \8 and \9 are not allowed.
+for (var i = 8; i < 9; ++i) {
+    testSyntaxError("`\\" + i + "`", "SyntaxError: The only valid numeric escape in strict mode is '\\0'");
+    testSyntaxError("`${expr}\\" + i + "`", "SyntaxError: The only valid numeric escape in strict mode is '\\0'");
+}
+testSyntaxError("`\\x7`", "SyntaxError: \\x can only be followed by a hex character sequence");
+testSyntaxError("`${expr}\\x7`", "SyntaxError: \\x can only be followed by a hex character sequence");
+testSyntaxError("`\\x`", "SyntaxError: \\x can only be followed by a hex character sequence");
+testSyntaxError("`${expr}\\x`", "SyntaxError: \\x can only be followed by a hex character sequence");
+testSyntaxError("`\\u`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`${expr}\\u`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`\\u2`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`${expr}\\u2`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+testSyntaxError("`\\u20`", "SyntaxError: \\u can only be followed by a Unicode character sequence");
+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");
diff --git a/Source/JavaScriptCore/tests/stress/template-literal.js b/Source/JavaScriptCore/tests/stress/template-literal.js
new file mode 100644 (file)
index 0000000..e69cfdf
--- /dev/null
@@ -0,0 +1,206 @@
+function test(actual, expected) {
+    if (actual !== expected)
+        throw new Error("bad value: " + actual);
+}
+
+function testEval(script, expected) {
+    test(eval(script), expected);
+}
+
+function testEmbedded(value, expected) {
+    var template = `Hello ${value} World`;
+    test(template, expected);
+}
+
+test(``, "");
+test(`${""}`, "");
+test(`${``}`, "");
+test(`${``}${``}${``}${""}`, "");
+
+test(`Hello World`, "Hello World");
+test(`Hello
+        World`, "Hello\n        World");
+
+test(`\uFEFF`, "\uFEFF");
+testEval("`\uFEFF`", "\uFEFF");
+
+test(`\x20`, "\x20");
+test(`\x2020`, "\x2020");
+
+for (var ch of [ '\'', '"', '\\', 'b', 'f', 'n', 'r', 't', 'v' ])
+    testEval("`\\" + ch + "`", eval("'\\" + ch + "'"));
+
+test(`\
+Hello World`, "Hello World");
+
+test(`\
+
+Hello World`, "\nHello World");
+
+test(`\u2028\u2029\r\n`, "\u2028\u2029\r\n");
+test(`\u2028\u2029\n\r\n`, "\u2028\u2029\n\r\n");
+test(`\u2028200`, "\u2028200");
+
+testEmbedded(42, "Hello 42 World");
+testEmbedded("ISUCA", "Hello ISUCA World");
+testEmbedded(null, "Hello null World");
+testEmbedded(undefined, "Hello undefined World");
+testEmbedded({}, "Hello [object Object] World");
+
+(function () {
+    var object = {
+        name: "Cocoa",
+    };
+    var array = [
+        "Cappuccino"
+    ]
+    test(`Hello ${object.name} and ${array[0]} :D`, "Hello Cocoa and Cappuccino :D");
+}());
+
+(function () {
+    function ok() {
+        return "Cocoa";
+    }
+    test(`Hello ${ ok() }`, "Hello Cocoa");
+}());
+
+(function () {
+    var object = {
+        toString() {
+            return 'Cocoa';
+        }
+    };
+    test(`Hello ${object} :D`, "Hello Cocoa :D");
+}());
+
+// Immediately adjacent template expressions, with empty intermediate template strings.
+test(`${"C"}${"o"}${"c"}${"o"}${"a"}`, "Cocoa");
+test(`${"C"}${"o"}${"c"}${"o"}${" "}`, "Coco ");
+
+// Nested templates.
+test(`Hello ${ `Cocoa` }`, "Hello Cocoa");
+test(`Hello ${ `Co${`c`}oa` }`, "Hello Cocoa");
+
+// Evaluation order
+(function () {
+    var count = 0;
+
+    function check(num) {
+        var now = count++;
+        test(now, num);
+        return now;
+    }
+
+    test(`Hello ${ `${ check(0) } ${ ` ${ check(1) } ${ check(2) }` } ${ check(3) }` } ${ check(4) }`, "Hello 0  1 2 3 4")
+}());
+
+// Exceptions
+
+(function () {
+    function gen(num) {
+        return {
+            toString() {
+                throw new Error(num);
+            }
+        };
+    }
+
+    var error = null;
+    try {
+        var template = `${gen(0)} ${gen(1)} ${gen(2)}`;
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error('no error thrown');
+    if (String(error) !== 'Error: 0')
+        throw new Error("bad error: " + String(error));
+
+    var error = null;
+    try {
+        var template = `${52} ${gen(0)} ${gen(1)}`;
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error('no error thrown');
+    if (String(error) !== 'Error: 0')
+        throw new Error("bad error: " + String(error));
+}());
+
+
+(function () {
+    var stat= {
+        count: 0
+    };
+    function gen(num) {
+        stat[num] = {
+            called: true,
+            count: stat.count++,
+            toString: null
+        };
+        return {
+            toString() {
+                stat[num].toString = {
+                    called: true,
+                    count: stat.count++,
+                };
+                throw new Error(num);
+            }
+        };
+    }
+
+    var error = null;
+    try {
+        var template = `${gen(0)} ${gen(1)} ${gen(2)}`;
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error('no error thrown');
+    if (String(error) !== 'Error: 0')
+        throw new Error("bad error: " + String(error));
+    test(stat[0].count, 0);
+    test(stat[0].toString.called, true);
+    test(stat[0].toString.count, 1);
+    test(stat[1], undefined);
+    test(stat[2], undefined);
+}());
+
+(function () {
+    var stat= {
+        count: 0
+    };
+    function gen(num) {
+        stat[num] = {
+            called: true,
+            count: stat.count++,
+            toString: null
+        };
+        return {
+            toString() {
+                stat[num].toString = {
+                    called: true,
+                    count: stat.count++,
+                };
+                throw new Error(num);
+            }
+        };
+    }
+
+    var error = null;
+    try {
+        var template = `${ `${gen(0)}` } ${ `${gen(1)} ${gen(2)}` }`;
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error('no error thrown');
+    if (String(error) !== 'Error: 0')
+        throw new Error("bad error: " + String(error));
+    test(stat[0].count, 0);
+    test(stat[0].toString.called, true);
+    test(stat[0].toString.count, 1);
+    test(stat[1], undefined);
+    test(stat[2], undefined);
+}());
index c3413e9..38a3706 100644 (file)
@@ -1,3 +1,14 @@
+2015-04-26  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement ES6 template literals
+        https://bugs.webkit.org/show_bug.cgi?id=142691
+
+        Reviewed by Darin Adler.
+
+        Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.
+
+        * Configurations/FeatureDefines.xcconfig:
+
 2015-04-26  Javier Fernandez  <jfernandez@igalia.com>
 
         [CSS Grid Layout] Support for align-self and align-items in grid layout
index efc3205..f5b45d9 100644 (file)
@@ -45,6 +45,7 @@ ENABLE_CANVAS_PATH = ENABLE_CANVAS_PATH;
 ENABLE_CANVAS_PROXY = ;
 ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING;
 ENABLE_ES6_CLASS_SYNTAX = ENABLE_ES6_CLASS_SYNTAX;
+ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX = ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX;
 ENABLE_CONTENT_FILTERING = ENABLE_CONTENT_FILTERING;
 ENABLE_CSP_NEXT = ;
 ENABLE_CSS_ANIMATIONS_LEVEL_2 = ENABLE_CSS_ANIMATIONS_LEVEL_2;
@@ -214,4 +215,4 @@ ENABLE_LLINT_C_LOOP = ;
 
 ENABLE_SATURATED_LAYOUT_ARITHMETIC = ENABLE_SATURATED_LAYOUT_ARITHMETIC;
 
-FEATURE_DEFINES = $(ENABLE_3D_TRANSFORMS) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) $(ENABLE_AVF_CAPTIONS) $(ENABLE_ATTACHMENT_ELEMENT) $(ENABLE_CACHE_PARTITIONING) $(ENABLE_CANVAS_PATH) $(ENABLE_CANVAS_PROXY) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_ES6_CLASS_SYNTAX) $(ENABLE_CONTENT_FILTERING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_ANIMATIONS_LEVEL_2) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_DEVICE_ADAPTATION) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SELECTORS_LEVEL4) $(ENABLE_CSS_SHAPES) $(ENABLE_CSS3_TEXT) $(ENABLE_CSS3_TEXT_LINE_BREAK) $(ENABLE_CURSOR_VISIBILITY) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM4_EVENTS_CONSTRUCTOR) $(ENABLE_ENCRYPTED_MEDIA) $(ENABLE_ENCRYPTED_MEDIA_V2) $(ENABLE_FILTERS_LEVEL_2) $(ENABLE_FONT_LOAD_EVENTS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GAMEPAD_DEPRECATED) $(ENABLE_GEOLOCATION) $(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) $(ENABLE_ICONDATABASE) $(ENABLE_SERVICE_CONTROLS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INDEXED_DATABASE_IN_WORKERS) $(ENABLE_INDIE_UI) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_COLOR_POPOVER) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_WIRELESS_PLAYBACK_TARGET) $(ENABLE_IOS_GESTURE_EVENTS) $(ENABLE_IOS_TEXT_AUTOSIZING) $(ENABLE_IOS_TOUCH_EVENTS) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LEGACY_VENDOR_PREFIXES) $(ENABLE_LEGACY_WEB_AUDIO) $(ENABLE_LETTERPRESS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_CONTROLS_SCRIPT) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MOUSE_CURSOR_SCALE) $(ENABLE_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NAVIGATOR_HWCONCURRENCY) $(ENABLE_NOTIFICATIONS) $(ENABLE_PDFKIT_PLUGIN) $(ENABLE_POINTER_LOCK) $(ENABLE_PROMISES) $(ENABLE_PROXIMITY_EVENTS) $(ENABLE_PUBLIC_SUFFIX_LIST) $(ENABLE_QUOTA) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_REQUEST_AUTOCOMPLETE) $(ENABLE_REMOTE_INSPECTOR) $(ENABLE_RESOLUTION_MEDIA_QUERY) $(ENABLE_RUBBER_BANDING) $(ENABLE_CSS_SCROLL_SNAP) $(ENABLE_SPEECH_SYNTHESIS) $(ENABLE_STREAMS_API) $(ENABLE_SUBTLE_CRYPTO) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_OTF_CONVERTER) $(ENABLE_TELEPHONE_NUMBER_DETECTION) $(ENABLE_TEMPLATE_ELEMENT) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TOUCH_EVENTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_CSS_TRAILING_WORD) $(ENABLE_USERSELECT_ALL) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_DATACUE_VALUE) $(ENABLE_VIEW_MODE_CSS_MEDIA) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_REPLAY) $(ENABLE_WEB_SOCKETS) $(ENABLE_PICTURE_SIZES) $(ENABLE_WEB_TIMING) $(ENABLE_WEBVTT_REGIONS) $(ENABLE_XHR_TIMEOUT) $(ENABLE_XSLT) $(ENABLE_FTL_JIT) $(ENABLE_LLINT_C_LOOP) $(ENABLE_SATURATED_LAYOUT_ARITHMETIC) $(ENABLE_VIDEO_PRESENTATION_MODE);
+FEATURE_DEFINES = $(ENABLE_3D_TRANSFORMS) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) $(ENABLE_AVF_CAPTIONS) $(ENABLE_ATTACHMENT_ELEMENT) $(ENABLE_CACHE_PARTITIONING) $(ENABLE_CANVAS_PATH) $(ENABLE_CANVAS_PROXY) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_ES6_CLASS_SYNTAX) $(ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX) $(ENABLE_CONTENT_FILTERING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_ANIMATIONS_LEVEL_2) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_DEVICE_ADAPTATION) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SELECTORS_LEVEL4) $(ENABLE_CSS_SHAPES) $(ENABLE_CSS3_TEXT) $(ENABLE_CSS3_TEXT_LINE_BREAK) $(ENABLE_CURSOR_VISIBILITY) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM4_EVENTS_CONSTRUCTOR) $(ENABLE_ENCRYPTED_MEDIA) $(ENABLE_ENCRYPTED_MEDIA_V2) $(ENABLE_FILTERS_LEVEL_2) $(ENABLE_FONT_LOAD_EVENTS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GAMEPAD_DEPRECATED) $(ENABLE_GEOLOCATION) $(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) $(ENABLE_ICONDATABASE) $(ENABLE_SERVICE_CONTROLS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INDEXED_DATABASE_IN_WORKERS) $(ENABLE_INDIE_UI) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_COLOR_POPOVER) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_WIRELESS_PLAYBACK_TARGET) $(ENABLE_IOS_GESTURE_EVENTS) $(ENABLE_IOS_TEXT_AUTOSIZING) $(ENABLE_IOS_TOUCH_EVENTS) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LEGACY_VENDOR_PREFIXES) $(ENABLE_LEGACY_WEB_AUDIO) $(ENABLE_LETTERPRESS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_CONTROLS_SCRIPT) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MOUSE_CURSOR_SCALE) $(ENABLE_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NAVIGATOR_HWCONCURRENCY) $(ENABLE_NOTIFICATIONS) $(ENABLE_PDFKIT_PLUGIN) $(ENABLE_POINTER_LOCK) $(ENABLE_PROMISES) $(ENABLE_PROXIMITY_EVENTS) $(ENABLE_PUBLIC_SUFFIX_LIST) $(ENABLE_QUOTA) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_REQUEST_AUTOCOMPLETE) $(ENABLE_REMOTE_INSPECTOR) $(ENABLE_RESOLUTION_MEDIA_QUERY) $(ENABLE_RUBBER_BANDING) $(ENABLE_CSS_SCROLL_SNAP) $(ENABLE_SPEECH_SYNTHESIS) $(ENABLE_STREAMS_API) $(ENABLE_SUBTLE_CRYPTO) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_OTF_CONVERTER) $(ENABLE_TELEPHONE_NUMBER_DETECTION) $(ENABLE_TEMPLATE_ELEMENT) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TOUCH_EVENTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_CSS_TRAILING_WORD) $(ENABLE_USERSELECT_ALL) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_DATACUE_VALUE) $(ENABLE_VIEW_MODE_CSS_MEDIA) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_REPLAY) $(ENABLE_WEB_SOCKETS) $(ENABLE_PICTURE_SIZES) $(ENABLE_WEB_TIMING) $(ENABLE_WEBVTT_REGIONS) $(ENABLE_XHR_TIMEOUT) $(ENABLE_XSLT) $(ENABLE_FTL_JIT) $(ENABLE_LLINT_C_LOOP) $(ENABLE_SATURATED_LAYOUT_ARITHMETIC) $(ENABLE_VIDEO_PRESENTATION_MODE);
index fd4bd47..06ff7ff 100644 (file)
@@ -1,3 +1,14 @@
+2015-04-26  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement ES6 template literals
+        https://bugs.webkit.org/show_bug.cgi?id=142691
+
+        Reviewed by Darin Adler.
+
+        Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.
+
+        * Configurations/FeatureDefines.xcconfig:
+
 2015-04-26  Doug Russell  <d_russell@apple.com>
 
         AX: richer text change notifications (142719)
index efc3205..f5b45d9 100644 (file)
@@ -45,6 +45,7 @@ ENABLE_CANVAS_PATH = ENABLE_CANVAS_PATH;
 ENABLE_CANVAS_PROXY = ;
 ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING;
 ENABLE_ES6_CLASS_SYNTAX = ENABLE_ES6_CLASS_SYNTAX;
+ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX = ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX;
 ENABLE_CONTENT_FILTERING = ENABLE_CONTENT_FILTERING;
 ENABLE_CSP_NEXT = ;
 ENABLE_CSS_ANIMATIONS_LEVEL_2 = ENABLE_CSS_ANIMATIONS_LEVEL_2;
@@ -214,4 +215,4 @@ ENABLE_LLINT_C_LOOP = ;
 
 ENABLE_SATURATED_LAYOUT_ARITHMETIC = ENABLE_SATURATED_LAYOUT_ARITHMETIC;
 
-FEATURE_DEFINES = $(ENABLE_3D_TRANSFORMS) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) $(ENABLE_AVF_CAPTIONS) $(ENABLE_ATTACHMENT_ELEMENT) $(ENABLE_CACHE_PARTITIONING) $(ENABLE_CANVAS_PATH) $(ENABLE_CANVAS_PROXY) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_ES6_CLASS_SYNTAX) $(ENABLE_CONTENT_FILTERING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_ANIMATIONS_LEVEL_2) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_DEVICE_ADAPTATION) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SELECTORS_LEVEL4) $(ENABLE_CSS_SHAPES) $(ENABLE_CSS3_TEXT) $(ENABLE_CSS3_TEXT_LINE_BREAK) $(ENABLE_CURSOR_VISIBILITY) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM4_EVENTS_CONSTRUCTOR) $(ENABLE_ENCRYPTED_MEDIA) $(ENABLE_ENCRYPTED_MEDIA_V2) $(ENABLE_FILTERS_LEVEL_2) $(ENABLE_FONT_LOAD_EVENTS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GAMEPAD_DEPRECATED) $(ENABLE_GEOLOCATION) $(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) $(ENABLE_ICONDATABASE) $(ENABLE_SERVICE_CONTROLS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INDEXED_DATABASE_IN_WORKERS) $(ENABLE_INDIE_UI) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_COLOR_POPOVER) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_WIRELESS_PLAYBACK_TARGET) $(ENABLE_IOS_GESTURE_EVENTS) $(ENABLE_IOS_TEXT_AUTOSIZING) $(ENABLE_IOS_TOUCH_EVENTS) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LEGACY_VENDOR_PREFIXES) $(ENABLE_LEGACY_WEB_AUDIO) $(ENABLE_LETTERPRESS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_CONTROLS_SCRIPT) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MOUSE_CURSOR_SCALE) $(ENABLE_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NAVIGATOR_HWCONCURRENCY) $(ENABLE_NOTIFICATIONS) $(ENABLE_PDFKIT_PLUGIN) $(ENABLE_POINTER_LOCK) $(ENABLE_PROMISES) $(ENABLE_PROXIMITY_EVENTS) $(ENABLE_PUBLIC_SUFFIX_LIST) $(ENABLE_QUOTA) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_REQUEST_AUTOCOMPLETE) $(ENABLE_REMOTE_INSPECTOR) $(ENABLE_RESOLUTION_MEDIA_QUERY) $(ENABLE_RUBBER_BANDING) $(ENABLE_CSS_SCROLL_SNAP) $(ENABLE_SPEECH_SYNTHESIS) $(ENABLE_STREAMS_API) $(ENABLE_SUBTLE_CRYPTO) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_OTF_CONVERTER) $(ENABLE_TELEPHONE_NUMBER_DETECTION) $(ENABLE_TEMPLATE_ELEMENT) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TOUCH_EVENTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_CSS_TRAILING_WORD) $(ENABLE_USERSELECT_ALL) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_DATACUE_VALUE) $(ENABLE_VIEW_MODE_CSS_MEDIA) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_REPLAY) $(ENABLE_WEB_SOCKETS) $(ENABLE_PICTURE_SIZES) $(ENABLE_WEB_TIMING) $(ENABLE_WEBVTT_REGIONS) $(ENABLE_XHR_TIMEOUT) $(ENABLE_XSLT) $(ENABLE_FTL_JIT) $(ENABLE_LLINT_C_LOOP) $(ENABLE_SATURATED_LAYOUT_ARITHMETIC) $(ENABLE_VIDEO_PRESENTATION_MODE);
+FEATURE_DEFINES = $(ENABLE_3D_TRANSFORMS) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) $(ENABLE_AVF_CAPTIONS) $(ENABLE_ATTACHMENT_ELEMENT) $(ENABLE_CACHE_PARTITIONING) $(ENABLE_CANVAS_PATH) $(ENABLE_CANVAS_PROXY) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_ES6_CLASS_SYNTAX) $(ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX) $(ENABLE_CONTENT_FILTERING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_ANIMATIONS_LEVEL_2) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_DEVICE_ADAPTATION) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SELECTORS_LEVEL4) $(ENABLE_CSS_SHAPES) $(ENABLE_CSS3_TEXT) $(ENABLE_CSS3_TEXT_LINE_BREAK) $(ENABLE_CURSOR_VISIBILITY) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM4_EVENTS_CONSTRUCTOR) $(ENABLE_ENCRYPTED_MEDIA) $(ENABLE_ENCRYPTED_MEDIA_V2) $(ENABLE_FILTERS_LEVEL_2) $(ENABLE_FONT_LOAD_EVENTS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GAMEPAD_DEPRECATED) $(ENABLE_GEOLOCATION) $(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) $(ENABLE_ICONDATABASE) $(ENABLE_SERVICE_CONTROLS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INDEXED_DATABASE_IN_WORKERS) $(ENABLE_INDIE_UI) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_COLOR_POPOVER) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_WIRELESS_PLAYBACK_TARGET) $(ENABLE_IOS_GESTURE_EVENTS) $(ENABLE_IOS_TEXT_AUTOSIZING) $(ENABLE_IOS_TOUCH_EVENTS) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LEGACY_VENDOR_PREFIXES) $(ENABLE_LEGACY_WEB_AUDIO) $(ENABLE_LETTERPRESS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_CONTROLS_SCRIPT) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MOUSE_CURSOR_SCALE) $(ENABLE_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NAVIGATOR_HWCONCURRENCY) $(ENABLE_NOTIFICATIONS) $(ENABLE_PDFKIT_PLUGIN) $(ENABLE_POINTER_LOCK) $(ENABLE_PROMISES) $(ENABLE_PROXIMITY_EVENTS) $(ENABLE_PUBLIC_SUFFIX_LIST) $(ENABLE_QUOTA) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_REQUEST_AUTOCOMPLETE) $(ENABLE_REMOTE_INSPECTOR) $(ENABLE_RESOLUTION_MEDIA_QUERY) $(ENABLE_RUBBER_BANDING) $(ENABLE_CSS_SCROLL_SNAP) $(ENABLE_SPEECH_SYNTHESIS) $(ENABLE_STREAMS_API) $(ENABLE_SUBTLE_CRYPTO) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_OTF_CONVERTER) $(ENABLE_TELEPHONE_NUMBER_DETECTION) $(ENABLE_TEMPLATE_ELEMENT) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TOUCH_EVENTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_CSS_TRAILING_WORD) $(ENABLE_USERSELECT_ALL) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_DATACUE_VALUE) $(ENABLE_VIEW_MODE_CSS_MEDIA) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_REPLAY) $(ENABLE_WEB_SOCKETS) $(ENABLE_PICTURE_SIZES) $(ENABLE_WEB_TIMING) $(ENABLE_WEBVTT_REGIONS) $(ENABLE_XHR_TIMEOUT) $(ENABLE_XSLT) $(ENABLE_FTL_JIT) $(ENABLE_LLINT_C_LOOP) $(ENABLE_SATURATED_LAYOUT_ARITHMETIC) $(ENABLE_VIDEO_PRESENTATION_MODE);
index b012ab2..64d7ae9 100644 (file)
@@ -1,3 +1,14 @@
+2015-04-26  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement ES6 template literals
+        https://bugs.webkit.org/show_bug.cgi?id=142691
+
+        Reviewed by Darin Adler.
+
+        Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.
+
+        * Configurations/FeatureDefines.xcconfig:
+
 2015-04-26  Sungmann Cho  <sungmann.cho@navercorp.com>
 
         Remove PluginView::renderer().
index efc3205..f5b45d9 100644 (file)
@@ -45,6 +45,7 @@ ENABLE_CANVAS_PATH = ENABLE_CANVAS_PATH;
 ENABLE_CANVAS_PROXY = ;
 ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING;
 ENABLE_ES6_CLASS_SYNTAX = ENABLE_ES6_CLASS_SYNTAX;
+ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX = ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX;
 ENABLE_CONTENT_FILTERING = ENABLE_CONTENT_FILTERING;
 ENABLE_CSP_NEXT = ;
 ENABLE_CSS_ANIMATIONS_LEVEL_2 = ENABLE_CSS_ANIMATIONS_LEVEL_2;
@@ -214,4 +215,4 @@ ENABLE_LLINT_C_LOOP = ;
 
 ENABLE_SATURATED_LAYOUT_ARITHMETIC = ENABLE_SATURATED_LAYOUT_ARITHMETIC;
 
-FEATURE_DEFINES = $(ENABLE_3D_TRANSFORMS) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) $(ENABLE_AVF_CAPTIONS) $(ENABLE_ATTACHMENT_ELEMENT) $(ENABLE_CACHE_PARTITIONING) $(ENABLE_CANVAS_PATH) $(ENABLE_CANVAS_PROXY) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_ES6_CLASS_SYNTAX) $(ENABLE_CONTENT_FILTERING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_ANIMATIONS_LEVEL_2) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_DEVICE_ADAPTATION) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SELECTORS_LEVEL4) $(ENABLE_CSS_SHAPES) $(ENABLE_CSS3_TEXT) $(ENABLE_CSS3_TEXT_LINE_BREAK) $(ENABLE_CURSOR_VISIBILITY) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM4_EVENTS_CONSTRUCTOR) $(ENABLE_ENCRYPTED_MEDIA) $(ENABLE_ENCRYPTED_MEDIA_V2) $(ENABLE_FILTERS_LEVEL_2) $(ENABLE_FONT_LOAD_EVENTS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GAMEPAD_DEPRECATED) $(ENABLE_GEOLOCATION) $(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) $(ENABLE_ICONDATABASE) $(ENABLE_SERVICE_CONTROLS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INDEXED_DATABASE_IN_WORKERS) $(ENABLE_INDIE_UI) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_COLOR_POPOVER) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_WIRELESS_PLAYBACK_TARGET) $(ENABLE_IOS_GESTURE_EVENTS) $(ENABLE_IOS_TEXT_AUTOSIZING) $(ENABLE_IOS_TOUCH_EVENTS) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LEGACY_VENDOR_PREFIXES) $(ENABLE_LEGACY_WEB_AUDIO) $(ENABLE_LETTERPRESS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_CONTROLS_SCRIPT) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MOUSE_CURSOR_SCALE) $(ENABLE_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NAVIGATOR_HWCONCURRENCY) $(ENABLE_NOTIFICATIONS) $(ENABLE_PDFKIT_PLUGIN) $(ENABLE_POINTER_LOCK) $(ENABLE_PROMISES) $(ENABLE_PROXIMITY_EVENTS) $(ENABLE_PUBLIC_SUFFIX_LIST) $(ENABLE_QUOTA) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_REQUEST_AUTOCOMPLETE) $(ENABLE_REMOTE_INSPECTOR) $(ENABLE_RESOLUTION_MEDIA_QUERY) $(ENABLE_RUBBER_BANDING) $(ENABLE_CSS_SCROLL_SNAP) $(ENABLE_SPEECH_SYNTHESIS) $(ENABLE_STREAMS_API) $(ENABLE_SUBTLE_CRYPTO) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_OTF_CONVERTER) $(ENABLE_TELEPHONE_NUMBER_DETECTION) $(ENABLE_TEMPLATE_ELEMENT) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TOUCH_EVENTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_CSS_TRAILING_WORD) $(ENABLE_USERSELECT_ALL) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_DATACUE_VALUE) $(ENABLE_VIEW_MODE_CSS_MEDIA) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_REPLAY) $(ENABLE_WEB_SOCKETS) $(ENABLE_PICTURE_SIZES) $(ENABLE_WEB_TIMING) $(ENABLE_WEBVTT_REGIONS) $(ENABLE_XHR_TIMEOUT) $(ENABLE_XSLT) $(ENABLE_FTL_JIT) $(ENABLE_LLINT_C_LOOP) $(ENABLE_SATURATED_LAYOUT_ARITHMETIC) $(ENABLE_VIDEO_PRESENTATION_MODE);
+FEATURE_DEFINES = $(ENABLE_3D_TRANSFORMS) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) $(ENABLE_AVF_CAPTIONS) $(ENABLE_ATTACHMENT_ELEMENT) $(ENABLE_CACHE_PARTITIONING) $(ENABLE_CANVAS_PATH) $(ENABLE_CANVAS_PROXY) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_ES6_CLASS_SYNTAX) $(ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX) $(ENABLE_CONTENT_FILTERING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_ANIMATIONS_LEVEL_2) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_DEVICE_ADAPTATION) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SELECTORS_LEVEL4) $(ENABLE_CSS_SHAPES) $(ENABLE_CSS3_TEXT) $(ENABLE_CSS3_TEXT_LINE_BREAK) $(ENABLE_CURSOR_VISIBILITY) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DOM4_EVENTS_CONSTRUCTOR) $(ENABLE_ENCRYPTED_MEDIA) $(ENABLE_ENCRYPTED_MEDIA_V2) $(ENABLE_FILTERS_LEVEL_2) $(ENABLE_FONT_LOAD_EVENTS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GAMEPAD_DEPRECATED) $(ENABLE_GEOLOCATION) $(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) $(ENABLE_ICONDATABASE) $(ENABLE_SERVICE_CONTROLS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INDEXED_DATABASE_IN_WORKERS) $(ENABLE_INDIE_UI) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_COLOR_POPOVER) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_WIRELESS_PLAYBACK_TARGET) $(ENABLE_IOS_GESTURE_EVENTS) $(ENABLE_IOS_TEXT_AUTOSIZING) $(ENABLE_IOS_TOUCH_EVENTS) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LEGACY_VENDOR_PREFIXES) $(ENABLE_LEGACY_WEB_AUDIO) $(ENABLE_LETTERPRESS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_CONTROLS_SCRIPT) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MOUSE_CURSOR_SCALE) $(ENABLE_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NAVIGATOR_HWCONCURRENCY) $(ENABLE_NOTIFICATIONS) $(ENABLE_PDFKIT_PLUGIN) $(ENABLE_POINTER_LOCK) $(ENABLE_PROMISES) $(ENABLE_PROXIMITY_EVENTS) $(ENABLE_PUBLIC_SUFFIX_LIST) $(ENABLE_QUOTA) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_REQUEST_AUTOCOMPLETE) $(ENABLE_REMOTE_INSPECTOR) $(ENABLE_RESOLUTION_MEDIA_QUERY) $(ENABLE_RUBBER_BANDING) $(ENABLE_CSS_SCROLL_SNAP) $(ENABLE_SPEECH_SYNTHESIS) $(ENABLE_STREAMS_API) $(ENABLE_SUBTLE_CRYPTO) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_OTF_CONVERTER) $(ENABLE_TELEPHONE_NUMBER_DETECTION) $(ENABLE_TEMPLATE_ELEMENT) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TOUCH_EVENTS) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_CSS_TRAILING_WORD) $(ENABLE_USERSELECT_ALL) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_DATACUE_VALUE) $(ENABLE_VIEW_MODE_CSS_MEDIA) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_REPLAY) $(ENABLE_WEB_SOCKETS) $(ENABLE_PICTURE_SIZES) $(ENABLE_WEB_TIMING) $(ENABLE_WEBVTT_REGIONS) $(ENABLE_XHR_TIMEOUT) $(ENABLE_XSLT) $(ENABLE_FTL_JIT) $(ENABLE_LLINT_C_LOOP) $(ENABLE_SATURATED_LAYOUT_ARITHMETIC) $(ENABLE_VIDEO_PRESENTATION_MODE);
index 755e02f..5df3a58 100644 (file)
@@ -66,6 +66,7 @@ macro(WEBKIT_OPTION_BEGIN)
     WEBKIT_OPTION_DEFINE(ENABLE_ENCRYPTED_MEDIA "Toggle EME support" PRIVATE OFF)
     WEBKIT_OPTION_DEFINE(ENABLE_ENCRYPTED_MEDIA_V2 "Support EME v2" PRIVATE OFF)
     WEBKIT_OPTION_DEFINE(ENABLE_ES6_CLASS_SYNTAX "Toggle ES6 class syntax support" PRIVATE ON)
+    WEBKIT_OPTION_DEFINE(ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX "Toggle ES6 template literal syntax support" PRIVATE ON)
     WEBKIT_OPTION_DEFINE(ENABLE_FILTERS_LEVEL_2 "Toggle Filters Module Level 2" PRIVATE OFF)
     WEBKIT_OPTION_DEFINE(ENABLE_FONT_LOAD_EVENTS "Toggle Font Load Events support" PRIVATE OFF)
     WEBKIT_OPTION_DEFINE(ENABLE_FTPDIR "Toggle FTP directory support" PRIVATE ON)
index b0ac71a..b79aadd 100644 (file)
@@ -15,6 +15,7 @@
 #cmakedefine01 ENABLE_CANVAS_PROXY
 #cmakedefine01 ENABLE_CHANNEL_MESSAGING
 #cmakedefine01 ENABLE_ES6_CLASS_SYNTAX
+#cmakedefine01 ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX
 #cmakedefine01 ENABLE_CONTENT_FILTERING
 #cmakedefine01 ENABLE_CONTEXT_MENUS
 #cmakedefine01 ENABLE_CREDENTIAL_STORAGE
index 1684c7a..d9f4a15 100644 (file)
@@ -1,3 +1,14 @@
+2015-04-26  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement ES6 template literals
+        https://bugs.webkit.org/show_bug.cgi?id=142691
+
+        Reviewed by Darin Adler.
+
+        Add ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX compile time flag.
+
+        * Scripts/webkitperl/FeatureList.pm:
+
 2015-04-26  Gyuyoung Kim  <gyuyoung.kim@webkit.org>
 
         [CMake][EFL] Remove unnecessary include, library path in WebKitTestRunner/PlatformEfl.cmake 
index 5e7279c..bb04fc8 100644 (file)
@@ -50,6 +50,7 @@ my (
     $canvasProxySupport,
     $channelMessagingSupport,
     $classSyntax,
+    $templateLiteralSyntax,
     $cspNextSupport,
     $css3ConditionalRulesSupport,
     $css3TextSupport,
@@ -172,6 +173,9 @@ my @features = (
     { option => "class-syntax", desc => "Toggle ES6 class syntax support",
       define => "ENABLE_ES6_CLASS_SYNTAX", default => 1, value => \$classSyntax },
 
+    { option => "template-literal-syntax", desc => "Toggle ES6 template literal syntax support",
+      define => "ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX", default => 1, value => \$templateLiteralSyntax },
+
     { option => "csp-next", desc => "Toggle Content Security Policy 1.1 support",
       define => "ENABLE_CSP_NEXT", default => isGtk(), value => \$cspNextSupport },