Source/JavaScriptCore:
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Jun 2015 06:49:20 +0000 (06:49 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Jun 2015 06:49:20 +0000 (06:49 +0000)
 [ES6] Implement ES6 arrow function syntax. Parser of arrow function with execution as common function.
 https://bugs.webkit.org/show_bug.cgi?id=144955

 Reviewed by Yusuke Suzuki.

 Added support of ES6 arrow function. Changes were made according to following spec http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax. Patch does not include any arrow function specific behavior e.g. lexical bind this, arguments and etc.
This patch implements the simplest cases of arrow function declaration:
   parameters             () => 10 + 20
   parameter               x => x + 20
   parameters         (x, y) => x + y
   function with block     x => { return x*10; }

Not implemented:
   bind of the this, arguments, super and etc.
   exception in case of trying to use 'new' with arrow function

Patch by Aleksandr Skachkov <gskachkov@gmail.com> on 2015-06-26

* parser/ASTBuilder.h:
(JSC::ASTBuilder::createFunctionExpr):
(JSC::ASTBuilder::createArrowFunctionExpr):
(JSC::ASTBuilder::createGetterOrSetterProperty):
(JSC::ASTBuilder::createFuncDeclStatement):
* parser/Lexer.cpp:
(JSC::Lexer<T>::setTokenPosition):
(JSC::Lexer<T>::lex):
* parser/Lexer.h:
(JSC::Lexer::lastTokenLocation):
(JSC::Lexer::setTerminator):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::parseSourceElements):
(JSC::Parser<LexerType>::parseArrowFunctionSingleExpressionBody):
(JSC::Parser<LexerType>::parseSwitchClauses):
(JSC::Parser<LexerType>::parseSwitchDefaultClause):
(JSC::Parser<LexerType>::parseBlockStatement):
(JSC::Parser<LexerType>::parseFunctionBody):
(JSC::stringForFunctionMode):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseFunctionInfo):
(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseAssignmentExpression):
(JSC::Parser<LexerType>::parsePropertyMethod):
(JSC::Parser<LexerType>::parseGetterSetter):
(JSC::Parser<LexerType>::parseArrowFunctionExpression):
* parser/Parser.h:
(JSC::Parser::locationBeforeLastToken):
(JSC::Parser::isEndOfArrowFunction):
(JSC::Parser::isArrowFunctionParamters):
(JSC::Parser::setEndOfStatement):
* parser/ParserFunctionInfo.h:
* parser/ParserTokens.h:
* parser/SourceCode.h:
(JSC::SourceCode::subArrowExpression):
* parser/SourceProviderCacheItem.h:
(JSC::SourceProviderCacheItem::endFunctionToken):
(JSC::SourceProviderCacheItem::SourceProviderCacheItem):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createArrowFunctionExpr):
(JSC::SyntaxChecker::setFunctionNameStart):

LayoutTests:
 [ES6] Implement ES6 arrow function syntax. Parser of arrow function with execution as common function
 https://bugs.webkit.org/show_bug.cgi?id=144955

 Reviewed by Yusuke Suzuki.

 Added arrow function tests

Patch by Aleksandr Skachkov <gskachkov@gmail.com> on 2015-06-26

* js/arrowfunction-asparamter-1-expected.txt: Added.
* js/arrowfunction-asparamter-1.html: Added.
* js/arrowfunction-asparamter-2-expected.txt: Added.
* js/arrowfunction-asparamter-2.html: Added.
* js/arrowfunction-associativity-1-expected.txt: Added.
* js/arrowfunction-associativity-1.html: Added.
* js/arrowfunction-associativity-2-expected.txt: Added.
* js/arrowfunction-associativity-2.html: Added.
* js/arrowfunction-block-1-expected.txt: Added.
* js/arrowfunction-block-1.html: Added.
* js/arrowfunction-block-2-expected.txt: Added.
* js/arrowfunction-block-2.html: Added.
* js/arrowfunction-syntax-endings-expected.txt: Added.
* js/arrowfunction-syntax-endings.html: Added.
* js/arrowfunction-syntax-errors-expected.txt: Added.
* js/arrowfunction-syntax-errors.html: Added.
* js/arrowfunction-syntax-expected.txt: Added.
* js/arrowfunction-syntax.html: Added.
* js/script-tests/arrowfunction-asparamter-1.js: Added.
* js/script-tests/arrowfunction-asparamter-2.js: Added.
* js/script-tests/arrowfunction-associativity-1.js: Added.
* js/script-tests/arrowfunction-associativity-2.js: Added.
* js/script-tests/arrowfunction-block-1.js: Added.
* js/script-tests/arrowfunction-block-2.js: Added.
* js/script-tests/arrowfunction-syntax-endings.js: Added.
* js/script-tests/arrowfunction-syntax-errors.js: Added.
* js/script-tests/arrowfunction-syntax.js: Added.

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

39 files changed:
LayoutTests/ChangeLog
LayoutTests/js/arrowfunction-asparamter-1-expected.txt [new file with mode: 0644]
LayoutTests/js/arrowfunction-asparamter-1.html [new file with mode: 0644]
LayoutTests/js/arrowfunction-asparamter-2-expected.txt [new file with mode: 0644]
LayoutTests/js/arrowfunction-asparamter-2.html [new file with mode: 0644]
LayoutTests/js/arrowfunction-associativity-1-expected.txt [new file with mode: 0644]
LayoutTests/js/arrowfunction-associativity-1.html [new file with mode: 0644]
LayoutTests/js/arrowfunction-associativity-2-expected.txt [new file with mode: 0644]
LayoutTests/js/arrowfunction-associativity-2.html [new file with mode: 0644]
LayoutTests/js/arrowfunction-block-1-expected.txt [new file with mode: 0644]
LayoutTests/js/arrowfunction-block-1.html [new file with mode: 0644]
LayoutTests/js/arrowfunction-block-2-expected.txt [new file with mode: 0644]
LayoutTests/js/arrowfunction-block-2.html [new file with mode: 0644]
LayoutTests/js/arrowfunction-syntax-endings-expected.txt [new file with mode: 0644]
LayoutTests/js/arrowfunction-syntax-endings.html [new file with mode: 0644]
LayoutTests/js/arrowfunction-syntax-errors-expected.txt [new file with mode: 0644]
LayoutTests/js/arrowfunction-syntax-errors.html [new file with mode: 0644]
LayoutTests/js/arrowfunction-syntax-expected.txt [new file with mode: 0644]
LayoutTests/js/arrowfunction-syntax.html [new file with mode: 0644]
LayoutTests/js/script-tests/arrowfunction-asparamter-1.js [new file with mode: 0644]
LayoutTests/js/script-tests/arrowfunction-asparamter-2.js [new file with mode: 0644]
LayoutTests/js/script-tests/arrowfunction-associativity-1.js [new file with mode: 0644]
LayoutTests/js/script-tests/arrowfunction-associativity-2.js [new file with mode: 0644]
LayoutTests/js/script-tests/arrowfunction-block-1.js [new file with mode: 0644]
LayoutTests/js/script-tests/arrowfunction-block-2.js [new file with mode: 0644]
LayoutTests/js/script-tests/arrowfunction-syntax-endings.js [new file with mode: 0644]
LayoutTests/js/script-tests/arrowfunction-syntax-errors.js [new file with mode: 0644]
LayoutTests/js/script-tests/arrowfunction-syntax.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/Lexer.cpp
Source/JavaScriptCore/parser/Lexer.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/ParserFunctionInfo.h
Source/JavaScriptCore/parser/ParserTokens.h
Source/JavaScriptCore/parser/SourceCode.h
Source/JavaScriptCore/parser/SourceProviderCacheItem.h
Source/JavaScriptCore/parser/SyntaxChecker.h

index b05ad67..53cd4cc 100644 (file)
@@ -1,3 +1,40 @@
+2015-06-26 Aleksandr Skachkov  <gskachkov@gmail.com>
+
+         [ES6] Implement ES6 arrow function syntax. Parser of arrow function with execution as common function 
+         https://bugs.webkit.org/show_bug.cgi?id=144955
+
+         Reviewed by Yusuke Suzuki.
+
+         Added arrow function tests     
+
+        * js/arrowfunction-asparamter-1-expected.txt: Added.
+        * js/arrowfunction-asparamter-1.html: Added.
+        * js/arrowfunction-asparamter-2-expected.txt: Added.
+        * js/arrowfunction-asparamter-2.html: Added.
+        * js/arrowfunction-associativity-1-expected.txt: Added.
+        * js/arrowfunction-associativity-1.html: Added.
+        * js/arrowfunction-associativity-2-expected.txt: Added.
+        * js/arrowfunction-associativity-2.html: Added.
+        * js/arrowfunction-block-1-expected.txt: Added.
+        * js/arrowfunction-block-1.html: Added.
+        * js/arrowfunction-block-2-expected.txt: Added.
+        * js/arrowfunction-block-2.html: Added.
+        * js/arrowfunction-syntax-endings-expected.txt: Added.
+        * js/arrowfunction-syntax-endings.html: Added.
+        * js/arrowfunction-syntax-errors-expected.txt: Added.
+        * js/arrowfunction-syntax-errors.html: Added.
+        * js/arrowfunction-syntax-expected.txt: Added.
+        * js/arrowfunction-syntax.html: Added.
+        * js/script-tests/arrowfunction-asparamter-1.js: Added.
+        * js/script-tests/arrowfunction-asparamter-2.js: Added.
+        * js/script-tests/arrowfunction-associativity-1.js: Added.
+        * js/script-tests/arrowfunction-associativity-2.js: Added.
+        * js/script-tests/arrowfunction-block-1.js: Added.
+        * js/script-tests/arrowfunction-block-2.js: Added.
+        * js/script-tests/arrowfunction-syntax-endings.js: Added.
+        * js/script-tests/arrowfunction-syntax-errors.js: Added.
+        * js/script-tests/arrowfunction-syntax.js: Added.
+
 2015-06-25  Chris Fleizach  <cfleizach@apple.com>
 
         AX: improve list heuristics (presentational use versus actual lists)
