Changeset 185989 in webkit


Ignore:
Timestamp:
Jun 25, 2015 11:49:20 PM (9 years ago)
Author:
commit-queue@webkit.org
Message:

Source/JavaScriptCore:

[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.
Location:
trunk
Files:
27 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r185976 r185989  
     12015-06-26 Aleksandr Skachkov  <gskachkov@gmail.com>
     2
     3         [ES6] Implement ES6 arrow function syntax. Parser of arrow function with execution as common function
     4         https://bugs.webkit.org/show_bug.cgi?id=144955
     5
     6         Reviewed by Yusuke Suzuki.
     7
     8         Added arrow function tests     
     9
     10        * js/arrowfunction-asparamter-1-expected.txt: Added.
     11        * js/arrowfunction-asparamter-1.html: Added.
     12        * js/arrowfunction-asparamter-2-expected.txt: Added.
     13        * js/arrowfunction-asparamter-2.html: Added.
     14        * js/arrowfunction-associativity-1-expected.txt: Added.
     15        * js/arrowfunction-associativity-1.html: Added.
     16        * js/arrowfunction-associativity-2-expected.txt: Added.
     17        * js/arrowfunction-associativity-2.html: Added.
     18        * js/arrowfunction-block-1-expected.txt: Added.
     19        * js/arrowfunction-block-1.html: Added.
     20        * js/arrowfunction-block-2-expected.txt: Added.
     21        * js/arrowfunction-block-2.html: Added.
     22        * js/arrowfunction-syntax-endings-expected.txt: Added.
     23        * js/arrowfunction-syntax-endings.html: Added.
     24        * js/arrowfunction-syntax-errors-expected.txt: Added.
     25        * js/arrowfunction-syntax-errors.html: Added.
     26        * js/arrowfunction-syntax-expected.txt: Added.
     27        * js/arrowfunction-syntax.html: Added.
     28        * js/script-tests/arrowfunction-asparamter-1.js: Added.
     29        * js/script-tests/arrowfunction-asparamter-2.js: Added.
     30        * js/script-tests/arrowfunction-associativity-1.js: Added.
     31        * js/script-tests/arrowfunction-associativity-2.js: Added.
     32        * js/script-tests/arrowfunction-block-1.js: Added.
     33        * js/script-tests/arrowfunction-block-2.js: Added.
     34        * js/script-tests/arrowfunction-syntax-endings.js: Added.
     35        * js/script-tests/arrowfunction-syntax-errors.js: Added.
     36        * js/script-tests/arrowfunction-syntax.js: Added.
     37
    1382015-06-25  Chris Fleizach  <cfleizach@apple.com>
    239
  • trunk/Source/JavaScriptCore/ChangeLog

    r185981 r185989  
     12015-06-26 Aleksandr Skachkov  <gskachkov@gmail.com>
     2
     3         [ES6] Implement ES6 arrow function syntax. Parser of arrow function with execution as common function.
     4         https://bugs.webkit.org/show_bug.cgi?id=144955
     5
     6         Reviewed by Yusuke Suzuki.
     7
     8         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.     
     9        This patch implements the simplest cases of arrow function declaration:
     10           parameters             () => 10 + 20
     11           parameter               x => x + 20
     12           parameters         (x, y) => x + y
     13           function with block     x => { return x*10; }
     14
     15        Not implemented:
     16           bind of the this, arguments, super and etc.
     17           exception in case of trying to use 'new' with arrow function
     18
     19        * parser/ASTBuilder.h:
     20        (JSC::ASTBuilder::createFunctionExpr):
     21        (JSC::ASTBuilder::createArrowFunctionExpr):
     22        (JSC::ASTBuilder::createGetterOrSetterProperty):
     23        (JSC::ASTBuilder::createFuncDeclStatement):
     24        * parser/Lexer.cpp:
     25        (JSC::Lexer<T>::setTokenPosition):
     26        (JSC::Lexer<T>::lex):
     27        * parser/Lexer.h:
     28        (JSC::Lexer::lastTokenLocation):
     29        (JSC::Lexer::setTerminator):
     30        * parser/Parser.cpp:
     31        (JSC::Parser<LexerType>::parseInner):
     32        (JSC::Parser<LexerType>::parseSourceElements):
     33        (JSC::Parser<LexerType>::parseArrowFunctionSingleExpressionBody):
     34        (JSC::Parser<LexerType>::parseSwitchClauses):
     35        (JSC::Parser<LexerType>::parseSwitchDefaultClause):
     36        (JSC::Parser<LexerType>::parseBlockStatement):
     37        (JSC::Parser<LexerType>::parseFunctionBody):
     38        (JSC::stringForFunctionMode):
     39        (JSC::Parser<LexerType>::parseFunctionParameters):
     40        (JSC::Parser<LexerType>::parseFunctionInfo):
     41        (JSC::Parser<LexerType>::parseFunctionDeclaration):
     42        (JSC::Parser<LexerType>::parseClass):
     43        (JSC::Parser<LexerType>::parseAssignmentExpression):
     44        (JSC::Parser<LexerType>::parsePropertyMethod):
     45        (JSC::Parser<LexerType>::parseGetterSetter):
     46        (JSC::Parser<LexerType>::parseArrowFunctionExpression):
     47        * parser/Parser.h:
     48        (JSC::Parser::locationBeforeLastToken):
     49        (JSC::Parser::isEndOfArrowFunction):
     50        (JSC::Parser::isArrowFunctionParamters):
     51        (JSC::Parser::setEndOfStatement):
     52        * parser/ParserFunctionInfo.h:
     53        * parser/ParserTokens.h:
     54        * parser/SourceCode.h:
     55        (JSC::SourceCode::subArrowExpression):
     56        * parser/SourceProviderCacheItem.h:
     57        (JSC::SourceProviderCacheItem::endFunctionToken):
     58        (JSC::SourceProviderCacheItem::SourceProviderCacheItem):
     59        * parser/SyntaxChecker.h:
     60        (JSC::SyntaxChecker::createArrowFunctionExpr):
     61        (JSC::SyntaxChecker::setFunctionNameStart):
     62
    1632015-06-25  Yusuke Suzuki  <utatane.tea@gmail.com>
    264
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r185981 r185989  
    348348    {
    349349        FuncExprNode* result = new (m_parserArena) FuncExprNode(location, *info.name, info.body,
    350             m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters);
     350            m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters);
    351351        info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
    352352        return result;
     
    365365    }
    366366
     367#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     368    ExpressionNode* createArrowFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& info)
     369    {
     370        SourceCode source = info.functionBodyType == ArrowFunctionBodyExpression
     371            ? m_sourceCode->subArrowExpression(info.arrowFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn)
     372            : m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn);
     373
     374        FuncExprNode* result = new (m_parserArena) FuncExprNode(location, *info.name, info.body, source, info.parameters);
     375        info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
     376        return result;
     377    }
     378#endif
     379
    367380    NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool,
    368381        const Identifier* name, const ParserFunctionInfo<ASTBuilder>& info, SuperBinding superBinding)
     
    371384        info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
    372385        info.body->setInferredName(*name);
    373         SourceCode source = m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn);
     386        SourceCode source = m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn);
    374387        FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, info.body, source, info.parameters);
    375388        return new (m_parserArena) PropertyNode(*name, funcExpr, type, PropertyNode::Unknown, superBinding);
     
    381394        info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
    382395        const Identifier& ident = parserArena.identifierArena().makeNumericIdentifier(vm, name);
    383         SourceCode source = m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn);
     396        SourceCode source = m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn);
    384397        FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, vm->propertyNames->nullIdentifier, info.body, source, info.parameters);
    385398        return new (m_parserArena) PropertyNode(ident, funcExpr, type, PropertyNode::Unknown, superBinding);
     
    418431    {
    419432        FuncDeclNode* decl = new (m_parserArena) FuncDeclNode(location, *info.name, info.body,
    420             m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters);
     433            m_sourceCode->subExpression(info.startFunctionOffset, info.endFunctionOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters);
    421434        if (*info.name == m_vm->propertyNames->arguments)
    422435            usesArguments();
  • trunk/Source/JavaScriptCore/parser/Lexer.cpp

    r185437 r185989  
    17161716}
    17171717
     1718#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1719template <typename T>
     1720void Lexer<T>::setTokenPosition(JSToken* tokenRecord)
     1721{
     1722    JSTokenData* tokenData = &tokenRecord->m_data;
     1723    tokenData->line = lineNumber();
     1724    tokenData->offset = currentOffset();
     1725    tokenData->lineStartOffset = currentLineStartOffset();
     1726    ASSERT(tokenData->offset >= tokenData->lineStartOffset);
     1727}
     1728#endif
     1729
    17181730template <typename T>
    17191731JSTokenType Lexer<T>::lex(JSToken* tokenRecord, unsigned lexerFlags, bool strictMode)
     
    17211733    JSTokenData* tokenData = &tokenRecord->m_data;
    17221734    JSTokenLocation* tokenLocation = &tokenRecord->m_location;
     1735    m_lastTockenLocation = JSTokenLocation(tokenRecord->m_location);
     1736   
    17231737    ASSERT(!m_error);
    17241738    ASSERT(m_buffer8.isEmpty());
     
    17791793        token = GT;
    17801794        break;
    1781     case CharacterEqual:
     1795    case CharacterEqual: {
     1796#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1797        if (peek(1) == '>') {
     1798            token = ARROWFUNCTION;
     1799            tokenData->line = lineNumber();
     1800            tokenData->offset = currentOffset();
     1801            tokenData->lineStartOffset = currentLineStartOffset();
     1802            ASSERT(tokenData->offset >= tokenData->lineStartOffset);
     1803            shift();
     1804            shift();
     1805            break;
     1806        }
     1807#endif
    17821808        shift();
    17831809        if (m_current == '=') {
     
    17931819        token = EQUAL;
    17941820        break;
     1821    }
    17951822    case CharacterLess:
    17961823        shift();
  • trunk/Source/JavaScriptCore/parser/Lexer.h

    r184337 r185989  
    8888    bool isReparsing() const { return m_isReparsing; }
    8989
     90#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     91    void setTokenPosition(JSToken* tokenRecord);
     92#endif
    9093    JSTokenType lex(JSToken*, unsigned, bool strictMode);
    9194    bool nextTokenIsColon();
     
    98101    }
    99102    JSTextPosition positionBeforeLastNewline() const { return m_positionBeforeLastNewline; }
     103    JSTokenLocation lastTokenLocation() const { return m_lastTockenLocation; }
    100104    void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
    101105    int lastLineNumber() const { return m_lastLineNumber; }
     
    131135    {
    132136        m_lineNumber = line;
     137    }
     138    void setTerminator(bool terminator)
     139    {
     140        m_terminator = terminator;
    133141    }
    134142
     
    216224    const T* m_lineStart;
    217225    JSTextPosition m_positionBeforeLastNewline;
     226    JSTokenLocation m_lastTockenLocation;
    218227    bool m_isReparsing;
    219228    bool m_atLineStart;
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r185981 r185989  
    265265        m_statementDepth--;
    266266    ScopeRef scope = currentScope();
    267     SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode);
     267    SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode, StandardFunctionParseType);
    268268    if (!sourceElements || !consume(EOFTOK)) {
    269269        if (hasError())
     
    344344
    345345template <typename LexerType>
    346 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
     346template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode, FunctionParseType functionParseType)
    347347{
    348348    const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
     
    353353    auto savePoint = createSavePoint();
    354354    bool hasSetStrict = false;
     355   
     356#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     357    if (match(ARROWFUNCTION)) {
     358        TreeStatement arrowfunctionStatement = parseArrowFunctionSingleExpressionBody(context, functionParseType);
     359           
     360        if (arrowfunctionStatement) {
     361            context.setEndOffset(arrowfunctionStatement, m_lastTokenEndPosition.offset);
     362            context.appendStatement(sourceElements, arrowfunctionStatement);
     363        }
     364       
     365        propagateError();
     366        return sourceElements;
     367    }
     368#endif
     369   
    355370    while (TreeStatement statement = parseStatement(context, directive, &directiveLiteralLength)) {
    356371        if (mode == CheckForStrictMode && !seenNonDirective) {
     
    583598    return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition);
    584599}
     600
     601#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     602template <typename LexerType>
     603template <class TreeBuilder> TreeStatement Parser<LexerType>::parseArrowFunctionSingleExpressionBody(TreeBuilder& context, FunctionParseType parseType)
     604{
     605    ASSERT(match(ARROWFUNCTION));
     606
     607    // When reparsing phase, parseType becomes StandardFunctionParseType even if the function is arrow function.
     608    // This condition considers the following situations.
     609    // (1): If we are in the reparsing phase, this arrow function is already parsed once, so there is no syntax error.
     610    // (2): But if we are not in the reparsing phase, we should check this function is called in the context of the arrow function.
     611    if (!m_lexer->isReparsing() && parseType != ArrowFunctionParseType)
     612        failDueToUnexpectedToken();
     613   
     614    JSTokenLocation location(tokenLocation());
     615    JSTextPosition start = tokenStartPosition();
     616    JSTextPosition end = tokenEndPosition();
     617
     618    next();
     619
     620    failIfStackOverflow();
     621    TreeExpression expr = parseAssignmentExpression(context);
     622    failIfFalse(expr, "Cannot parse the arrow function expression");
     623   
     624    context.setEndOffset(expr, m_lastTokenEndPosition.offset);
     625
     626    failIfFalse(isEndOfArrowFunction(), "Expected a ';', ']', '}', ')', ',', line terminator or EOF following a arrow function statement");
     627
     628    end = tokenEndPosition();
     629   
     630    if (!m_lexer->prevTerminator())
     631        setEndOfStatement();
     632
     633    return context.createReturnStatement(location, expr, start, end);
     634}
     635#endif
    585636
    586637template <typename LexerType>
     
    10661117    failIfFalse(condition, "Cannot parse switch clause");
    10671118    consumeOrFail(COLON, "Expected a ':' after switch clause expression");
    1068     TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
     1119    TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
    10691120    failIfFalse(statements, "Cannot parse the body of a switch clause");
    10701121    TreeClause clause = context.createClause(condition, statements);
     
    10791130        failIfFalse(condition, "Cannot parse switch case expression");
    10801131        consumeOrFail(COLON, "Expected a ':' after switch clause expression");
    1081         TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
     1132        TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
    10821133        failIfFalse(statements, "Cannot parse the body of a switch clause");
    10831134        clause = context.createClause(condition, statements);
     
    10961147    next();
    10971148    consumeOrFail(COLON, "Expected a ':' after switch default clause");
    1098     TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
     1149    TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
    10991150    failIfFalse(statements, "Cannot parse the body of a switch default clause");
    11001151    TreeClause result = context.createClause(0, statements);
     
    11811232        return result;
    11821233    }
    1183     TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
     1234    TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
    11841235    failIfFalse(subtree, "Cannot parse the body of the block statement");
    11851236    matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
     
    12021253    TreeStatement result = 0;
    12031254    bool shouldSetEndOffset = true;
     1255
    12041256    switch (m_token.m_type) {
    12051257    case OPENBRACE:
     
    13111363template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
    13121364    TreeBuilder& context, int functionKeywordStart, int functionNameStart,
    1313     int parametersStart, ConstructorKind constructorKind)
     1365    int parametersStart, ConstructorKind constructorKind, FunctionParseType parseType)
    13141366{
    13151367    JSTokenLocation startLocation(tokenLocation());
    13161368    unsigned startColumn = tokenColumn();
    1317     next();
    1318 
    1319     if (match(CLOSEBRACE)) {
    1320         unsigned endColumn = tokenColumn();
    1321         return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
    1322     }
     1369
     1370    if (parseType == StandardFunctionParseType) {
     1371        next();
     1372        if (match(CLOSEBRACE)) {
     1373            unsigned endColumn = tokenColumn();
     1374            return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
     1375        }
     1376    }
     1377
    13231378    DepthManager statementDepth(&m_statementDepth);
    13241379    m_statementDepth = 0;
    13251380    typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
    1326     failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode), "Cannot parse body of this function");
     1381#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1382    failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, parseType), parseType == StandardFunctionParseType ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
     1383#else
     1384    failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, StandardFunctionParseType), "Cannot parse body of this function");
     1385#endif
    13271386    unsigned endColumn = tokenColumn();
    13281387    return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
     
    13401399    case MethodMode:
    13411400        return "method";
     1401#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1402    case ArrowFunctionMode:
     1403        return "arrow function";
     1404#endif
    13421405    }
    13431406    RELEASE_ASSERT_NOT_REACHED();
     
    13451408}
    13461409
    1347 template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, AutoPopScopeRef& functionScope, ParserFunctionInfo<TreeBuilder>& info)
    1348 {
    1349     if (match(IDENT)) {
    1350         info.name = m_token.m_data.ident;
    1351         m_lastFunctionName = info.name;
    1352         next();
    1353         if (!nameIsInContainingScope)
    1354             failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
    1355     } else if (requirements == FunctionNeedsName) {
    1356         if (match(OPENPAREN) && mode == FunctionMode)
    1357             semanticFail("Function statements must have a name");
    1358         semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
    1359         failDueToUnexpectedToken();
    1360         return false;
    1361     }
     1410template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionParseMode mode, ParserFunctionInfo<TreeBuilder>& info)
     1411{
    13621412    int parametersStart = m_token.m_location.startOffset;
     1413   
     1414#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1415    if (mode == ArrowFunctionMode) {
     1416        if (!match(IDENT) && !match(OPENPAREN)) {
     1417            semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
     1418            failWithMessage("Expected an arrow function input parameter");
     1419        } else {
     1420            if (match(OPENPAREN)) {
     1421                next();
     1422               
     1423                if (!match(CLOSEPAREN)) {
     1424                    info.parameters = parseFormalParameters(context);
     1425                    failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
     1426                }
     1427               
     1428                consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
     1429            } else {
     1430                auto parameter = parseDeconstructionPattern(context, DeconstructToParameters);
     1431                failIfFalse(parameter, "Cannot parse parameter pattern");
     1432                info.parameters = context.createFormalParameterList(parameter);
     1433                failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
     1434            }
     1435        }
     1436       
     1437        return parametersStart;
     1438    }
     1439#endif
     1440   
    13631441    if (!consume(OPENPAREN)) {
    13641442        semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
     
    13851463    return parametersStart;
    13861464}
    1387    
    1388 template <typename LexerType>
    1389 template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& info)
     1465
     1466template <typename LexerType>
     1467template <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)
    13901468{
    13911469    AutoPopScopeRef functionScope(this, pushScope());
     
    13941472    const Identifier* lastFunctionName = m_lastFunctionName;
    13951473    m_lastFunctionName = nullptr;
    1396    
    1397     int parametersStart = parseFunctionParameters(context, requirements, mode, nameIsInContainingScope, functionScope, info);
    1398     propagateError();
    1399 
    1400     matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
    1401 
    1402     // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
    1403     // Set ConstructorKind to None for non-constructor methods of classes.
    1404     if (m_defaultConstructorKind != ConstructorKind::None) {
    1405         constructorKind = m_defaultConstructorKind;
    1406         expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
    1407     }
     1474    int parametersStart;
     1475   
     1476    switch (parseType) {
     1477    case StandardFunctionParseType: {
     1478        if (match(IDENT)) {
     1479            info.name = m_token.m_data.ident;
     1480            m_lastFunctionName = info.name;
     1481            next();
     1482            if (!nameIsInContainingScope)
     1483                failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
     1484        } else if (requirements == FunctionNeedsName) {
     1485            if (match(OPENPAREN) && mode == FunctionMode)
     1486                semanticFail("Function statements must have a name");
     1487            semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
     1488            failDueToUnexpectedToken();
     1489            return false;
     1490        }
     1491       
     1492        parametersStart = parseFunctionParameters(context, mode, info);
     1493        propagateError();
     1494       
     1495        matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
     1496       
     1497        // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
     1498        // Set ConstructorKind to None for non-constructor methods of classes.
     1499   
     1500        if (m_defaultConstructorKind != ConstructorKind::None) {
     1501            constructorKind = m_defaultConstructorKind;
     1502            expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
     1503        }
     1504       
     1505        info.startFunctionOffset = m_token.m_data.offset;
     1506       
     1507        break;
     1508    }
     1509#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1510    case ArrowFunctionParseType: {
     1511        parametersStart = parseFunctionParameters(context, ArrowFunctionMode, info);
     1512        propagateError();
     1513       
     1514        matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
     1515        ASSERT(constructorKind == ConstructorKind::None);
     1516       
     1517        info.arrowFunctionOffset = m_token.m_data.offset;
     1518        // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
     1519        // and we need use common approach to parse function body
     1520        SavePoint savePoint = createSavePoint();
     1521       
     1522        next();
     1523        info.functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
     1524        info.startFunctionOffset = (info.functionBodyType == ArrowFunctionBodyBlock) ? m_token.m_data.offset : info.arrowFunctionOffset;
     1525       
     1526        restoreSavePoint(savePoint);
     1527
     1528        break;
     1529    }
     1530#endif
     1531    }
     1532   
    14081533    bool isClassConstructor = constructorKind != ConstructorKind::None;
    14091534
    1410     info.openBraceOffset = m_token.m_data.offset;
    14111535    info.bodyStartLine = tokenLine();
    14121536    info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
     
    14141538   
    14151539    // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
    1416     if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.openBraceOffset) : 0) {
     1540    if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.startFunctionOffset) : 0) {
    14171541        // If we're in a strict context, the cached function info must say it was strict too.
    14181542        ASSERT(!strictMode() || cachedInfo->strictMode);
    14191543        JSTokenLocation endLocation;
    14201544
    1421         endLocation.line = cachedInfo->closeBraceLine;
    1422         endLocation.startOffset = cachedInfo->closeBraceOffset;
    1423         endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset;
     1545        endLocation.line = cachedInfo->lastTockenLine;
     1546        endLocation.startOffset = cachedInfo->lastTockenStartOffset;
     1547        endLocation.lineStartOffset = cachedInfo->lastTockenLineStartOffset;
    14241548
    14251549        bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine);
     
    14381562        failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
    14391563       
    1440         info.closeBraceOffset = cachedInfo->closeBraceOffset;
    1441 
    1442         m_token = cachedInfo->closeBraceToken();
     1564        m_token = cachedInfo->endFunctionToken();
     1565       
    14431566        if (endColumnIsOnStartLine)
    14441567            m_token.m_location.lineStartOffset = currentLineStartOffset;
     
    14461569        m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
    14471570        m_lexer->setLineNumber(m_token.m_location.line);
    1448 
     1571        info.endFunctionOffset = cachedInfo->endFunctionOffset;
     1572#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1573        if (parseType == ArrowFunctionParseType)
     1574            info.functionBodyType = cachedInfo->isBodyArrowExpression ?  ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
     1575        else
     1576            info.functionBodyType = StandardFunctionBodyBlock;
     1577       
     1578        switch (info.functionBodyType) {
     1579        case ArrowFunctionBodyExpression:
     1580            next();
     1581            context.setEndOffset(info.body, m_lexer->currentOffset());
     1582            break;
     1583        case ArrowFunctionBodyBlock:
     1584        case StandardFunctionBodyBlock:
     1585            context.setEndOffset(info.body, m_lexer->currentOffset());
     1586            next();
     1587            break;
     1588        }
     1589#else
    14491590        context.setEndOffset(info.body, m_lexer->currentOffset());
    1450        
    1451         next();
     1591        next();
     1592#endif
    14521593        info.bodyEndLine = m_lastTokenEndPosition.line;
    14531594        return true;
    14541595    }
     1596   
    14551597    m_lastFunctionName = lastFunctionName;
    14561598    ParserState oldState = saveState();
    1457     info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind);
     1599   
     1600#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1601    switch (info.functionBodyType) {
     1602    case ArrowFunctionBodyBlock: {
     1603        // Consume => in case of arrow function block e.g. x => { return x; }
     1604        next();
     1605   
     1606        info.bodyStartLine = tokenLine();
     1607        info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
     1608           
     1609        info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
     1610        break;
     1611    }
     1612    case StandardFunctionBodyBlock:
     1613    case ArrowFunctionBodyExpression : {
     1614        info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, parseType);
     1615        break;
     1616    }
     1617    }
     1618#else
     1619    info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
     1620#endif
     1621   
    14581622    restoreState(oldState);
    14591623    failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
     
    14711635        semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
    14721636
    1473     info.closeBraceOffset = m_token.m_data.offset;
    1474     unsigned closeBraceLine = m_token.m_data.line;
    1475     unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset;
     1637    JSTokenLocation location = JSTokenLocation(m_token.m_location);
     1638    info.endFunctionOffset = m_token.m_data.offset;
     1639   
     1640#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1641    if (info.functionBodyType == ArrowFunctionBodyExpression) {
     1642        location = locationBeforeLastToken();
     1643        info.endFunctionOffset = location.endOffset;
     1644    }
     1645#endif
    14761646   
    14771647    // Cache the tokenizer state and the function scope the first time the function is parsed.
     
    14791649    static const int minimumFunctionLengthToCache = 16;
    14801650    std::unique_ptr<SourceProviderCacheItem> newInfo;
    1481     int functionLength = info.closeBraceOffset - info.openBraceOffset;
     1651    int functionLength = info.endFunctionOffset - info.startFunctionOffset;
    14821652    if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
    14831653        SourceProviderCacheItemCreationParameters parameters;
     1654        parameters.endFunctionOffset = info.endFunctionOffset;
    14841655        parameters.functionNameStart = functionNameStart;
    1485         parameters.closeBraceLine = closeBraceLine;
    1486         parameters.closeBraceOffset = info.closeBraceOffset;
    1487         parameters.closeBraceLineStartOffset = closeBraceLineStartOffset;
     1656        parameters.lastTockenLine = location.line;
     1657        parameters.lastTockenStartOffset = location.startOffset;
     1658        parameters.lastTockenEndOffset = location.endOffset;
     1659        parameters.lastTockenLineStartOffset = location.lineStartOffset;
     1660#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1661        if (info.functionBodyType == ArrowFunctionBodyExpression) {
     1662            parameters.isBodyArrowExpression = true;
     1663            parameters.tokenType = m_token.m_type;
     1664        }
     1665#endif
    14881666        functionScope->fillParametersForSourceProviderCache(parameters);
    14891667        newInfo = SourceProviderCacheItem::create(parameters);
    1490 
    14911668    }
    14921669   
    14931670    failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
     1671   
     1672#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1673    if (info.functionBodyType == ArrowFunctionBodyExpression)
     1674        failIfFalse(isEndOfArrowFunction(), "Expected the closing ';' ',' ']' ')' '}', line terminator or EOF after arrow function");
     1675    else {
     1676        matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
     1677        next();
     1678    }
     1679#else
    14941680    matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
     1681    next();
     1682#endif
    14951683   
    14961684    if (newInfo)
    1497         m_functionCache->add(info.openBraceOffset, WTF::move(newInfo));
    1498    
    1499     next();
     1685        m_functionCache->add(info.startFunctionOffset, WTF::move(newInfo));
     1686   
    15001687    info.bodyEndLine = m_lastTokenEndPosition.line;
    15011688    return true;
     
    15111698    ParserFunctionInfo<TreeBuilder> info;
    15121699    failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded,
    1513         functionKeywordStart, info)), "Cannot parse this function");
     1700        functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse this function");
    15141701    failIfFalse(info.name, "Function statements must have a name");
    15151702    failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode");
     
    16301817            ParserFunctionInfo<TreeBuilder> methodInfo;
    16311818            bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
    1632             failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false,
    1633                 isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo)), "Cannot parse this method");
     1819            failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
    16341820            failIfFalse(ident && declareVariable(ident), "Cannot declare a method named '", methodInfo.name->impl(), "'");
    16351821            methodInfo.name = isConstructor ? className : ident;
     
    18722058}
    18732059
     2060   
    18742061template <typename LexerType>
    18752062template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
     
    18902077        restoreSavePoint(savePoint);
    18912078    }
     2079   
     2080#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     2081    if (isArrowFunctionParamters())
     2082        return parseArrowFunctionExpression(context);
     2083#endif
     2084   
    18922085    TreeExpression lhs = parseConditionalExpression(context);
    18932086    failIfFalse(lhs, "Cannot parse expression");
     
    21302323    unsigned methodStart = tokenStart();
    21312324    ParserFunctionInfo<TreeBuilder> methodInfo;
    2132     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded,
    2133         methodStart, methodInfo)), "Cannot parse this method");
     2325    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
    21342326    methodInfo.name = methodName;
    21352327    return context.createFunctionExpr(methodLocation, methodInfo);
     
    21582350        failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
    21592351        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, constructorKind, superBinding,
    2160             getterOrSetterStartOffset, info)), "Cannot parse getter definition");
     2352            getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse getter definition");
    21612353    } else {
    21622354        failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
    21632355        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, constructorKind, superBinding,
    2164             getterOrSetterStartOffset, info)), "Cannot parse setter definition");
     2356            getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse setter definition");
    21652357    }
    21662358    if (stringPropertyName)
     
    24292621        ParserFunctionInfo<TreeBuilder> info;
    24302622        info.name = &m_vm->propertyNames->nullIdentifier;
    2431         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded,
    2432             functionKeywordStart, info)), "Cannot parse function expression");
     2623        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse function expression");
    24332624        return context.createFunctionExpr(location, info);
    24342625    }
     
    26692860    return base;
    26702861}
     2862
     2863#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     2864template <typename LexerType>
     2865template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrowFunctionExpression(TreeBuilder& context)
     2866{
     2867    JSTokenLocation location;
     2868
     2869    unsigned functionKeywordStart = tokenStart();
     2870    location = tokenLocation();
     2871    ParserFunctionInfo<TreeBuilder> info;
     2872    info.name = &m_vm->propertyNames->nullIdentifier;
     2873    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, ArrowFunctionParseType)), "Cannot parse arrow function expression");
     2874
     2875    return context.createArrowFunctionExpr(location, info);
     2876}
     2877#endif
    26712878
    26722879static const char* operatorString(bool prefix, unsigned tok)
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r185699 r185989  
    8181
    8282enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
     83#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     84enum FunctionParseType { StandardFunctionParseType, ArrowFunctionParseType };
     85#else
     86enum FunctionParseType { StandardFunctionParseType};
     87#endif
    8388enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
    8489enum FunctionParseMode {
     
    8792    SetterMode,
    8893    MethodMode,
     94#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     95    ArrowFunctionMode
     96#endif
    8997};
    9098enum DeconstructionKind {
     
    431439
    432440    JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
     441    JSTokenLocation locationBeforeLastToken() const { return m_lexer->lastTokenLocation(); }
    433442    Vector<RefPtr<UniquedStringImpl>>&& closedVariables() { return WTF::move(m_closedVariables); }
    434443
     
    612621        return m_token.m_type == IDENT && *m_token.m_data.ident == m_vm->propertyNames->of;
    613622    }
     623   
     624#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     625    ALWAYS_INLINE bool isEndOfArrowFunction()
     626    {
     627        return match(SEMICOLON) || match(COMMA) || match(CLOSEPAREN) || match(CLOSEBRACE) || match(CLOSEBRACKET) || match(EOFTOK) || m_lexer->prevTerminator();
     628    }
     629   
     630    ALWAYS_INLINE bool isArrowFunctionParamters()
     631    {
     632        bool isArrowFunction = false;
     633       
     634        if (match(EOFTOK))
     635            return isArrowFunction;
     636       
     637        SavePoint saveArrowFunctionPoint = createSavePoint();
     638       
     639        if (consume(OPENPAREN)) {
     640            bool isArrowFunctionParamters = true;
     641           
     642            while (consume(IDENT)) {
     643                if (consume(COMMA)) {
     644                    if (!match(IDENT)) {
     645                        isArrowFunctionParamters = false;
     646                        break;
     647                    }
     648                } else
     649                    break;
     650            }
     651           
     652            if (isArrowFunctionParamters) {
     653                if (consume(CLOSEPAREN) && match(ARROWFUNCTION))
     654                    isArrowFunction = true;
     655            }
     656        } else if (consume(IDENT) && match(ARROWFUNCTION))
     657            isArrowFunction = true;
     658
     659        restoreSavePoint(saveArrowFunctionPoint);
     660       
     661        return isArrowFunction;
     662    }
     663#endif
    614664   
    615665    ALWAYS_INLINE unsigned tokenStart()
     
    716766        return result;
    717767    }
    718    
    719     template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode);
     768
     769    template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode, FunctionParseType);
    720770    template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
    721771#if ENABLE(ES6_CLASS_SYNTAX)
     
    757807    template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName);
    758808    template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind = ConstructorKind::None, SuperBinding = SuperBinding::NotNeeded);
    759     template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind);
     809    template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, FunctionParseType);
    760810    template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
    761811    enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
     
    763813    template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&);
    764814
     815#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     816    template <class TreeBuilder> TreeStatement parseArrowFunctionSingleExpressionBody(TreeBuilder&, FunctionParseType);
     817    template <class TreeBuilder> TreeExpression parseArrowFunctionExpression(TreeBuilder&);
     818#endif
     819
    765820    template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern createBindingPattern(TreeBuilder&, DeconstructionKind, const Identifier&, int depth, JSToken);
    766821    template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&, DeconstructionKind, int depth = 0);
     
    768823    template <class TreeBuilder> NEVER_INLINE TreeExpression parseDefaultValueForDeconstructionPattern(TreeBuilder&);
    769824
    770     template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&);
    771    
    772     template <class TreeBuilder> NEVER_INLINE int parseFunctionParameters(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool, AutoPopScopeRef&, ParserFunctionInfo<TreeBuilder>&);
     825    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionParseType);
     826   
     827    template <class TreeBuilder> NEVER_INLINE int parseFunctionParameters(TreeBuilder&, FunctionParseMode, ParserFunctionInfo<TreeBuilder>&);
    773828
    774829#if ENABLE(ES6_CLASS_SYNTAX)
    775830    template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionRequirements, ParserClassInfo<TreeBuilder>&);
    776831#endif
     832
    777833#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
    778834    template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateString parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode, bool& elementIsTail);
     
    794850    }
    795851   
     852
     853#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     854    void setEndOfStatement()
     855    {
     856        m_lexer->setTokenPosition(&m_token);
     857    }
     858#endif
     859
    796860    bool canRecurse()
    797861    {
  • trunk/Source/JavaScriptCore/parser/ParserFunctionInfo.h

    r181973 r185989  
    2929namespace JSC {
    3030
     31#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     32enum FunctionBodyType { ArrowFunctionBodyExpression, ArrowFunctionBodyBlock, StandardFunctionBodyBlock };
     33#endif
     34
    3135template <class TreeBuilder>
    3236struct ParserFunctionInfo {
     
    3438    typename TreeBuilder::FormalParameterList parameters = 0;
    3539    typename TreeBuilder::FunctionBody body = 0;
    36     unsigned openBraceOffset = 0;
    37     unsigned closeBraceOffset = 0;
     40    unsigned startFunctionOffset = 0;
     41    unsigned endFunctionOffset = 0;
    3842    int bodyStartLine = 0;
    3943    int bodyEndLine = 0;
    4044    unsigned bodyStartColumn = 0;
     45#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     46    unsigned arrowFunctionOffset = 0;
     47    unsigned arrowFunctionNextTockenEndOffset = 0;
     48    bool isArrowFunction { false };
     49    bool isEndByTerminator { false };
     50    FunctionBodyType functionBodyType { StandardFunctionBodyBlock };
     51#endif
    4152};
    4253
  • trunk/Source/JavaScriptCore/parser/ParserTokens.h

    r183373 r185989  
    7676    DEBUGGER,
    7777    ELSE,
     78#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     79    ARROWFUNCTION,
     80#endif
    7881#if ENABLE(ES6_CLASS_SYNTAX)
    7982    CLASSTOKEN,
  • trunk/Source/JavaScriptCore/parser/SourceCode.h

    r182034 r185989  
    106106        SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn);
    107107
     108#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     109        SourceCode subArrowExpression(unsigned startArrowFunction, unsigned endArrowFunction, int firstLine, int startColumn);
     110#endif
    108111    private:
    109112        RefPtr<SourceProvider> m_provider;
     
    118121        return SourceCode(StringSourceProvider::create(source, url, startPosition), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt());
    119122    }
     123   
     124#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     125    inline SourceCode SourceCode::subArrowExpression(unsigned startArrowFunction, unsigned endArrowFunction, int firstLine, int startColumn)
     126    {
     127        ASSERT(provider()->source()[startArrowFunction] == '=' && provider()->source()[startArrowFunction + 1] == '>');
     128
     129        startColumn += 1; // Convert to base 1.
     130        return SourceCode(provider(), startArrowFunction, endArrowFunction, firstLine, startColumn);
     131    }
     132#endif
    120133
    121134    inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn)
  • trunk/Source/JavaScriptCore/parser/SourceProviderCacheItem.h

    r184828 r185989  
    3636struct SourceProviderCacheItemCreationParameters {
    3737    unsigned functionNameStart;
    38     unsigned closeBraceLine;
    39     unsigned closeBraceOffset;
    40     unsigned closeBraceLineStartOffset;
     38    unsigned lastTockenLine;
     39    unsigned lastTockenStartOffset;
     40    unsigned lastTockenEndOffset;
     41    unsigned lastTockenLineStartOffset;
     42    unsigned endFunctionOffset;
    4143    bool needsFullActivation;
    4244    bool usesEval;
     
    4446    Vector<RefPtr<UniquedStringImpl>> usedVariables;
    4547    Vector<RefPtr<UniquedStringImpl>> writtenVariables;
     48#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     49    bool isBodyArrowExpression { false };
     50    JSTokenType tokenType { CLOSEBRACE };
     51#endif
    4652};
    4753
     
    5763    ~SourceProviderCacheItem();
    5864
    59     JSToken closeBraceToken() const
     65    JSToken endFunctionToken() const
    6066    {
    6167        JSToken token;
     68#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     69        token.m_type = isBodyArrowExpression ? tokenType : CLOSEBRACE;
     70#else
    6271        token.m_type = CLOSEBRACE;
    63         token.m_data.offset = closeBraceOffset;
    64         token.m_location.startOffset = closeBraceOffset;
    65         token.m_location.endOffset = closeBraceOffset + 1;
    66         token.m_location.line = closeBraceLine;
    67         token.m_location.lineStartOffset = closeBraceLineStartOffset;
     72#endif
     73        token.m_data.offset = lastTockenStartOffset;
     74        token.m_location.startOffset = lastTockenStartOffset;
     75        token.m_location.endOffset = lastTockenEndOffset;
     76        token.m_location.line = lastTockenLine;
     77        token.m_location.lineStartOffset = lastTockenLineStartOffset;
    6878        // token.m_location.sourceOffset is initialized once by the client. So,
    6979        // we do not need to set it here.
     
    7383    unsigned functionNameStart : 31;
    7484    bool needsFullActivation : 1;
     85
     86    unsigned endFunctionOffset : 31;
     87    unsigned lastTockenLine : 31;
     88    unsigned lastTockenStartOffset : 31;
     89    unsigned lastTockenEndOffset: 31;
    7590   
    76     unsigned closeBraceLine : 31;
    7791    bool usesEval : 1;
    7892
    79     unsigned closeBraceOffset : 31;
    8093    bool strictMode : 1;
    8194
    82     unsigned closeBraceLineStartOffset;
     95    unsigned lastTockenLineStartOffset;
    8396    unsigned usedVariablesCount;
    8497    unsigned writtenVariablesCount;
     
    8699    UniquedStringImpl** usedVariables() const { return const_cast<UniquedStringImpl**>(m_variables); }
    87100    UniquedStringImpl** writtenVariables() const { return const_cast<UniquedStringImpl**>(&m_variables[usedVariablesCount]); }
     101#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     102    bool isBodyArrowExpression;
     103    JSTokenType tokenType;
     104#endif
    88105
    89106private:
     
    110127    : functionNameStart(parameters.functionNameStart)
    111128    , needsFullActivation(parameters.needsFullActivation)
    112     , closeBraceLine(parameters.closeBraceLine)
     129    , endFunctionOffset(parameters.endFunctionOffset)
     130    , lastTockenLine(parameters.lastTockenLine)
     131    , lastTockenStartOffset(parameters.lastTockenStartOffset)
     132    , lastTockenEndOffset(parameters.lastTockenEndOffset)
    113133    , usesEval(parameters.usesEval)
    114     , closeBraceOffset(parameters.closeBraceOffset)
    115134    , strictMode(parameters.strictMode)
    116     , closeBraceLineStartOffset(parameters.closeBraceLineStartOffset)
     135    , lastTockenLineStartOffset(parameters.lastTockenLineStartOffset)
    117136    , usedVariablesCount(parameters.usedVariables.size())
    118137    , writtenVariablesCount(parameters.writtenVariables.size())
     138#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     139    , isBodyArrowExpression(parameters.isBodyArrowExpression)
     140    , tokenType(parameters.tokenType)
     141#endif
    119142{
    120143    unsigned j = 0;
  • trunk/Source/JavaScriptCore/parser/SyntaxChecker.h

    r185981 r185989  
    180180    ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
    181181    int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind) { return FunctionBodyResult; }
     182#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     183    ExpressionType createArrowFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     184#endif
     185    void setFunctionNameStart(int, int) { }
    182186    int createArguments() { return ArgumentsResult; }
    183187    int createArguments(int) { return ArgumentsResult; }
Note: See TracChangeset for help on using the changeset viewer.