diff --git a/LayoutTests/js/arrowfunction-asparamter-1-expected.txt b/LayoutTests/js/arrowfunction-asparamter-1-expected.txt
new file mode 100644 (file)
index 0000000..ff9ae39
--- /dev/null
@@ -0,0 +1,10 @@
+Tests for ES6 arrow function, passing arrow function as the paramter
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS "" + [1, 2, 3, 4].map(x => x, 32) is '1,2,3,4'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/arrowfunction-asparamter-1.html b/LayoutTests/js/arrowfunction-asparamter-1.html
new file mode 100644 (file)
index 0000000..d1daf6a
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/arrowfunction-asparamter-1.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/arrowfunction-asparamter-2-expected.txt b/LayoutTests/js/arrowfunction-asparamter-2-expected.txt
new file mode 100644 (file)
index 0000000..9acb096
--- /dev/null
@@ -0,0 +1,11 @@
+Tests for ES6 arrow function, passing arrow function as the paramter
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS f(x=>{return x * 25;}, 121) is 25*121
+PASS f2((x, y)=>{return x * y;}, 14, 12) is 14*12
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/arrowfunction-asparamter-2.html b/LayoutTests/js/arrowfunction-asparamter-2.html
new file mode 100644 (file)
index 0000000..07740db
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/arrowfunction-asparamter-2.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/arrowfunction-associativity-1-expected.txt b/LayoutTests/js/arrowfunction-associativity-1-expected.txt
new file mode 100644 (file)
index 0000000..3db2568
--- /dev/null
@@ -0,0 +1,13 @@
+Tests for ES6 arrow function nested declaration
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+af1 = af2 = af3 => af1 = af2 = af3
+PASS af1 is af2
+PASS af2 is 13
+PASS af1 is 13
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/arrowfunction-associativity-1.html b/LayoutTests/js/arrowfunction-associativity-1.html
new file mode 100644 (file)
index 0000000..8501f44
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/arrowfunction-associativity-1.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/arrowfunction-associativity-2-expected.txt b/LayoutTests/js/arrowfunction-associativity-2-expected.txt
new file mode 100644 (file)
index 0000000..e621a99
--- /dev/null
@@ -0,0 +1,11 @@
+Tests for ES6 arrow function nested declaration
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+af = a => b => a
+PASS af('ABC')('DEF') is 'ABC'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/arrowfunction-associativity-2.html b/LayoutTests/js/arrowfunction-associativity-2.html
new file mode 100644 (file)
index 0000000..924f5c1
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/arrowfunction-associativity-2.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/arrowfunction-block-1-expected.txt b/LayoutTests/js/arrowfunction-block-1-expected.txt
new file mode 100644 (file)
index 0000000..7999804
--- /dev/null
@@ -0,0 +1,13 @@
+Tests for ES6 arrow function declaration body as block
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+f = () => {}
+PASS typeof f() is 'undefined'
+g = () => ({})
+PASS typeof g() is 'object'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/arrowfunction-block-1.html b/LayoutTests/js/arrowfunction-block-1.html
new file mode 100644 (file)
index 0000000..1d66560
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/arrowfunction-block-1.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/arrowfunction-block-2-expected.txt b/LayoutTests/js/arrowfunction-block-2-expected.txt
new file mode 100644 (file)
index 0000000..01e9f10
--- /dev/null
@@ -0,0 +1,10 @@
+Tests for ES6 arrow function declaration body as block
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS typeof af(0) is "undefined"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/arrowfunction-block-2.html b/LayoutTests/js/arrowfunction-block-2.html
new file mode 100644 (file)
index 0000000..8d05de6
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/arrowfunction-block-2.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/arrowfunction-syntax-endings-expected.txt b/LayoutTests/js/arrowfunction-syntax-endings-expected.txt
new file mode 100644 (file)
index 0000000..50bd5b2
--- /dev/null
@@ -0,0 +1,14 @@
+Tests for ES6 arrow function endings
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS afEOL(12) is 13
+PASS x=>x+1 did not throw exception.
+PASS x=>x+1
+ did not throw exception.
+PASS f() is 39
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/arrowfunction-syntax-endings.html b/LayoutTests/js/arrowfunction-syntax-endings.html
new file mode 100644 (file)
index 0000000..17c6d7d
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/arrowfunction-syntax-endings.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/arrowfunction-syntax-errors-expected.txt b/LayoutTests/js/arrowfunction-syntax-errors-expected.txt
new file mode 100644 (file)
index 0000000..a7479ac
--- /dev/null
@@ -0,0 +1,123 @@
+Tests for ES6 arrow function syntax errors
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS =>{} threw exception SyntaxError: Unexpected keyword '=>'.
+PASS x=> threw exception SyntaxError: Unexpected end of script.
+PASS x=>* threw exception SyntaxError: Unexpected token '*'.
+PASS x=>/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
+PASS x=>% threw exception SyntaxError: Unexpected token '%'.
+PASS x=>+ threw exception SyntaxError: Unexpected end of script.
+PASS x=>- threw exception SyntaxError: Unexpected end of script.
+PASS x=><< threw exception SyntaxError: Unexpected token '<<'.
+PASS x=>>> threw exception SyntaxError: Unexpected token '>>'.
+PASS x=>>>> threw exception SyntaxError: Unexpected token '>>>'.
+PASS x=>< threw exception SyntaxError: Unexpected token '<'.
+PASS x=>> threw exception SyntaxError: Unexpected token '>'.
+PASS x=><= threw exception SyntaxError: Unexpected token '<='.
+PASS x=>>= threw exception SyntaxError: Unexpected token '>='.
+PASS x=>instanceof threw exception SyntaxError: Unexpected keyword 'instanceof'.
+PASS x=>in threw exception SyntaxError: Unexpected keyword 'in'.
+PASS x=>== threw exception SyntaxError: Unexpected token '=='.
+PASS x=>!= threw exception SyntaxError: Unexpected token '!='.
+PASS x=>=== threw exception SyntaxError: Unexpected token '==='.
+PASS x=>!== threw exception SyntaxError: Unexpected token '!=='.
+PASS x=>& threw exception SyntaxError: Unexpected token '&'.
+PASS x=>^ threw exception SyntaxError: Unexpected token '^'.
+PASS x=>| threw exception SyntaxError: Unexpected token '|'.
+PASS x=>&& threw exception SyntaxError: Unexpected token '&&'.
+PASS x=>|| threw exception SyntaxError: Unexpected token '||'.
+PASS x=>; threw exception SyntaxError: Unexpected token ';'.
+PASS x=>, threw exception SyntaxError: Unexpected token ','.
+PASS x=>{ threw exception SyntaxError: Unexpected end of script.
+PASS x=>{* threw exception SyntaxError: Unexpected token '*'.
+PASS x=>{/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
+PASS x=>{% threw exception SyntaxError: Unexpected token '%'.
+PASS x=>{+ threw exception SyntaxError: Unexpected end of script.
+PASS x=>{- threw exception SyntaxError: Unexpected end of script.
+PASS x=>{<< threw exception SyntaxError: Unexpected token '<<'.
+PASS x=>{>> threw exception SyntaxError: Unexpected token '>>'.
+PASS x=>{>>> threw exception SyntaxError: Unexpected token '>>>'.
+PASS x=>{< threw exception SyntaxError: Unexpected token '<'.
+PASS x=>{> threw exception SyntaxError: Unexpected token '>'.
+PASS x=>{<= threw exception SyntaxError: Unexpected token '<='.
+PASS x=>{>= threw exception SyntaxError: Unexpected token '>='.
+PASS x=>{instanceof threw exception SyntaxError: Unexpected keyword 'instanceof'.
+PASS x=>{in threw exception SyntaxError: Unexpected keyword 'in'.
+PASS x=>{== threw exception SyntaxError: Unexpected token '=='.
+PASS x=>{!= threw exception SyntaxError: Unexpected token '!='.
+PASS x=>{=== threw exception SyntaxError: Unexpected token '==='.
+PASS x=>{!== threw exception SyntaxError: Unexpected token '!=='.
+PASS x=>{& threw exception SyntaxError: Unexpected token '&'.
+PASS x=>{^ threw exception SyntaxError: Unexpected token '^'.
+PASS x=>{| threw exception SyntaxError: Unexpected token '|'.
+PASS x=>{&& threw exception SyntaxError: Unexpected token '&&'.
+PASS x=>{|| threw exception SyntaxError: Unexpected token '||'.
+PASS x=>{; threw exception SyntaxError: Unexpected end of script.
+PASS x=>{, threw exception SyntaxError: Unexpected token ','.
+PASS x=>} threw exception SyntaxError: Unexpected token '}'.
+PASS var y = x=> threw exception SyntaxError: Unexpected end of script.
+PASS var y = x=>* threw exception SyntaxError: Unexpected token '*'.
+PASS var y = x=>/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
+PASS var y = x=>% threw exception SyntaxError: Unexpected token '%'.
+PASS var y = x=>+ threw exception SyntaxError: Unexpected end of script.
+PASS var y = x=>- threw exception SyntaxError: Unexpected end of script.
+PASS var y = x=><< threw exception SyntaxError: Unexpected token '<<'.
+PASS var y = x=>>> threw exception SyntaxError: Unexpected token '>>'.
+PASS var y = x=>>>> threw exception SyntaxError: Unexpected token '>>>'.
+PASS var y = x=>< threw exception SyntaxError: Unexpected token '<'.
+PASS var y = x=>> threw exception SyntaxError: Unexpected token '>'.
+PASS var y = x=><= threw exception SyntaxError: Unexpected token '<='.
+PASS var y = x=>>= threw exception SyntaxError: Unexpected token '>='.
+PASS var y = x=>instanceof threw exception SyntaxError: Unexpected keyword 'instanceof'.
+PASS var y = x=>in threw exception SyntaxError: Unexpected keyword 'in'.
+PASS var y = x=>== threw exception SyntaxError: Unexpected token '=='.
+PASS var y = x=>!= threw exception SyntaxError: Unexpected token '!='.
+PASS var y = x=>=== threw exception SyntaxError: Unexpected token '==='.
+PASS var y = x=>!== threw exception SyntaxError: Unexpected token '!=='.
+PASS var y = x=>& threw exception SyntaxError: Unexpected token '&'.
+PASS var y = x=>^ threw exception SyntaxError: Unexpected token '^'.
+PASS var y = x=>| threw exception SyntaxError: Unexpected token '|'.
+PASS var y = x=>&& threw exception SyntaxError: Unexpected token '&&'.
+PASS var y = x=>|| threw exception SyntaxError: Unexpected token '||'.
+PASS var y = x=>; threw exception SyntaxError: Unexpected token ';'.
+PASS var y = x=>, threw exception SyntaxError: Unexpected token ','.
+PASS var y = x=>{ threw exception SyntaxError: Unexpected end of script.
+PASS var y = x=>{* threw exception SyntaxError: Unexpected token '*'.
+PASS var y = x=>{/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
+PASS var y = x=>{% threw exception SyntaxError: Unexpected token '%'.
+PASS var y = x=>{+ threw exception SyntaxError: Unexpected end of script.
+PASS var y = x=>{- threw exception SyntaxError: Unexpected end of script.
+PASS var y = x=>{<< threw exception SyntaxError: Unexpected token '<<'.
+PASS var y = x=>{>> threw exception SyntaxError: Unexpected token '>>'.
+PASS var y = x=>{>>> threw exception SyntaxError: Unexpected token '>>>'.
+PASS var y = x=>{< threw exception SyntaxError: Unexpected token '<'.
+PASS var y = x=>{> threw exception SyntaxError: Unexpected token '>'.
+PASS var y = x=>{<= threw exception SyntaxError: Unexpected token '<='.
+PASS var y = x=>{>= threw exception SyntaxError: Unexpected token '>='.
+PASS var y = x=>{instanceof threw exception SyntaxError: Unexpected keyword 'instanceof'.
+PASS var y = x=>{in threw exception SyntaxError: Unexpected keyword 'in'.
+PASS var y = x=>{== threw exception SyntaxError: Unexpected token '=='.
+PASS var y = x=>{!= threw exception SyntaxError: Unexpected token '!='.
+PASS var y = x=>{=== threw exception SyntaxError: Unexpected token '==='.
+PASS var y = x=>{!== threw exception SyntaxError: Unexpected token '!=='.
+PASS var y = x=>{& threw exception SyntaxError: Unexpected token '&'.
+PASS var y = x=>{^ threw exception SyntaxError: Unexpected token '^'.
+PASS var y = x=>{| threw exception SyntaxError: Unexpected token '|'.
+PASS var y = x=>{&& threw exception SyntaxError: Unexpected token '&&'.
+PASS var y = x=>{|| threw exception SyntaxError: Unexpected token '||'.
+PASS var y = x=>{; threw exception SyntaxError: Unexpected end of script.
+PASS var y = x=>{, threw exception SyntaxError: Unexpected token ','.
+PASS var y = x=>} threw exception SyntaxError: Unexpected token '}'.
+PASS var t = x=>x+1; =>{} threw exception SyntaxError: Unexpected keyword '=>'.
+PASS [=>x+1] threw exception SyntaxError: Unexpected keyword '=>'.
+PASS [x=>x+1, =>x+1] threw exception SyntaxError: Unexpected keyword '=>'.
+PASS var f=>x+1; threw exception SyntaxError: Unexpected keyword '=>'. Expected ';' after var declaration..
+PASS var x, y=>y+1; threw exception SyntaxError: Unexpected keyword '=>'. Expected ';' after var declaration..
+PASS debug(=>x+1) threw exception SyntaxError: Unexpected keyword '=>'.
+PASS debug("xyz", =>x+1) threw exception SyntaxError: Unexpected keyword '=>'.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/arrowfunction-syntax-errors.html b/LayoutTests/js/arrowfunction-syntax-errors.html
new file mode 100644 (file)
index 0000000..3744212
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/arrowfunction-syntax-errors.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/arrowfunction-syntax-expected.txt b/LayoutTests/js/arrowfunction-syntax-expected.txt
new file mode 100644 (file)
index 0000000..ae688c7
--- /dev/null
@@ -0,0 +1,46 @@
+Tests for ES6 arrow function calling
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS af0(10) is 11
+PASS af1(10) is 20
+PASS af2(1212) is 1000
+PASS af2_1(121) is a
+PASS af3(11,12) is 23
+PASS afwrapper(x => 1234) is 1234
+PASS afwrapper(x => 1234, 2345) is 1234
+PASS afwrapper(x => 121 + 232) is 353
+PASS afwrapper(x => 123 + 321, 9999) is 444
+PASS afwrapper(x => x + 12, 21) is 33
+PASS afwrapper((x) => x + 21, 32) is 53
+PASS afwrapper(() => 100) is 100
+PASS afwrapper(() => ext_value) is 121
+PASS afwrapper(() => ext_value * 10) is 1210
+PASS afwrapper((x) => ext_value * x, 30) is ext_value * 30
+PASS afwrapper(() => 100, 11) is 100
+PASS afwrapper(() => 100 + 10) is 110
+PASS afwrapper(() => 100 + 11, 12) is 111
+PASS arrowFunction4(1011) is 1012
+PASS xyz1 is 10101
+PASS afwrapper2((x, y) => x + y, 12 ,43) is 55
+PASS afArr0[0](10) is 100
+PASS afArr1[0](10) is 11
+PASS afArr1[1](11) is 13
+PASS afArr2[0](11) is 12
+PASS afArr2[1](11) is 13
+PASS afArr3[0](11) is 101
+PASS afArr3[1](11) is 12323
+PASS afObj.func(11) is 23
+PASS afBlock0(11) is 1000
+PASS afBlock1(11) is 1100
+PASS afBlock2(11) is 2200
+PASS afBlock3(11, 12222) is 134442
+PASS (function funcSelfExecAE1(value) { var f = x => x+1; return f(value);})(123); is 124
+PASS (function funcSelfExecAE2(value) { var f = x => { x++; return x + 1; }; return f(value);})(123); is 125
+PASS (function funcSelfExecAE3(value) { var f = (x) => { x++; return x + 1; }; return f(value);})(123); is 125
+PASS (function funcSelfExecAE4(value) { var f = (x, y) => { x++; return x + y; }; return f(value, value * 2);})(123); is 370
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/arrowfunction-syntax.html b/LayoutTests/js/arrowfunction-syntax.html
new file mode 100644 (file)
index 0000000..ac632cb
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/arrowfunction-syntax.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/script-tests/arrowfunction-asparamter-1.js b/LayoutTests/js/script-tests/arrowfunction-asparamter-1.js
new file mode 100644 (file)
index 0000000..19e0a50
--- /dev/null
@@ -0,0 +1,5 @@
+description('Tests for ES6 arrow function, passing arrow function as the paramter');
+
+shouldBe('"" + [1, 2, 3, 4].map(x => x, 32)', "'1,2,3,4'");
+
+var successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/arrowfunction-asparamter-2.js b/LayoutTests/js/script-tests/arrowfunction-asparamter-2.js
new file mode 100644 (file)
index 0000000..354567b
--- /dev/null
@@ -0,0 +1,9 @@
+description('Tests for ES6 arrow function, passing arrow function as the paramter');
+
+var f = function (cl, paramter) { return cl(paramter); };
+var f2 = function (cl, paramter1, paramter2) { return cl(paramter1, paramter2); };
+
+shouldBe('f(x=>{return x * 25;}, 121)', '25*121' );
+shouldBe('f2((x, y)=>{return x * y;}, 14, 12)', '14*12');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/arrowfunction-associativity-1.js b/LayoutTests/js/script-tests/arrowfunction-associativity-1.js
new file mode 100644 (file)
index 0000000..38ee61b
--- /dev/null
@@ -0,0 +1,11 @@
+description('Tests for ES6 arrow function nested declaration');
+
+var af1, af2, af3;
+af1 = af2 = af3 => af1 = af2 = af3;
+debug('af1 = af2 = af3 => af1 = af2 = af3')
+shouldBe('af1', 'af2');
+af1(13);
+shouldBe('af2', '13');
+shouldBe('af1', '13');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/arrowfunction-associativity-2.js b/LayoutTests/js/script-tests/arrowfunction-associativity-2.js
new file mode 100644 (file)
index 0000000..03d16a4
--- /dev/null
@@ -0,0 +1,8 @@
+description('Tests for ES6 arrow function nested declaration');
+
+debug("af = a => b => a")
+var af = a => b => a;
+
+shouldBe("af('ABC')('DEF')", "'ABC'");
+
+var successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/arrowfunction-block-1.js b/LayoutTests/js/script-tests/arrowfunction-block-1.js
new file mode 100644 (file)
index 0000000..ee7c12b
--- /dev/null
@@ -0,0 +1,11 @@
+description('Tests for ES6 arrow function declaration body as block');
+
+debug('f = () => {}');
+var f = () => {};
+shouldBe("typeof f()", "'undefined'");
+
+debug('g = () => ({})');
+var g = () => ({});
+shouldBe("typeof g()", "'object'");
+
+var successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/arrowfunction-block-2.js b/LayoutTests/js/script-tests/arrowfunction-block-2.js
new file mode 100644 (file)
index 0000000..7535ed3
--- /dev/null
@@ -0,0 +1,7 @@
+description('Tests for ES6 arrow function declaration body as block');
+
+var af = a => { a + 1; };
+
+shouldBe("typeof af(0)", '"undefined"');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/arrowfunction-syntax-endings.js b/LayoutTests/js/script-tests/arrowfunction-syntax-endings.js
new file mode 100644 (file)
index 0000000..74935e8
--- /dev/null
@@ -0,0 +1,35 @@
+description("Tests for ES6 arrow function endings");
+
+var afEOL = x=>x+1
+result = afEOL(12);
+
+shouldBe('afEOL(12)', '13');
+
+shouldNotThrow('x=>x+1');
+
+var afEOLTxt = 'x=>x+1' + String.fromCharCode(10);
+shouldNotThrow(afEOLTxt);
+
+var f = function () {
+  var result = 0;
+  var afEOF;
+
+
+  afEOF = x => x*10000 + x*1000 - x*10000 - x*1000 + x
+
+
+
+  result = afEOF(12);
+
+
+  result = result + afEOF(13);
+
+
+  result = result + afEOF(14);
+
+  return result;
+};
+
+shouldBe('f()', '39');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/arrowfunction-syntax-errors.js b/LayoutTests/js/script-tests/arrowfunction-syntax-errors.js
new file mode 100644 (file)
index 0000000..14d1b62
--- /dev/null
@@ -0,0 +1,37 @@
+description("Tests for ES6 arrow function syntax errors");
+
+shouldThrow('=>{}');
+
+function checkStatement(statement) {
+  var unexpectedSymbols = [ "",
+      "*", "/", "%" ,  "+", "-" ,
+       "<<", ">>", ">>>" ,
+       "<", ">", "<=", ">=", "instanceof", "in" ,
+       "==", "!=", "===", "!==",
+       "&" ,  "^" ,  "|" ,
+       "&&" ,  "||", ";" , ","
+  ];
+
+  for (var i = 0; i < unexpectedSymbols.length; i++) {
+    shouldThrow(statement + unexpectedSymbols[i]);
+  }
+}
+
+checkStatement('x=>');
+checkStatement('x=>{');
+shouldThrow('x=>}');
+
+checkStatement('var y = x=>');
+checkStatement('var y = x=>{');
+shouldThrow('var y = x=>}');
+
+
+shouldThrow('var t = x=>x+1; =>{}');
+shouldThrow('[=>x+1]');
+shouldThrow('[x=>x+1, =>x+1]');
+shouldThrow('var f=>x+1;');
+shouldThrow('var x, y=>y+1;');
+shouldThrow('debug(=>x+1)');
+shouldThrow('debug("xyz", =>x+1)');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/js/script-tests/arrowfunction-syntax.js b/LayoutTests/js/script-tests/arrowfunction-syntax.js
new file mode 100644 (file)
index 0000000..42ac35b
--- /dev/null
@@ -0,0 +1,82 @@
+description("Tests for ES6 arrow function calling");
+
+var af0 = v => v + 1;
+shouldBe('af0(10)', '11');
+
+var af1 = (v) => v * 2;
+shouldBe('af1(10)', '20');
+
+var af2 = () => 1000;
+shouldBe('af2(1212)', '1000' );
+
+var a = 151;
+var af2_1 = () => a;
+shouldBe('af2_1(121)', 'a');
+
+var af3 = (v, x) => v + x;
+shouldBe('af3(11,12)', '23');
+
+var afwrapper = function (cl, paramter) { return cl(paramter); };
+
+shouldBe('afwrapper(x => 1234)', '1234');
+shouldBe('afwrapper(x => 1234, 2345)', '1234' );
+shouldBe('afwrapper(x => 121 + 232)', '353' );
+shouldBe('afwrapper(x => 123 + 321, 9999)', '444' );
+shouldBe('afwrapper(x => x + 12, 21)', '33' );
+shouldBe('afwrapper((x) => x + 21, 32)', '53');
+shouldBe('afwrapper(() => 100)', '100');
+
+var ext_value = 121;
+shouldBe('afwrapper(() => ext_value)', '121');
+shouldBe('afwrapper(() => ext_value * 10)', '1210');
+shouldBe('afwrapper((x) => ext_value * x, 30)', 'ext_value * 30');
+shouldBe('afwrapper(() => 100, 11)', '100' );
+shouldBe('afwrapper(() => 100 + 10)', '110');
+shouldBe('afwrapper(() => 100 + 11, 12)', '111' );
+
+var arrowFunction4 = v => v + 1, xyz1 = 10101;
+shouldBe('arrowFunction4(1011)', '1012');
+shouldBe('xyz1', '10101');
+
+var afwrapper2 = function (cl, paramter1, paramter2) { return cl(paramter1, paramter2); };
+shouldBe('afwrapper2((x, y) => x + y, 12 ,43)', '55');
+
+var afArr0 = [v => v * 10];
+shouldBe('afArr0[0](10)', '100');
+
+var afArr1 = [v => v + 1, v => v + 2];
+shouldBe('afArr1[0](10)', '11');
+shouldBe('afArr1[1](11)', '13');
+
+var afArr2 = [(v) => v + 1, (v) => v + 2];
+shouldBe('afArr2[0](11)', '12');
+shouldBe('afArr2[1](11)', '13');
+
+var afArr3 = [() => 101, () => 12323];
+shouldBe('afArr3[0](11)', '101');
+shouldBe('afArr3[1](11)', '12323');
+
+var afObj = {func : y => y + 12};
+shouldBe('afObj.func(11)', '23');
+
+var afBlock0 = () => { return 1000; };
+shouldBe('afBlock0(11)', '1000');
+
+var afBlock1 = v => { var intval = 100; return v * intval; };
+shouldBe('afBlock1(11)', '1100');
+
+var afBlock2 = (v) => { var int = 200; return v * int; };
+shouldBe('afBlock2(11)', '2200');
+
+var afBlock3 = (v, x) => { var result = x * v; return result; };
+shouldBe('afBlock3(11, 12222)', '134442');
+
+shouldBe('(function funcSelfExecAE1(value) { var f = x => x+1; return f(value);})(123);', '124');
+
+shouldBe('(function funcSelfExecAE2(value) { var f = x => { x++; return x + 1; }; return f(value);})(123);', '125');
+
+shouldBe('(function funcSelfExecAE3(value) { var f = (x) => { x++; return x + 1; }; return f(value);})(123);', '125');
+
+shouldBe('(function funcSelfExecAE4(value) { var f = (x, y) => { x++; return x + y; }; return f(value, value * 2);})(123);', '370');
+
+var successfullyParsed = true;
index 7389456..5becb2a 100644 (file)
@@ -1,3 +1,65 @@
+2015-06-26 Aleksandr Skachkov  <gskachkov@gmail.com>
+
+         [ES6] Implement ES6 arrow function syntax. Parser of arrow function with execution as common function. 
+         https://bugs.webkit.org/show_bug.cgi?id=144955
+
+         Reviewed by Yusuke Suzuki.
+
+         Added support of ES6 arrow function. Changes were made according to following spec http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax. Patch does not include any arrow function specific behavior e.g. lexical bind this, arguments and etc.     
+        This patch implements the simplest cases of arrow function declaration:
+           parameters             () => 10 + 20
+           parameter               x => x + 20
+           parameters         (x, y) => x + y
+           function with block     x => { return x*10; }
+
+        Not implemented:
+           bind of the this, arguments, super and etc.
+           exception in case of trying to use 'new' with arrow function
+
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createFunctionExpr):
+        (JSC::ASTBuilder::createArrowFunctionExpr):
+        (JSC::ASTBuilder::createGetterOrSetterProperty):
+        (JSC::ASTBuilder::createFuncDeclStatement):
+        * parser/Lexer.cpp:
+        (JSC::Lexer<T>::setTokenPosition):
+        (JSC::Lexer<T>::lex):
+        * parser/Lexer.h:
+        (JSC::Lexer::lastTokenLocation):
+        (JSC::Lexer::setTerminator):
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseInner):
+        (JSC::Parser<LexerType>::parseSourceElements):
+        (JSC::Parser<LexerType>::parseArrowFunctionSingleExpressionBody):
+        (JSC::Parser<LexerType>::parseSwitchClauses):
+        (JSC::Parser<LexerType>::parseSwitchDefaultClause):
+        (JSC::Parser<LexerType>::parseBlockStatement):
+        (JSC::Parser<LexerType>::parseFunctionBody):
+        (JSC::stringForFunctionMode):
+        (JSC::Parser<LexerType>::parseFunctionParameters):
+        (JSC::Parser<LexerType>::parseFunctionInfo):
+        (JSC::Parser<LexerType>::parseFunctionDeclaration):
+        (JSC::Parser<LexerType>::parseClass):
+        (JSC::Parser<LexerType>::parseAssignmentExpression):
+        (JSC::Parser<LexerType>::parsePropertyMethod):
+        (JSC::Parser<LexerType>::parseGetterSetter):
+        (JSC::Parser<LexerType>::parseArrowFunctionExpression):
+        * parser/Parser.h:
+        (JSC::Parser::locationBeforeLastToken):
+        (JSC::Parser::isEndOfArrowFunction):
+        (JSC::Parser::isArrowFunctionParamters):
+        (JSC::Parser::setEndOfStatement):
+        * parser/ParserFunctionInfo.h:
+        * parser/ParserTokens.h:
+        * parser/SourceCode.h:
+        (JSC::SourceCode::subArrowExpression):
+        * parser/SourceProviderCacheItem.h:
+        (JSC::SourceProviderCacheItem::endFunctionToken):
+        (JSC::SourceProviderCacheItem::SourceProviderCacheItem):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createArrowFunctionExpr):
+        (JSC::SyntaxChecker::setFunctionNameStart):
+
 2015-06-25  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [ES6] Support rest element in destructuring assignments
index 4715b86..015b454 100644 (file)
@@ -347,7 +347,7 @@ public:
     ExpressionNode* createFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& info)
     {
         FuncExprNode* result = new (m_parserArena) FuncExprNode(location, *info.name, info.body,
-            m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters);
+            m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters);
         info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
         return result;
     }
@@ -364,13 +364,26 @@ public:
             inStrictContext, constructorKind);
     }
 
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    ExpressionNode* createArrowFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& info)
+    {
+        SourceCode source = info.functionBodyType == ArrowFunctionBodyExpression
+            ? m_sourceCode->subArrowExpression(info.arrowFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn)
+            : m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn);
+
+        FuncExprNode* result = new (m_parserArena) FuncExprNode(location, *info.name, info.body, source, info.parameters);
+        info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
+        return result;
+    }
+#endif
+
     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool,
         const Identifier* name, const ParserFunctionInfo<ASTBuilder>& info, SuperBinding superBinding)
     {
         ASSERT(name);
         info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
         info.body->setInferredName(*name);
-        SourceCode source = m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn);
+        SourceCode source = m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn);
         FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, info.body, source, info.parameters);
         return new (m_parserArena) PropertyNode(*name, funcExpr, type, PropertyNode::Unknown, superBinding);
     }
@@ -380,7 +393,7 @@ public:
     {
         info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
         const Identifier& ident = parserArena.identifierArena().makeNumericIdentifier(vm, name);
-        SourceCode source = m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn);
+        SourceCode source = m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn);
         FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, vm->propertyNames->nullIdentifier, info.body, source, info.parameters);
         return new (m_parserArena) PropertyNode(ident, funcExpr, type, PropertyNode::Unknown, superBinding);
     }
@@ -417,7 +430,7 @@ public:
     StatementNode* createFuncDeclStatement(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& info)
     {
         FuncDeclNode* decl = new (m_parserArena) FuncDeclNode(location, *info.name, info.body,
-            m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters);
+            m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters);
         if (*info.name == m_vm->propertyNames->arguments)
             usesArguments();
         m_scope.m_funcDeclarations.append(decl->body());
index 5c0c3f9..53aa9b0 100644 (file)
@@ -1715,11 +1715,25 @@ bool Lexer<T>::nextTokenIsColon()
     return code < m_codeEnd && *code == ':';
 }
 
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+template <typename T>
+void Lexer<T>::setTokenPosition(JSToken* tokenRecord)
+{
+    JSTokenData* tokenData = &tokenRecord->m_data;
+    tokenData->line = lineNumber();
+    tokenData->offset = currentOffset();
+    tokenData->lineStartOffset = currentLineStartOffset();
+    ASSERT(tokenData->offset >= tokenData->lineStartOffset);
+}
+#endif
+
 template <typename T>
 JSTokenType Lexer<T>::lex(JSToken* tokenRecord, unsigned lexerFlags, bool strictMode)
 {
     JSTokenData* tokenData = &tokenRecord->m_data;
     JSTokenLocation* tokenLocation = &tokenRecord->m_location;
+    m_lastTockenLocation = JSTokenLocation(tokenRecord->m_location);
+    
     ASSERT(!m_error);
     ASSERT(m_buffer8.isEmpty());
     ASSERT(m_buffer16.isEmpty());
@@ -1778,7 +1792,19 @@ start:
         }
         token = GT;
         break;
-    case CharacterEqual:
+    case CharacterEqual: {
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+        if (peek(1) == '>') {
+            token = ARROWFUNCTION;
+            tokenData->line = lineNumber();
+            tokenData->offset = currentOffset();
+            tokenData->lineStartOffset = currentLineStartOffset();
+            ASSERT(tokenData->offset >= tokenData->lineStartOffset);
+            shift();
+            shift();
+            break;
+        }
+#endif
         shift();
         if (m_current == '=') {
             shift();
@@ -1792,6 +1818,7 @@ start:
         }
         token = EQUAL;
         break;
+    }
     case CharacterLess:
         shift();
         if (m_current == '!' && peek(1) == '-' && peek(2) == '-') {
index cab7d52..b142c48 100644 (file)
@@ -87,6 +87,9 @@ public:
     void setIsReparsing() { m_isReparsing = true; }
     bool isReparsing() const { return m_isReparsing; }
 
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    void setTokenPosition(JSToken* tokenRecord);
+#endif
     JSTokenType lex(JSToken*, unsigned, bool strictMode);
     bool nextTokenIsColon();
     int lineNumber() const { return m_lineNumber; }
@@ -97,6 +100,7 @@ public:
         return JSTextPosition(m_lineNumber, currentOffset(), currentLineStartOffset());
     }
     JSTextPosition positionBeforeLastNewline() const { return m_positionBeforeLastNewline; }
+    JSTokenLocation lastTokenLocation() const { return m_lastTockenLocation; }
     void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
     int lastLineNumber() const { return m_lastLineNumber; }
     bool prevTerminator() const { return m_terminator; }
@@ -131,6 +135,10 @@ public:
     {
         m_lineNumber = line;
     }
+    void setTerminator(bool terminator)
+    {
+        m_terminator = terminator;
+    }
 
     SourceProvider* sourceProvider() const { return m_source->provider(); }
 
@@ -215,6 +223,7 @@ private:
     const T* m_codeStartPlusOffset;
     const T* m_lineStart;
     JSTextPosition m_positionBeforeLastNewline;
+    JSTokenLocation m_lastTockenLocation;
     bool m_isReparsing;
     bool m_atLineStart;
     bool m_error;
index 468eb39..c447112 100644 (file)
@@ -264,7 +264,7 @@ String Parser<LexerType>::parseInner()
     if (m_lexer->isReparsing())
         m_statementDepth--;
     ScopeRef scope = currentScope();
-    SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode);
+    SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode, StandardFunctionParseType);
     if (!sourceElements || !consume(EOFTOK)) {
         if (hasError())
             parseError = m_errorMessage;
@@ -343,7 +343,7 @@ bool Parser<LexerType>::allowAutomaticSemicolon()
 }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
+template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode, FunctionParseType functionParseType)
 {
     const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
     TreeSourceElements sourceElements = context.createSourceElements();
@@ -352,6 +352,21 @@ template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceEl
     unsigned directiveLiteralLength = 0;
     auto savePoint = createSavePoint();
     bool hasSetStrict = false;
+    
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    if (match(ARROWFUNCTION)) {
+        TreeStatement arrowfunctionStatement = parseArrowFunctionSingleExpressionBody(context, functionParseType);
+            
+        if (arrowfunctionStatement) {
+            context.setEndOffset(arrowfunctionStatement, m_lastTokenEndPosition.offset);
+            context.appendStatement(sourceElements, arrowfunctionStatement);
+        }
+        
+        propagateError();
+        return sourceElements;
+    }
+#endif
+    
     while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) {
         if (mode == CheckForStrictMode && !seenNonDirective) {
             if (directive) {
@@ -583,6 +598,42 @@ template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::create
     return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition);
 }
 
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseArrowFunctionSingleExpressionBody(TreeBuilder& context, FunctionParseType parseType)
+{
+    ASSERT(match(ARROWFUNCTION));
+
+    // When reparsing phase, parseType becomes StandardFunctionParseType even if the function is arrow function.
+    // This condition considers the following situations.
+    // (1): If we are in the reparsing phase, this arrow function is already parsed once, so there is no syntax error.
+    // (2): But if we are not in the reparsing phase, we should check this function is called in the context of the arrow function.
+    if (!m_lexer->isReparsing() && parseType != ArrowFunctionParseType)
+        failDueToUnexpectedToken();
+    
+    JSTokenLocation location(tokenLocation());
+    JSTextPosition start = tokenStartPosition();
+    JSTextPosition end = tokenEndPosition();
+
+    next();
+
+    failIfStackOverflow();
+    TreeExpression expr = parseAssignmentExpression(context);
+    failIfFalse(expr, "Cannot parse the arrow function expression");
+    
+    context.setEndOffset(expr, m_lastTokenEndPosition.offset);
+
+    failIfFalse(isEndOfArrowFunction(), "Expected a ';', ']', '}', ')', ',', line terminator or EOF following a arrow function statement");
+
+    end = tokenEndPosition();
+    
+    if (!m_lexer->prevTerminator())
+        setEndOfStatement();
+
+    return context.createReturnStatement(location, expr, start, end);
+}
+#endif
+
 template <typename LexerType>
 template <class TreeBuilder> TreeDeconstructionPattern Parser<LexerType>::tryParseDeconstructionPatternExpression(TreeBuilder& context)
 {
@@ -1065,7 +1116,7 @@ template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClause
     TreeExpression condition = parseExpression(context);
     failIfFalse(condition, "Cannot parse switch clause");
     consumeOrFail(COLON, "Expected a ':' after switch clause expression");
-    TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
+    TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
     failIfFalse(statements, "Cannot parse the body of a switch clause");
     TreeClause clause = context.createClause(condition, statements);
     context.setStartOffset(clause, startOffset);
@@ -1078,7 +1129,7 @@ template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClause
         TreeExpression condition = parseExpression(context);
         failIfFalse(condition, "Cannot parse switch case expression");
         consumeOrFail(COLON, "Expected a ':' after switch clause expression");
-        TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
+        TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
         failIfFalse(statements, "Cannot parse the body of a switch clause");
         clause = context.createClause(condition, statements);
         context.setStartOffset(clause, startOffset);
@@ -1095,7 +1146,7 @@ template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultCla
     unsigned startOffset = tokenStart();
     next();
     consumeOrFail(COLON, "Expected a ':' after switch default clause");
-    TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
+    TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
     failIfFalse(statements, "Cannot parse the body of a switch default clause");
     TreeClause result = context.createClause(0, statements);
     context.setStartOffset(result, startOffset);
@@ -1180,7 +1231,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatemen
         context.setEndOffset(result, endOffset);
         return result;
     }
-    TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
+    TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
     failIfFalse(subtree, "Cannot parse the body of the block statement");
     matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
     int endOffset = m_token.m_data.offset;
@@ -1201,6 +1252,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(Tre
     failIfStackOverflow();
     TreeStatement result = 0;
     bool shouldSetEndOffset = true;
+
     switch (m_token.m_type) {
     case OPENBRACE:
         result = parseBlockStatement(context);
@@ -1310,20 +1362,27 @@ template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFor
 template <typename LexerType>
 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
     TreeBuilder& context, int functionKeywordStart, int functionNameStart, 
-    int parametersStart, ConstructorKind constructorKind)
+    int parametersStart, ConstructorKind constructorKind, FunctionParseType parseType)
 {
     JSTokenLocation startLocation(tokenLocation());
     unsigned startColumn = tokenColumn();
-    next();
 
-    if (match(CLOSEBRACE)) {
-        unsigned endColumn = tokenColumn();
-        return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
+    if (parseType == StandardFunctionParseType) {
+        next();
+        if (match(CLOSEBRACE)) {
+            unsigned endColumn = tokenColumn();
+            return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
+        }
     }
+
     DepthManager statementDepth(&m_statementDepth);
     m_statementDepth = 0;
     typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
-    failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode), "Cannot parse body of this function");
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, parseType), parseType == StandardFunctionParseType ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
+#else
+    failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, StandardFunctionParseType), "Cannot parse body of this function");
+#endif
     unsigned endColumn = tokenColumn();
     return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
 }
@@ -1339,27 +1398,46 @@ static const char* stringForFunctionMode(FunctionParseMode mode)
         return "function";
     case MethodMode:
         return "method";
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    case ArrowFunctionMode:
+        return "arrow function";
+#endif
     }
     RELEASE_ASSERT_NOT_REACHED();
     return nullptr;
 }
 
-template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, AutoPopScopeRef& functionScope, ParserFunctionInfo<TreeBuilder>& info)
+template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionParseMode mode, ParserFunctionInfo<TreeBuilder>& info)
 {
-    if (match(IDENT)) {
-        info.name = m_token.m_data.ident;
-        m_lastFunctionName = info.name;
-        next();
-        if (!nameIsInContainingScope)
-            failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
-    } else if (requirements == FunctionNeedsName) {
-        if (match(OPENPAREN) && mode == FunctionMode)
-            semanticFail("Function statements must have a name");
-        semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
-        failDueToUnexpectedToken();
-        return false;
-    }
     int parametersStart = m_token.m_location.startOffset;
+    
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    if (mode == ArrowFunctionMode) {
+        if (!match(IDENT) && !match(OPENPAREN)) {
+            semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
+            failWithMessage("Expected an arrow function input parameter");
+        } else {
+            if (match(OPENPAREN)) {
+                next();
+                
+                if (!match(CLOSEPAREN)) {
+                    info.parameters = parseFormalParameters(context);
+                    failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
+                }
+                
+                consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
+            } else {
+                auto parameter = parseDeconstructionPattern(context, DeconstructToParameters);
+                failIfFalse(parameter, "Cannot parse parameter pattern");
+                info.parameters = context.createFormalParameterList(parameter);
+                failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
+            }
+        }
+        
+        return parametersStart;
+    }
+#endif
+    
     if (!consume(OPENPAREN)) {
         semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
         failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
@@ -1384,43 +1462,89 @@ template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>
     
     return parametersStart;
 }
-    
+
 template <typename LexerType>
-template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& info)
+template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& info, FunctionParseType parseType)
 {
     AutoPopScopeRef functionScope(this, pushScope());
     functionScope->setIsFunction();
     int functionNameStart = m_token.m_location.startOffset;
     const Identifier* lastFunctionName = m_lastFunctionName;
     m_lastFunctionName = nullptr;
+    int parametersStart;
     
-    int parametersStart = parseFunctionParameters(context, requirements, mode, nameIsInContainingScope, functionScope, info);
-    propagateError();
-
-    matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
+    switch (parseType) {
+    case StandardFunctionParseType: {
+        if (match(IDENT)) {
+            info.name = m_token.m_data.ident;
+            m_lastFunctionName = info.name;
+            next();
+            if (!nameIsInContainingScope)
+                failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
+        } else if (requirements == FunctionNeedsName) {
+            if (match(OPENPAREN) && mode == FunctionMode)
+                semanticFail("Function statements must have a name");
+            semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
+            failDueToUnexpectedToken();
+            return false;
+        }
+        
+        parametersStart = parseFunctionParameters(context, mode, info);
+        propagateError();
+        
+        matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
+        
+        // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
+        // Set ConstructorKind to None for non-constructor methods of classes.
+    
+        if (m_defaultConstructorKind != ConstructorKind::None) {
+            constructorKind = m_defaultConstructorKind;
+            expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
+        }
+        
+        info.startFunctionOffset = m_token.m_data.offset;
+        
+        break;
+    }
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    case ArrowFunctionParseType: {
+        parametersStart = parseFunctionParameters(context, ArrowFunctionMode, info);
+        propagateError();
+        
+        matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
+        ASSERT(constructorKind == ConstructorKind::None);
+        
+        info.arrowFunctionOffset = m_token.m_data.offset;
+        // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
+        // and we need use common approach to parse function body
+        SavePoint savePoint = createSavePoint();
+        
+        next();
+        info.functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
+        info.startFunctionOffset = (info.functionBodyType == ArrowFunctionBodyBlock) ? m_token.m_data.offset : info.arrowFunctionOffset;
+        
+        restoreSavePoint(savePoint);
 
-    // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
-    // Set ConstructorKind to None for non-constructor methods of classes.
-    if (m_defaultConstructorKind != ConstructorKind::None) {
-        constructorKind = m_defaultConstructorKind;
-        expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
+        break;
     }
+#endif
+    }
+    
     bool isClassConstructor = constructorKind != ConstructorKind::None;
 
-    info.openBraceOffset = m_token.m_data.offset;
     info.bodyStartLine = tokenLine();
     info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
     JSTokenLocation startLocation(tokenLocation());
     
     // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
-    if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.openBraceOffset) : 0) {
+    if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.startFunctionOffset) : 0) {
         // If we're in a strict context, the cached function info must say it was strict too.
         ASSERT(!strictMode() || cachedInfo->strictMode);
         JSTokenLocation endLocation;
 
-        endLocation.line = cachedInfo->closeBraceLine;
-        endLocation.startOffset = cachedInfo->closeBraceOffset;
-        endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset;
+        endLocation.line = cachedInfo->lastTockenLine;
+        endLocation.startOffset = cachedInfo->lastTockenStartOffset;
+        endLocation.lineStartOffset = cachedInfo->lastTockenLineStartOffset;
 
         bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine);
         ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
@@ -1437,24 +1561,64 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
         functionScope->restoreFromSourceProviderCache(cachedInfo);
         failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
         
-        info.closeBraceOffset = cachedInfo->closeBraceOffset;
-
-        m_token = cachedInfo->closeBraceToken();
+        m_token = cachedInfo->endFunctionToken();
+        
         if (endColumnIsOnStartLine)
             m_token.m_location.lineStartOffset = currentLineStartOffset;
 
         m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
         m_lexer->setLineNumber(m_token.m_location.line);
-
-        context.setEndOffset(info.body, m_lexer->currentOffset());
+        info.endFunctionOffset = cachedInfo->endFunctionOffset;
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+        if (parseType == ArrowFunctionParseType)
+            info.functionBodyType = cachedInfo->isBodyArrowExpression ?  ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
+        else
+            info.functionBodyType = StandardFunctionBodyBlock;
         
+        switch (info.functionBodyType) {
+        case ArrowFunctionBodyExpression:
+            next();
+            context.setEndOffset(info.body, m_lexer->currentOffset());
+            break;
+        case ArrowFunctionBodyBlock:
+        case StandardFunctionBodyBlock:
+            context.setEndOffset(info.body, m_lexer->currentOffset());
+            next();
+            break;
+        }
+#else
+        context.setEndOffset(info.body, m_lexer->currentOffset());
         next();
+#endif
         info.bodyEndLine = m_lastTokenEndPosition.line;
         return true;
     }
+    
     m_lastFunctionName = lastFunctionName;
     ParserState oldState = saveState();
-    info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind);
+    
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    switch (info.functionBodyType) {
+    case ArrowFunctionBodyBlock: {
+        // Consume => in case of arrow function block e.g. x => { return x; }
+        next();
+    
+        info.bodyStartLine = tokenLine();
+        info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
+            
+        info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
+        break;
+    }
+    case StandardFunctionBodyBlock:
+    case ArrowFunctionBodyExpression : {
+        info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, parseType);
+        break;
+    }
+    }
+#else
+    info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
+#endif
+    
     restoreState(oldState);
     failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
     context.setEndOffset(info.body, m_lexer->currentOffset());
@@ -1470,33 +1634,56 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
     if (functionScope->needsSuperBinding())
         semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
 
-    info.closeBraceOffset = m_token.m_data.offset;
-    unsigned closeBraceLine = m_token.m_data.line;
-    unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset;
+    JSTokenLocation location = JSTokenLocation(m_token.m_location);
+    info.endFunctionOffset = m_token.m_data.offset;
+    
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    if (info.functionBodyType == ArrowFunctionBodyExpression) {
+        location = locationBeforeLastToken();
+        info.endFunctionOffset = location.endOffset;
+    }
+#endif
     
     // Cache the tokenizer state and the function scope the first time the function is parsed.
     // Any future reparsing can then skip the function.
     static const int minimumFunctionLengthToCache = 16;
     std::unique_ptr<SourceProviderCacheItem> newInfo;
-    int functionLength = info.closeBraceOffset - info.openBraceOffset;
+    int functionLength = info.endFunctionOffset - info.startFunctionOffset;
     if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
         SourceProviderCacheItemCreationParameters parameters;
+        parameters.endFunctionOffset = info.endFunctionOffset;
         parameters.functionNameStart = functionNameStart;
-        parameters.closeBraceLine = closeBraceLine;
-        parameters.closeBraceOffset = info.closeBraceOffset;
-        parameters.closeBraceLineStartOffset = closeBraceLineStartOffset;
+        parameters.lastTockenLine = location.line;
+        parameters.lastTockenStartOffset = location.startOffset;
+        parameters.lastTockenEndOffset = location.endOffset;
+        parameters.lastTockenLineStartOffset = location.lineStartOffset;
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+        if (info.functionBodyType == ArrowFunctionBodyExpression) {
+            parameters.isBodyArrowExpression = true;
+            parameters.tokenType = m_token.m_type;
+        }
+#endif
         functionScope->fillParametersForSourceProviderCache(parameters);
         newInfo = SourceProviderCacheItem::create(parameters);
-
     }
     
     failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
+    
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    if (info.functionBodyType == ArrowFunctionBodyExpression)
+        failIfFalse(isEndOfArrowFunction(), "Expected the closing ';' ',' ']' ')' '}', line terminator or EOF after arrow function");
+    else {
+        matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
+        next();
+    }
+#else
     matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
+    next();
+#endif
     
     if (newInfo)
-        m_functionCache->add(info.openBraceOffset, WTF::move(newInfo));
+        m_functionCache->add(info.startFunctionOffset, WTF::move(newInfo));
     
-    next();
     info.bodyEndLine = m_lastTokenEndPosition.line;
     return true;
 }
@@ -1510,7 +1697,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla
     next();
     ParserFunctionInfo<TreeBuilder> info;
     failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded,
-        functionKeywordStart, info)), "Cannot parse this function");
+        functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse this function");
     failIfFalse(info.name, "Function statements must have a name");
     failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode");
     return context.createFuncDeclStatement(location, info);
@@ -1629,8 +1816,7 @@ template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(T
         } else {
             ParserFunctionInfo<TreeBuilder> methodInfo;
             bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
-            failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false,
-                isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo)), "Cannot parse this method");
+            failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
             failIfFalse(ident && declareVariable(ident), "Cannot declare a method named '", methodInfo.name->impl(), "'");
             methodInfo.name = isConstructor ? className : ident;
 
@@ -1871,6 +2057,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(T
     return head;
 }
 
+    
 template <typename LexerType>
 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
 {
@@ -1889,6 +2076,12 @@ template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmen
         }
         restoreSavePoint(savePoint);
     }
+    
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    if (isArrowFunctionParamters())
+        return parseArrowFunctionExpression(context);
+#endif
+    
     TreeExpression lhs = parseConditionalExpression(context);
     failIfFalse(lhs, "Cannot parse expression");
     if (initialNonLHSCount != m_nonLHSCount) {
@@ -2129,8 +2322,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMeth
     JSTokenLocation methodLocation(tokenLocation());
     unsigned methodStart = tokenStart();
     ParserFunctionInfo<TreeBuilder> methodInfo;
-    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded,
-        methodStart, methodInfo)), "Cannot parse this method");
+    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
     methodInfo.name = methodName;
     return context.createFunctionExpr(methodLocation, methodInfo);
 }
@@ -2157,11 +2349,11 @@ template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(T
     if (type & PropertyNode::Getter) {
         failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, constructorKind, superBinding,
-            getterOrSetterStartOffset, info)), "Cannot parse getter definition");
+            getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse getter definition");
     } else {
         failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, constructorKind, superBinding,
-            getterOrSetterStartOffset, info)), "Cannot parse setter definition");
+            getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse setter definition");
     }
     if (stringPropertyName)
         return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, superBinding);
@@ -2428,8 +2620,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre
         next();
         ParserFunctionInfo<TreeBuilder> info;
         info.name = &m_vm->propertyNames->nullIdentifier;
-        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded,
-            functionKeywordStart, info)), "Cannot parse function expression");
+        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse function expression");
         return context.createFunctionExpr(location, info);
     }
 #if ENABLE(ES6_CLASS_SYNTAX)
@@ -2669,6 +2860,22 @@ endMemberExpression:
     return base;
 }
 
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrowFunctionExpression(TreeBuilder& context)
+{
+    JSTokenLocation location;
+
+    unsigned functionKeywordStart = tokenStart();
+    location = tokenLocation();
+    ParserFunctionInfo<TreeBuilder> info;
+    info.name = &m_vm->propertyNames->nullIdentifier;
+    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, ArrowFunctionParseType)), "Cannot parse arrow function expression");
+
+    return context.createArrowFunctionExpr(location, info);
+}
+#endif
+
 static const char* operatorString(bool prefix, unsigned tok)
 {
     switch (tok) {
index 21c6e1f..2c605e6 100644 (file)
@@ -80,12 +80,20 @@ class SourceCode;
 COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
 
 enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+enum FunctionParseType { StandardFunctionParseType, ArrowFunctionParseType };
+#else
+enum FunctionParseType { StandardFunctionParseType};
+#endif
 enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
 enum FunctionParseMode {
     FunctionMode,
     GetterMode,
     SetterMode,
     MethodMode,
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    ArrowFunctionMode
+#endif
 };
 enum DeconstructionKind {
     DeconstructToVariables,
@@ -430,6 +438,7 @@ public:
     std::unique_ptr<ParsedNode> parse(ParserError&);
 
     JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
+    JSTokenLocation locationBeforeLastToken() const { return m_lexer->lastTokenLocation(); }
     Vector<RefPtr<UniquedStringImpl>>&& closedVariables() { return WTF::move(m_closedVariables); }
 
 private:
@@ -612,6 +621,47 @@ private:
         return m_token.m_type == IDENT && *m_token.m_data.ident == m_vm->propertyNames->of;
     }
     
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    ALWAYS_INLINE bool isEndOfArrowFunction()
+    {
+        return match(SEMICOLON) || match(COMMA) || match(CLOSEPAREN) || match(CLOSEBRACE) || match(CLOSEBRACKET) || match(EOFTOK) || m_lexer->prevTerminator();
+    }
+    
+    ALWAYS_INLINE bool isArrowFunctionParamters()
+    {
+        bool isArrowFunction = false;
+        
+        if (match(EOFTOK))
+            return isArrowFunction;
+        
+        SavePoint saveArrowFunctionPoint = createSavePoint();
+        
+        if (consume(OPENPAREN)) {
+            bool isArrowFunctionParamters = true;
+            
+            while (consume(IDENT)) {
+                if (consume(COMMA)) {
+                    if (!match(IDENT)) {
+                        isArrowFunctionParamters = false;
+                        break;
+                    }
+                } else
+                    break;
+            }
+            
+            if (isArrowFunctionParamters) {
+                if (consume(CLOSEPAREN) && match(ARROWFUNCTION))
+                    isArrowFunction = true;
+            }
+        } else if (consume(IDENT) && match(ARROWFUNCTION))
+            isArrowFunction = true;
+
+        restoreSavePoint(saveArrowFunctionPoint);
+        
+        return isArrowFunction;
+    }
+#endif
+    
     ALWAYS_INLINE unsigned tokenStart()
     {
         return m_token.m_location.startOffset;
@@ -715,8 +765,8 @@ private:
         }
         return result;
     }
-    
-    template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode);
+
+    template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode, FunctionParseType);
     template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
 #if ENABLE(ES6_CLASS_SYNTAX)
     template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&);
@@ -756,24 +806,30 @@ private:
     template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
     template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName);
     template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind = ConstructorKind::None, SuperBinding = SuperBinding::NotNeeded);
-    template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind);
+    template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, FunctionParseType);
     template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
     enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
     template <class TreeBuilder> TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext);
     template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&);
 
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    template <class TreeBuilder> TreeStatement parseArrowFunctionSingleExpressionBody(TreeBuilder&, FunctionParseType);
+    template <class TreeBuilder> TreeExpression parseArrowFunctionExpression(TreeBuilder&);
+#endif
+
     template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern createBindingPattern(TreeBuilder&, DeconstructionKind, const Identifier&, int depth, JSToken);
     template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&, DeconstructionKind, int depth = 0);
     template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&);
     template <class TreeBuilder> NEVER_INLINE TreeExpression parseDefaultValueForDeconstructionPattern(TreeBuilder&);
 
-    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&);
+    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionParseType);
     
-    template <class TreeBuilder> NEVER_INLINE int parseFunctionParameters(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool, AutoPopScopeRef&, ParserFunctionInfo<TreeBuilder>&);
+    template <class TreeBuilder> NEVER_INLINE int parseFunctionParameters(TreeBuilder&, FunctionParseMode, ParserFunctionInfo<TreeBuilder>&);
 
 #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, typename LexerType::RawStringsBuildMode, bool& elementIsTail);
     template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateLiteral parseTemplateLiteral(TreeBuilder&, typename LexerType::RawStringsBuildMode);
@@ -793,6 +849,14 @@ private:
         return allowAutomaticSemicolon();
     }
     
+
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    void setEndOfStatement()
+    {
+        m_lexer->setTokenPosition(&m_token);
+    }
+#endif
+
     bool canRecurse()
     {
         return m_vm->isSafeToRecurse();
index 6b73628..366084d 100644 (file)
 
 namespace JSC {
 
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+enum FunctionBodyType { ArrowFunctionBodyExpression, ArrowFunctionBodyBlock, StandardFunctionBodyBlock };
+#endif
+
 template <class TreeBuilder>
 struct ParserFunctionInfo {
     const Identifier* name = 0;
     typename TreeBuilder::FormalParameterList parameters = 0;
     typename TreeBuilder::FunctionBody body = 0;
-    unsigned openBraceOffset = 0;
-    unsigned closeBraceOffset = 0;
+    unsigned startFunctionOffset = 0;
+    unsigned endFunctionOffset = 0;
     int bodyStartLine = 0;
     int bodyEndLine = 0;
     unsigned bodyStartColumn = 0;
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    unsigned arrowFunctionOffset = 0;
+    unsigned arrowFunctionNextTockenEndOffset = 0;
+    bool isArrowFunction { false };
+    bool isEndByTerminator { false };
+    FunctionBodyType functionBodyType { StandardFunctionBodyBlock };
+#endif
 };
 
 #if ENABLE(ES6_CLASS_SYNTAX)
index 026e4f8..e9154ca 100644 (file)
@@ -75,6 +75,9 @@ enum JSTokenType {
     FINALLY,
     DEBUGGER,
     ELSE,
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    ARROWFUNCTION,
+#endif
 #if ENABLE(ES6_CLASS_SYNTAX)
     CLASSTOKEN,
     EXTENDS,
index 73d23db..f4a1902 100644 (file)
@@ -105,6 +105,9 @@ namespace JSC {
         
         SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn);
 
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+        SourceCode subArrowExpression(unsigned startArrowFunction, unsigned endArrowFunction, int firstLine, int startColumn);
+#endif
     private:
         RefPtr<SourceProvider> m_provider;
         int m_startChar;
@@ -117,6 +120,16 @@ namespace JSC {
     {
         return SourceCode(StringSourceProvider::create(source, url, startPosition), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt());
     }
+    
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    inline SourceCode SourceCode::subArrowExpression(unsigned startArrowFunction, unsigned endArrowFunction, int firstLine, int startColumn)
+    {
+        ASSERT(provider()->source()[startArrowFunction] == '=' && provider()->source()[startArrowFunction + 1] == '>');
+
+        startColumn += 1; // Convert to base 1.
+        return SourceCode(provider(), startArrowFunction, endArrowFunction, firstLine, startColumn);
+    }
+#endif
 
     inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn)
     {
index 5e3fdff..c0c507f 100644 (file)
@@ -35,14 +35,20 @@ namespace JSC {
 
 struct SourceProviderCacheItemCreationParameters {
     unsigned functionNameStart;
-    unsigned closeBraceLine;
-    unsigned closeBraceOffset;
-    unsigned closeBraceLineStartOffset;
+    unsigned lastTockenLine;
+    unsigned lastTockenStartOffset;
+    unsigned lastTockenEndOffset;
+    unsigned lastTockenLineStartOffset;
+    unsigned endFunctionOffset;
     bool needsFullActivation;
     bool usesEval;
     bool strictMode;
     Vector<RefPtr<UniquedStringImpl>> usedVariables;
     Vector<RefPtr<UniquedStringImpl>> writtenVariables;
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    bool isBodyArrowExpression { false };
+    JSTokenType tokenType { CLOSEBRACE };
+#endif
 };
 
 #if COMPILER(MSVC)
@@ -56,15 +62,19 @@ public:
     static std::unique_ptr<SourceProviderCacheItem> create(const SourceProviderCacheItemCreationParameters&);
     ~SourceProviderCacheItem();
 
-    JSToken closeBraceToken() const 
+    JSToken endFunctionToken() const 
     {
         JSToken token;
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+        token.m_type = isBodyArrowExpression ? tokenType : CLOSEBRACE;
+#else
         token.m_type = CLOSEBRACE;
-        token.m_data.offset = closeBraceOffset;
-        token.m_location.startOffset = closeBraceOffset;
-        token.m_location.endOffset = closeBraceOffset + 1;
-        token.m_location.line = closeBraceLine;
-        token.m_location.lineStartOffset = closeBraceLineStartOffset;
+#endif
+        token.m_data.offset = lastTockenStartOffset;
+        token.m_location.startOffset = lastTockenStartOffset;
+        token.m_location.endOffset = lastTockenEndOffset;
+        token.m_location.line = lastTockenLine;
+        token.m_location.lineStartOffset = lastTockenLineStartOffset;
         // token.m_location.sourceOffset is initialized once by the client. So,
         // we do not need to set it here.
         return token;
@@ -72,19 +82,26 @@ public:
 
     unsigned functionNameStart : 31;
     bool needsFullActivation : 1;
+
+    unsigned endFunctionOffset : 31;
+    unsigned lastTockenLine : 31;
+    unsigned lastTockenStartOffset : 31;
+    unsigned lastTockenEndOffset: 31;
     
-    unsigned closeBraceLine : 31;
     bool usesEval : 1;
 
-    unsigned closeBraceOffset : 31;
     bool strictMode : 1;
 
-    unsigned closeBraceLineStartOffset;
+    unsigned lastTockenLineStartOffset;
     unsigned usedVariablesCount;
     unsigned writtenVariablesCount;
 
     UniquedStringImpl** usedVariables() const { return const_cast<UniquedStringImpl**>(m_variables); }
     UniquedStringImpl** writtenVariables() const { return const_cast<UniquedStringImpl**>(&m_variables[usedVariablesCount]); }
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    bool isBodyArrowExpression;
+    JSTokenType tokenType;
+#endif
 
 private:
     SourceProviderCacheItem(const SourceProviderCacheItemCreationParameters&);
@@ -109,13 +126,19 @@ inline std::unique_ptr<SourceProviderCacheItem> SourceProviderCacheItem::create(
 inline SourceProviderCacheItem::SourceProviderCacheItem(const SourceProviderCacheItemCreationParameters& parameters)
     : functionNameStart(parameters.functionNameStart)
     , needsFullActivation(parameters.needsFullActivation)
-    , closeBraceLine(parameters.closeBraceLine)
+    , endFunctionOffset(parameters.endFunctionOffset)
+    , lastTockenLine(parameters.lastTockenLine)
+    , lastTockenStartOffset(parameters.lastTockenStartOffset)
+    , lastTockenEndOffset(parameters.lastTockenEndOffset)
     , usesEval(parameters.usesEval)
-    , closeBraceOffset(parameters.closeBraceOffset)
     , strictMode(parameters.strictMode)
-    , closeBraceLineStartOffset(parameters.closeBraceLineStartOffset)
+    , lastTockenLineStartOffset(parameters.lastTockenLineStartOffset)
     , usedVariablesCount(parameters.usedVariables.size())
     , writtenVariablesCount(parameters.writtenVariables.size())
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    , isBodyArrowExpression(parameters.isBodyArrowExpression)
+    , tokenType(parameters.tokenType)
+#endif
 {
     unsigned j = 0;
     for (unsigned i = 0; i < usedVariablesCount; ++i, ++j) {
index f5d426f..b47b66a 100644 (file)
@@ -179,6 +179,10 @@ public:
 #endif
     ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind) { return FunctionBodyResult; }
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+    ExpressionType createArrowFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
+#endif 
+    void setFunctionNameStart(int, int) { }
     int createArguments() { return ArgumentsResult; }
     int createArguments(int) { return ArgumentsResult; }
     ExpressionType createSpreadExpression(const JSTokenLocation&, ExpressionType, int, int, int) { return SpreadExpr; }