Ignore:
Timestamp:
Jul 17, 2015, 11:48:30 AM (10 years ago)
Author:
[email protected]
Message:

Function parameters should be parsed in the same parser arena as the function body
https://bugs.webkit.org/show_bug.cgi?id=145995

Reviewed by Yusuke Suzuki.

Source/JavaScriptCore:

This patch changes how functions are parsed in JSC. A function's
parameters are now parsed in the same arena as the function itself.
This allows us to arena allocate all destructuring AST nodes and
the FunctionParameters node. This will help make implementing ES6
default parameter values sane.

A source code that represents a function now includes the text of the function's
parameters. The starting offset is at the opening parenthesis of the parameter
list or at the starting character of the identifier for arrow functions that
have single arguments and don't start with parenthesis.

For example:

"function (param1, param2) { ... }"


| This offset used to be the starting offset of a function's SourceCode


| This is the new starting offset for a function's SourceCode.

This requires us to change how some offsets are calculated
and also requires us to report some different line numbers for internal
metrics that use a SourceCode's starting line and column numbers.

This patch also does a bit of cleanup with regards to how
functions are parsed in general (especially arrow functions).
It removes some unnecessary #ifdefs and the likes for arrow
to make things clearer and more deliberate.

  • API/JSScriptRef.cpp:

(parseScript):

  • builtins/BuiltinExecutables.cpp:

(JSC::BuiltinExecutables::createExecutableInternal):

  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::generateFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedFunctionExecutable::visitChildren):
(JSC::UnlinkedFunctionExecutable::parameterCount): Deleted.

  • bytecode/UnlinkedCodeBlock.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::DestructuringAssignmentNode::emitBytecode):
(JSC::assignDefaultValueIfUndefined):
(JSC::ArrayPatternNode::collectBoundIdentifiers):
(JSC::DestructuringPatternNode::~DestructuringPatternNode): Deleted.

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createClassExpr):
(JSC::ASTBuilder::createFunctionExpr):
(JSC::ASTBuilder::createFunctionBody):
(JSC::ASTBuilder::createArrowFunctionExpr):
(JSC::ASTBuilder::createGetterOrSetterProperty):
(JSC::ASTBuilder::createElementList):
(JSC::ASTBuilder::createFormalParameterList):
(JSC::ASTBuilder::appendParameter):
(JSC::ASTBuilder::createClause):
(JSC::ASTBuilder::createClauseList):
(JSC::ASTBuilder::createFuncDeclStatement):
(JSC::ASTBuilder::createForInLoop):
(JSC::ASTBuilder::createForOfLoop):
(JSC::ASTBuilder::isResolve):
(JSC::ASTBuilder::createDestructuringAssignment):
(JSC::ASTBuilder::createArrayPattern):
(JSC::ASTBuilder::appendArrayPatternSkipEntry):
(JSC::ASTBuilder::appendArrayPatternEntry):
(JSC::ASTBuilder::appendArrayPatternRestEntry):
(JSC::ASTBuilder::finishArrayPattern):
(JSC::ASTBuilder::createObjectPattern):
(JSC::ASTBuilder::appendObjectPatternEntry):
(JSC::ASTBuilder::createBindingLocation):
(JSC::ASTBuilder::setEndOffset):

  • parser/Lexer.cpp:

(JSC::Lexer<T>::Lexer):
(JSC::Lexer<T>::nextTokenIsColon):
(JSC::Lexer<T>::setTokenPosition):
(JSC::Lexer<T>::lex):
(JSC::Lexer<T>::clear):

  • parser/Lexer.h:

(JSC::Lexer::setIsReparsingFunction):
(JSC::Lexer::isReparsingFunction):
(JSC::Lexer::lineNumber):
(JSC::Lexer::setIsReparsing): Deleted.
(JSC::Lexer::isReparsing): Deleted.

  • parser/NodeConstructors.h:

(JSC::TryNode::TryNode):
(JSC::FunctionParameters::FunctionParameters):
(JSC::FuncExprNode::FuncExprNode):
(JSC::FuncDeclNode::FuncDeclNode):
(JSC::ArrayPatternNode::ArrayPatternNode):
(JSC::ObjectPatternNode::ObjectPatternNode):
(JSC::BindingNode::BindingNode):
(JSC::DestructuringAssignmentNode::DestructuringAssignmentNode):
(JSC::ParameterNode::ParameterNode): Deleted.
(JSC::ArrayPatternNode::create): Deleted.
(JSC::ObjectPatternNode::create): Deleted.
(JSC::BindingNode::create): Deleted.

  • parser/Nodes.cpp:

(JSC::ProgramNode::ProgramNode):
(JSC::EvalNode::EvalNode):
(JSC::FunctionBodyNode::FunctionBodyNode):
(JSC::FunctionBodyNode::finishParsing):
(JSC::FunctionNode::FunctionNode):
(JSC::FunctionNode::finishParsing):
(JSC::FunctionParameters::create): Deleted.
(JSC::FunctionParameters::FunctionParameters): Deleted.
(JSC::FunctionParameters::~FunctionParameters): Deleted.

  • parser/Nodes.h:

(JSC::ProgramNode::startColumn):
(JSC::ProgramNode::endColumn):
(JSC::EvalNode::startColumn):
(JSC::EvalNode::endColumn):
(JSC::FunctionParameters::size):
(JSC::FunctionParameters::at):
(JSC::FunctionParameters::append):
(JSC::FuncExprNode::body):
(JSC::DestructuringPatternNode::~DestructuringPatternNode):
(JSC::DestructuringPatternNode::isBindingNode):
(JSC::DestructuringPatternNode::emitDirectBinding):
(JSC::ArrayPatternNode::appendIndex):
(JSC::ObjectPatternNode::appendEntry):
(JSC::BindingNode::boundProperty):
(JSC::BindingNode::divotStart):
(JSC::BindingNode::divotEnd):
(JSC::DestructuringAssignmentNode::bindings):
(JSC::FuncDeclNode::body):
(JSC::ParameterNode::pattern): Deleted.
(JSC::ParameterNode::nextParam): Deleted.
(JSC::FunctionParameters::patterns): Deleted.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::~Parser):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::allowAutomaticSemicolon):
(JSC::Parser<LexerType>::parseSourceElements):
(JSC::Parser<LexerType>::createBindingPattern):
(JSC::Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements):
(JSC::Parser<LexerType>::tryParseDestructuringPatternExpression):
(JSC::Parser<LexerType>::parseSwitchClauses):
(JSC::Parser<LexerType>::parseSwitchDefaultClause):
(JSC::Parser<LexerType>::parseBlockStatement):
(JSC::Parser<LexerType>::parseStatement):
(JSC::Parser<LexerType>::parseFormalParameters):
(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>::parsePrimaryExpression):
(JSC::Parser<LexerType>::parseMemberExpression):
(JSC::Parser<LexerType>::parseArrowFunctionExpression):
(JSC::operatorString):
(JSC::Parser<LexerType>::parseArrowFunctionSingleExpressionBody): Deleted.

  • parser/Parser.h:

(JSC::Parser::positionBeforeLastNewline):
(JSC::Parser::locationBeforeLastToken):
(JSC::Parser::findCachedFunctionInfo):
(JSC::Parser::isofToken):
(JSC::Parser::isEndOfArrowFunction):
(JSC::Parser::isArrowFunctionParamters):
(JSC::Parser::tokenStart):
(JSC::Parser::isLETMaskedAsIDENT):
(JSC::Parser::autoSemiColon):
(JSC::Parser::setEndOfStatement):
(JSC::Parser::canRecurse):
(JSC::Parser<LexerType>::parse):
(JSC::parse):

  • parser/ParserFunctionInfo.h:
  • parser/ParserModes.h:

(JSC::functionNameIsInScope):

  • parser/SourceCode.h:

(JSC::makeSource):
(JSC::SourceCode::subExpression):
(JSC::SourceCode::subArrowExpression): Deleted.

  • parser/SourceProviderCache.h:

(JSC::SourceProviderCache::get):

  • parser/SourceProviderCacheItem.h:

(JSC::SourceProviderCacheItem::endFunctionToken):
(JSC::SourceProviderCacheItem::usedVariables):
(JSC::SourceProviderCacheItem::writtenVariables):
(JSC::SourceProviderCacheItem::SourceProviderCacheItem):

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::SyntaxChecker):
(JSC::SyntaxChecker::createClassExpr):
(JSC::SyntaxChecker::createFunctionExpr):
(JSC::SyntaxChecker::createFunctionBody):
(JSC::SyntaxChecker::createArrowFunctionExpr):
(JSC::SyntaxChecker::setFunctionNameStart):
(JSC::SyntaxChecker::createArguments):
(JSC::SyntaxChecker::createPropertyList):
(JSC::SyntaxChecker::createElementList):
(JSC::SyntaxChecker::createFormalParameterList):
(JSC::SyntaxChecker::appendParameter):
(JSC::SyntaxChecker::createClause):
(JSC::SyntaxChecker::createClauseList):

  • runtime/CodeCache.cpp:

(JSC::CodeCache::getGlobalCodeBlock):
(JSC::CodeCache::getFunctionExecutableFromGlobalCode):

  • runtime/Completion.cpp:

(JSC::checkSyntax):

  • runtime/Executable.cpp:

(JSC::ProgramExecutable::checkSyntax):

  • tests/controlFlowProfiler/conditional-expression.js:

(testConditionalFunctionCall):

LayoutTests:

  • fast/profiler/anonymous-event-handler-expected.txt:
  • fast/profiler/anonymous-function-called-from-different-contexts-expected.txt:
  • fast/profiler/anonymous-function-calls-built-in-functions-expected.txt:
  • fast/profiler/anonymous-function-calls-eval-expected.txt:
  • fast/profiler/anonymous-functions-with-display-names-expected.txt:
  • fast/profiler/apply-expected.txt:
  • fast/profiler/built-in-function-calls-anonymous-expected.txt:
  • fast/profiler/built-in-function-calls-user-defined-function-expected.txt:
  • fast/profiler/call-expected.txt:
  • fast/profiler/calling-the-function-that-started-the-profiler-from-another-scope-expected.txt:
  • fast/profiler/compare-multiple-profiles-expected.txt:
  • fast/profiler/constructor-expected.txt:
  • fast/profiler/dead-time-expected.txt:
  • fast/profiler/document-dot-write-expected.txt:
  • fast/profiler/event-handler-expected.txt:
  • fast/profiler/execution-context-and-eval-on-same-line-expected.txt:
  • fast/profiler/inline-event-handler-expected.txt:
  • fast/profiler/many-calls-in-the-same-scope-expected.txt:
  • fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt:
  • fast/profiler/multiple-and-different-scoped-function-calls-expected.txt:
  • fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt:
  • fast/profiler/multiple-frames-expected.txt:
  • fast/profiler/named-functions-with-display-names-expected.txt:
  • fast/profiler/nested-anonymous-functon-expected.txt:
  • fast/profiler/nested-start-and-stop-profiler-expected.txt:
  • fast/profiler/one-execution-context-expected.txt:
  • fast/profiler/profile-calls-in-included-file-expected.txt:
  • fast/profiler/profile-with-no-title-expected.txt:
  • fast/profiler/profiling-from-a-nested-location-but-stop-profiling-outside-the-nesting-expected.txt:
  • fast/profiler/profiling-from-a-nested-location-expected.txt:
  • fast/profiler/simple-event-call-expected.txt:
  • fast/profiler/simple-no-level-change-expected.txt:
  • fast/profiler/start-and-stop-profiler-multiple-times-expected.txt:
  • fast/profiler/start-and-stop-profiling-in-the-same-function-expected.txt:
  • fast/profiler/stop-profiling-after-setTimeout-expected.txt:
  • fast/profiler/stop-then-function-call-expected.txt:
  • fast/profiler/two-execution-contexts-expected.txt:
  • fast/profiler/user-defined-function-calls-built-in-functions-expected.txt:
  • fast/profiler/window-dot-eval-expected.txt:
  • js/dom/script-start-end-locations-expected.txt:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r186860 r186959  
    192192template <typename LexerType>
    193193Parser<LexerType>::Parser(
    194     VM* vm, const SourceCode& source, FunctionParameters* parameters,
    195     const Identifier& name, JSParserBuiltinMode builtinMode,
     194    VM* vm, const SourceCode& source, JSParserBuiltinMode builtinMode,
    196195    JSParserStrictMode strictMode, JSParserCodeType codeType,
    197196    ConstructorKind defaultConstructorKind, ThisTDZMode thisTDZMode)
     
    224223    if (strictMode == JSParserStrictMode::Strict)
    225224        scope->setStrictMode();
    226     if (parameters) {
    227         bool hadBindingParameters = false;
    228         for (unsigned i = 0; i < parameters->size(); i++) {
    229             auto parameter = parameters->at(i);
    230             if (!parameter->isBindingNode()) {
    231                 hadBindingParameters = true;
    232                 continue;
    233             }
    234             scope->declareParameter(&static_cast<BindingNode*>(parameter)->boundProperty());
    235         }
    236         if (hadBindingParameters) {
    237             Vector<Identifier> boundParameterNames;
    238             for (unsigned i = 0; i < parameters->size(); i++) {
    239                 auto parameter = parameters->at(i);
    240                 if (parameter->isBindingNode())
    241                     continue;
    242                 parameter->collectBoundIdentifiers(boundParameterNames);
    243             }
    244             for (auto& boundParameterName : boundParameterNames)
    245                 scope->declareVariable(&boundParameterName);
    246         }
    247     }
    248     if (!name.isNull())
    249         scope->declareCallee(&name);
     225
    250226    next();
    251227}
     
    257233
    258234template <typename LexerType>
    259 String Parser<LexerType>::parseInner()
     235String Parser<LexerType>::parseInner(const Identifier& calleeName, FunctionParseMode parseMode)
    260236{
    261237    String parseError = String();
    262238   
    263239    ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
    264     if (m_lexer->isReparsing())
    265         m_statementDepth--;
    266240    ScopeRef scope = currentScope();
    267241    scope->setIsLexicalScope();
    268242
    269     SourceElements* sourceElements = parseSourceElements(context, CheckForStrictMode, StandardFunctionParseType);
    270     if (!sourceElements || !consume(EOFTOK)) {
     243    bool isArrowFunctionBodyExpression = false;
     244    if (m_lexer->isReparsingFunction()) {
     245        ParserFunctionInfo<ASTBuilder> functionInfo;
     246        parseFunctionParameters(context, parseMode, functionInfo);
     247        m_parameters = functionInfo.parameters;
     248
     249#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     250        if (parseMode == ArrowFunctionMode && !hasError()) {
     251            // The only way we could have an error wile reparsing is if we run out of stack space.
     252            RELEASE_ASSERT(match(ARROWFUNCTION));
     253            next();
     254            isArrowFunctionBodyExpression = !match(OPENBRACE);
     255        }
     256#endif
     257    }
     258
     259    if (!calleeName.isNull())
     260        scope->declareCallee(&calleeName);
     261
     262    if (m_lexer->isReparsingFunction())
     263        m_statementDepth--;
     264
     265    SourceElements* sourceElements = nullptr;
     266    // The only way we can error this early is if we reparse a function and we run out of stack space.
     267    if (!hasError()) {
     268        if (isArrowFunctionBodyExpression)
     269            sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
     270        else
     271            sourceElements = parseSourceElements(context, CheckForStrictMode);
     272    }
     273
     274    bool validEnding;
     275    if (isArrowFunctionBodyExpression) {
     276        ASSERT(m_lexer->isReparsingFunction());
     277        // When we reparse and stack overflow, we're not guaranteed a valid ending. If we don't run out of stack space,
     278        // then of course this will always be valid because we already parsed for syntax errors. But we must
     279        // be cautious in case we run out of stack space.
     280        validEnding = isEndOfArrowFunction();
     281    } else
     282        validEnding = consume(EOFTOK);
     283
     284    if (!sourceElements || !validEnding) {
    271285        if (hasError())
    272286            parseError = m_errorMessage;
     
    347361
    348362template <typename LexerType>
    349 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode, FunctionParseType functionParseType)
     363template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
    350364{
    351365    const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
     
    356370    auto savePoint = createSavePoint();
    357371    bool hasSetStrict = false;
    358    
    359 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    360     if (match(ARROWFUNCTION)) {
    361         TreeStatement arrowfunctionStatement = parseArrowFunctionSingleExpressionBody(context, functionParseType);
    362            
    363         if (arrowfunctionStatement) {
    364             context.setEndOffset(arrowfunctionStatement, m_lastTokenEndPosition.offset);
    365             context.appendStatement(sourceElements, arrowfunctionStatement);
    366         }
    367        
    368         propagateError();
    369         return sourceElements;
    370     }
    371 #else
    372     UNUSED_PARAM(functionParseType);
    373 #endif
    374372   
    375373    while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
     
    663661}
    664662
    665 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    666 template <typename LexerType>
    667 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseArrowFunctionSingleExpressionBody(TreeBuilder& context, FunctionParseType parseType)
    668 {
    669     ASSERT(match(ARROWFUNCTION));
    670 
    671     // When reparsing phase, parseType becomes StandardFunctionParseType even if the function is arrow function.
    672     // This condition considers the following situations.
    673     // (1): If we are in the reparsing phase, this arrow function is already parsed once, so there is no syntax error.
    674     // (2): But if we are not in the reparsing phase, we should check this function is called in the context of the arrow function.
    675     if (!m_lexer->isReparsing() && parseType != ArrowFunctionParseType)
    676         failDueToUnexpectedToken();
    677    
     663template <typename LexerType>
     664template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context)
     665{
     666    ASSERT(!match(OPENBRACE));
     667
    678668    JSTokenLocation location(tokenLocation());
    679669    JSTextPosition start = tokenStartPosition();
    680     JSTextPosition end = tokenEndPosition();
    681 
    682     next();
    683670
    684671    failIfStackOverflow();
     
    690677    failIfFalse(isEndOfArrowFunction(), "Expected a ';', ']', '}', ')', ',', line terminator or EOF following a arrow function statement");
    691678
    692     end = tokenEndPosition();
     679    JSTextPosition end = tokenEndPosition();
    693680   
    694681    if (!m_lexer->prevTerminator())
    695682        setEndOfStatement();
    696683
    697     return context.createReturnStatement(location, expr, start, end);
    698 }
    699 #endif
     684    TreeSourceElements sourceElements = context.createSourceElements();
     685    TreeStatement body = context.createReturnStatement(location, expr, start, end);
     686    context.setEndOffset(body, m_lastTokenEndPosition.offset);
     687    context.appendStatement(sourceElements, body);
     688
     689    return sourceElements;
     690}
    700691
    701692template <typename LexerType>
     
    12301221    failIfFalse(condition, "Cannot parse switch clause");
    12311222    consumeOrFail(COLON, "Expected a ':' after switch clause expression");
    1232     TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
     1223    TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
    12331224    failIfFalse(statements, "Cannot parse the body of a switch clause");
    12341225    TreeClause clause = context.createClause(condition, statements);
     
    12431234        failIfFalse(condition, "Cannot parse switch case expression");
    12441235        consumeOrFail(COLON, "Expected a ':' after switch clause expression");
    1245         TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
     1236        TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
    12461237        failIfFalse(statements, "Cannot parse the body of a switch clause");
    12471238        clause = context.createClause(condition, statements);
     
    12601251    next();
    12611252    consumeOrFail(COLON, "Expected a ':' after switch default clause");
    1262     TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
     1253    TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
    12631254    failIfFalse(statements, "Cannot parse the body of a switch default clause");
    12641255    TreeClause result = context.createClause(0, statements);
     
    13591350        return result;
    13601351    }
    1361     TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode, StandardFunctionParseType);
     1352    TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
    13621353    failIfFalse(subtree, "Cannot parse the body of the block statement");
    13631354    matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
     
    14671458
    14681459template <typename LexerType>
    1469 template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
     1460template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, unsigned& parameterCount)
    14701461{
    14711462    auto parameter = parseDestructuringPattern(context, DestructureToParameters);
    14721463    failIfFalse(parameter, "Cannot parse parameter pattern");
    1473     TreeFormalParameterList list = context.createFormalParameterList(parameter);
    1474     TreeFormalParameterList tail = list;
     1464    context.appendParameter(list, parameter);
     1465    parameterCount++;
    14751466    while (consume(COMMA)) {
    14761467        parameter = parseDestructuringPattern(context, DestructureToParameters);
    14771468        failIfFalse(parameter, "Cannot parse parameter pattern");
    1478         tail = context.createFormalParameterList(tail, parameter);
    1479     }
    1480     return list;
     1469        context.appendParameter(list, parameter);
     1470        parameterCount++;
     1471    }
     1472    return true;
    14811473}
    14821474
    14831475template <typename LexerType>
    14841476template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
    1485     TreeBuilder& context, int functionKeywordStart, int functionNameStart,
    1486     int parametersStart, ConstructorKind constructorKind, FunctionParseType parseType)
    1487 {
    1488     JSTokenLocation startLocation(tokenLocation());
    1489     unsigned startColumn = tokenColumn();
    1490 
    1491     if (parseType == StandardFunctionParseType) {
     1477    TreeBuilder& context, const JSTokenLocation& startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart,
     1478    ConstructorKind constructorKind, FunctionBodyType bodyType, unsigned parameterCount, FunctionParseMode parseMode)
     1479{
     1480    if (bodyType == StandardFunctionBodyBlock || bodyType == ArrowFunctionBodyBlock) {
    14921481        next();
    14931482        if (match(CLOSEBRACE)) {
    14941483            unsigned endColumn = tokenColumn();
    1495             return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
     1484            return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, parameterCount, parseMode);
    14961485        }
    14971486    }
     
    14991488    DepthManager statementDepth(&m_statementDepth);
    15001489    m_statementDepth = 0;
    1501     typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get());
    1502 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    1503     failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, parseType), parseType == StandardFunctionParseType ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
    1504 #else
    1505     failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode, StandardFunctionParseType), "Cannot parse body of this function");
    1506 #endif
     1490    SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
     1491    if (bodyType == ArrowFunctionBodyExpression)
     1492        failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse body of this arrow function");
     1493    else
     1494        failIfFalse(parseSourceElements(syntaxChecker, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
    15071495    unsigned endColumn = tokenColumn();
    1508     return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind);
     1496    return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, parameterCount, parseMode);
    15091497}
    15101498
     
    15161504    case SetterMode:
    15171505        return "setter";
    1518     case FunctionMode:
     1506    case NormalFunctionMode:
    15191507        return "function";
    15201508    case MethodMode:
    15211509        return "method";
    1522 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    15231510    case ArrowFunctionMode:
    15241511        return "arrow function";
    1525 #endif
     1512    case NotAFunctionMode:
     1513        RELEASE_ASSERT_NOT_REACHED();
     1514        return "";
    15261515    }
    15271516    RELEASE_ASSERT_NOT_REACHED();
     
    15291518}
    15301519
    1531 template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionParseMode mode, ParserFunctionInfo<TreeBuilder>& info)
    1532 {
     1520template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, FunctionParseMode mode, ParserFunctionInfo<TreeBuilder>& functionInfo)
     1521{
     1522    RELEASE_ASSERT(mode != NotAFunctionMode);
    15331523    int parametersStart = m_token.m_location.startOffset;
    1534    
    1535 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1524    TreeFormalParameterList parameterList = context.createFormalParameterList();
     1525    functionInfo.parameters = parameterList;
     1526    functionInfo.startOffset = parametersStart;
     1527   
    15361528    if (mode == ArrowFunctionMode) {
    15371529        if (!match(IDENT) && !match(OPENPAREN)) {
     
    15421534                next();
    15431535               
    1544                 if (!match(CLOSEPAREN)) {
    1545                     info.parameters = parseFormalParameters(context);
    1546                     failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
    1547                 }
     1536                if (match(CLOSEPAREN))
     1537                    functionInfo.parameterCount = 0;
     1538                else
     1539                    failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
    15481540               
    15491541                consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
    15501542            } else {
     1543                functionInfo.parameterCount = 1;
    15511544                auto parameter = parseDestructuringPattern(context, DestructureToParameters);
    15521545                failIfFalse(parameter, "Cannot parse parameter pattern");
    1553                 info.parameters = context.createFormalParameterList(parameter);
    1554                 failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
     1546                context.appendParameter(parameterList, parameter);
    15551547            }
    15561548        }
    1557        
     1549
    15581550        return parametersStart;
    15591551    }
    1560 #endif
    1561    
     1552
    15621553    if (!consume(OPENPAREN)) {
    15631554        semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
     
    15651556    }
    15661557
    1567     if (mode == GetterMode)
     1558    if (mode == GetterMode) {
    15681559        consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
    1569     else if (mode == SetterMode) {
     1560        functionInfo.parameterCount = 0;
     1561    } else if (mode == SetterMode) {
    15701562        failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
    15711563        auto parameter = parseDestructuringPattern(context, DestructureToParameters);
    15721564        failIfFalse(parameter, "setter functions must have one parameter");
    1573         info.parameters = context.createFormalParameterList(parameter);
     1565        context.appendParameter(parameterList, parameter);
     1566        functionInfo.parameterCount = 1;
    15741567        failIfTrue(match(COMMA), "setter functions must have one parameter");
    15751568        consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
    15761569    } else {
    1577         if (!match(CLOSEPAREN)) {
    1578             info.parameters = parseFormalParameters(context);
    1579             failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode));
    1580         }
     1570        if (match(CLOSEPAREN))
     1571            functionInfo.parameterCount = 0;
     1572        else
     1573            failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
    15811574        consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
    15821575    }
    1583    
     1576
    15841577    return parametersStart;
    15851578}
    15861579
    15871580template <typename LexerType>
    1588 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)
    1589 {
     1581template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionParseType parseType)
     1582{
     1583    RELEASE_ASSERT(mode != NotAFunctionMode);
     1584
    15901585    AutoPopScopeRef functionScope(this, pushScope());
    15911586    functionScope->setIsFunction();
     
    15941589    m_lastFunctionName = nullptr;
    15951590    int parametersStart;
     1591    JSTokenLocation startLocation;
     1592    int startColumn;
     1593    FunctionBodyType functionBodyType;
    15961594   
    15971595    switch (parseType) {
    15981596    case StandardFunctionParseType: {
     1597        RELEASE_ASSERT(mode != ArrowFunctionMode);
    15991598        if (match(IDENT) || isLETMaskedAsIDENT()) {
    1600             info.name = m_token.m_data.ident;
    1601             m_lastFunctionName = info.name;
     1599            functionInfo.name = m_token.m_data.ident;
     1600            m_lastFunctionName = functionInfo.name;
    16021601            next();
    16031602            if (!nameIsInContainingScope)
    1604                 failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
     1603                failIfFalseIfStrict(functionScope->declareVariable(functionInfo.name), "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
    16051604        } else if (requirements == FunctionNeedsName) {
    1606             if (match(OPENPAREN) && mode == FunctionMode)
     1605            if (match(OPENPAREN) && mode == NormalFunctionMode)
    16071606                semanticFail("Function statements must have a name");
    16081607            semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
     
    16101609            return false;
    16111610        }
    1612        
    1613         parametersStart = parseFunctionParameters(context, mode, info);
     1611
     1612        startLocation = tokenLocation();
     1613        functionInfo.startLine = tokenLine();
     1614        startColumn = tokenColumn();
     1615
     1616        parametersStart = parseFunctionParameters(context, mode, functionInfo);
    16141617        propagateError();
    16151618       
     
    16231626            expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
    16241627        }
    1625        
    1626         info.startFunctionOffset = m_token.m_data.offset;
     1628
     1629        functionBodyType = StandardFunctionBodyBlock;
    16271630       
    16281631        break;
     
    16301633#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    16311634    case ArrowFunctionParseType: {
    1632         parametersStart = parseFunctionParameters(context, ArrowFunctionMode, info);
     1635        RELEASE_ASSERT(mode == ArrowFunctionMode);
     1636
     1637        startLocation = tokenLocation();
     1638        functionInfo.startLine = tokenLine();
     1639        startColumn = tokenColumn();
     1640
     1641        parametersStart = parseFunctionParameters(context, mode, functionInfo);
    16331642        propagateError();
    16341643       
     
    16401649        ASSERT(constructorKind == ConstructorKind::None);
    16411650       
    1642         info.arrowFunctionOffset = m_token.m_data.offset;
    16431651        // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
    16441652        // and we need use common approach to parse function body
    1645         SavePoint savePoint = createSavePoint();
     1653        next();
     1654        functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
    16461655       
    1647         next();
    1648         info.functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
    1649         info.startFunctionOffset = (info.functionBodyType == ArrowFunctionBodyBlock) ? m_token.m_data.offset : info.arrowFunctionOffset;
    1650        
    1651         restoreSavePoint(savePoint);
    1652 
    1653         break;
    1654     }
     1656        break;
     1657    }
     1658#else
     1659    default:
     1660        RELEASE_ASSERT_NOT_REACHED();
    16551661#endif
    16561662    }
     
    16581664    bool isClassConstructor = constructorKind != ConstructorKind::None;
    16591665
    1660     info.bodyStartLine = tokenLine();
    1661     info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
    1662     JSTokenLocation startLocation(tokenLocation());
     1666    functionInfo.bodyStartColumn = startColumn;
    16631667   
    16641668    // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
    1665     if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.startFunctionOffset) : 0) {
     1669    if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(functionInfo.startOffset) : 0) {
    16661670        // If we're in a strict context, the cached function info must say it was strict too.
    16671671        ASSERT(!strictMode() || cachedInfo->strictMode);
     
    16721676        endLocation.lineStartOffset = cachedInfo->lastTockenLineStartOffset;
    16731677
    1674         bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine);
     1678        bool endColumnIsOnStartLine = (endLocation.line == functionInfo.startLine);
    16751679        ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
    16761680        unsigned bodyEndColumn = endColumnIsOnStartLine ?
     
    16791683        unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
    16801684
    1681         info.body = context.createFunctionBody(
    1682             startLocation, endLocation, info.bodyStartColumn, bodyEndColumn,
     1685        functionInfo.body = context.createFunctionBody(
     1686            startLocation, endLocation, functionInfo.bodyStartColumn, bodyEndColumn,
    16831687            functionKeywordStart, functionNameStart, parametersStart,
    1684             cachedInfo->strictMode, constructorKind);
     1688            cachedInfo->strictMode, constructorKind, cachedInfo->parameterCount, mode);
    16851689       
    16861690        functionScope->restoreFromSourceProviderCache(cachedInfo);
     
    16941698        m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
    16951699        m_lexer->setLineNumber(m_token.m_location.line);
    1696         info.endFunctionOffset = cachedInfo->endFunctionOffset;
    1697 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
     1700        functionInfo.endOffset = cachedInfo->endFunctionOffset;
     1701
    16981702        if (parseType == ArrowFunctionParseType)
    1699             info.functionBodyType = cachedInfo->isBodyArrowExpression ?  ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
     1703            functionBodyType = cachedInfo->isBodyArrowExpression ?  ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
    17001704        else
    1701             info.functionBodyType = StandardFunctionBodyBlock;
     1705            functionBodyType = StandardFunctionBodyBlock;
    17021706       
    1703         switch (info.functionBodyType) {
     1707        switch (functionBodyType) {
    17041708        case ArrowFunctionBodyExpression:
    17051709            next();
    1706             context.setEndOffset(info.body, m_lexer->currentOffset());
     1710            context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
    17071711            break;
    17081712        case ArrowFunctionBodyBlock:
    17091713        case StandardFunctionBodyBlock:
    1710             context.setEndOffset(info.body, m_lexer->currentOffset());
     1714            context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
    17111715            next();
    17121716            break;
    17131717        }
    1714 #else
    1715         context.setEndOffset(info.body, m_lexer->currentOffset());
    1716         next();
    1717 #endif
    1718         info.bodyEndLine = m_lastTokenEndPosition.line;
     1718        functionInfo.endLine = m_lastTokenEndPosition.line;
    17191719        return true;
    17201720    }
     
    17231723    ParserState oldState = saveState();
    17241724   
    1725 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    1726     switch (info.functionBodyType) {
    1727     case ArrowFunctionBodyBlock: {
    1728         // Consume => in case of arrow function block e.g. x => { return x; }
    1729         next();
    1730    
    1731         info.bodyStartLine = tokenLine();
    1732         info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
    1733            
    1734         info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
    1735         break;
    1736     }
    1737     case StandardFunctionBodyBlock:
    1738     case ArrowFunctionBodyExpression : {
    1739         info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, parseType);
    1740         break;
    1741     }
    1742     }
    1743 #else
    1744     info.body = parseFunctionBody(context, functionKeywordStart, functionNameStart, parametersStart, constructorKind, StandardFunctionParseType);
    1745 #endif
     1725    functionInfo.body = parseFunctionBody(context, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, functionBodyType, functionInfo.parameterCount, mode);
    17461726   
    17471727    restoreState(oldState);
    1748     failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
    1749     context.setEndOffset(info.body, m_lexer->currentOffset());
    1750     if (functionScope->strictMode() && info.name) {
    1751         RELEASE_ASSERT(mode == FunctionMode || mode == MethodMode);
    1752         semanticFailIfTrue(m_vm->propertyNames->arguments == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
    1753         semanticFailIfTrue(m_vm->propertyNames->eval == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
     1728    failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
     1729    context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
     1730    if (functionScope->strictMode() && functionInfo.name) {
     1731        RELEASE_ASSERT(mode == NormalFunctionMode || mode == MethodMode);
     1732        semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
     1733        semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
    17541734    }
    17551735    if (functionScope->hasDirectSuper()) {
     
    17611741
    17621742    JSTokenLocation location = JSTokenLocation(m_token.m_location);
    1763     info.endFunctionOffset = m_token.m_data.offset;
    1764    
    1765 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    1766     if (info.functionBodyType == ArrowFunctionBodyExpression) {
     1743    functionInfo.endOffset = m_token.m_data.offset;
     1744   
     1745    if (functionBodyType == ArrowFunctionBodyExpression) {
    17671746        location = locationBeforeLastToken();
    1768         info.endFunctionOffset = location.endOffset;
    1769     }
    1770 #endif
     1747        functionInfo.endOffset = location.endOffset;
     1748    }
    17711749   
    17721750    // Cache the tokenizer state and the function scope the first time the function is parsed.
     
    17741752    static const int minimumFunctionLengthToCache = 16;
    17751753    std::unique_ptr<SourceProviderCacheItem> newInfo;
    1776     int functionLength = info.endFunctionOffset - info.startFunctionOffset;
     1754    int functionLength = functionInfo.endOffset - functionInfo.startOffset;
    17771755    if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
    17781756        SourceProviderCacheItemCreationParameters parameters;
    1779         parameters.endFunctionOffset = info.endFunctionOffset;
     1757        parameters.endFunctionOffset = functionInfo.endOffset;
    17801758        parameters.functionNameStart = functionNameStart;
    17811759        parameters.lastTockenLine = location.line;
     
    17831761        parameters.lastTockenEndOffset = location.endOffset;
    17841762        parameters.lastTockenLineStartOffset = location.lineStartOffset;
    1785 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    1786         if (info.functionBodyType == ArrowFunctionBodyExpression) {
     1763        parameters.parameterCount = functionInfo.parameterCount;
     1764        if (functionBodyType == ArrowFunctionBodyExpression) {
    17871765            parameters.isBodyArrowExpression = true;
    17881766            parameters.tokenType = m_token.m_type;
    17891767        }
    1790 #endif
    17911768        functionScope->fillParametersForSourceProviderCache(parameters);
    17921769        newInfo = SourceProviderCacheItem::create(parameters);
     
    17951772    popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
    17961773   
    1797 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    1798     if (info.functionBodyType == ArrowFunctionBodyExpression)
     1774    if (functionBodyType == ArrowFunctionBodyExpression)
    17991775        failIfFalse(isEndOfArrowFunction(), "Expected the closing ';' ',' ']' ')' '}', line terminator or EOF after arrow function");
    18001776    else {
     
    18021778        next();
    18031779    }
    1804 #else
    1805     matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
    1806     next();
    1807 #endif
    18081780   
    18091781    if (newInfo)
    1810         m_functionCache->add(info.startFunctionOffset, WTF::move(newInfo));
    1811    
    1812     info.bodyEndLine = m_lastTokenEndPosition.line;
     1782        m_functionCache->add(functionInfo.startOffset, WTF::move(newInfo));
     1783   
     1784    functionInfo.endLine = m_lastTokenEndPosition.line;
    18131785    return true;
    18141786}
     
    18211793    unsigned functionKeywordStart = tokenStart();
    18221794    next();
    1823     ParserFunctionInfo<TreeBuilder> info;
    1824     failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded,
    1825         functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse this function");
    1826     failIfFalse(info.name, "Function statements must have a name");
    1827     failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode");
    1828     return context.createFuncDeclStatement(location, info);
     1795    ParserFunctionInfo<TreeBuilder> functionInfo;
     1796    failIfFalse((parseFunctionInfo(context, FunctionNeedsName, NormalFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded,
     1797        functionKeywordStart, functionInfo, StandardFunctionParseType)), "Cannot parse this function");
     1798    failIfFalse(functionInfo.name, "Function statements must have a name");
     1799    failIfFalseIfStrict(declareVariable(functionInfo.name), "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
     1800    return context.createFuncDeclStatement(location, functionInfo);
    18291801}
    18301802
     
    19401912            ParserFunctionInfo<TreeBuilder> methodInfo;
    19411913            bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
    1942             failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? FunctionMode : MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
     1914            failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? NormalFunctionMode : MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
    19431915            failIfFalse(ident && declareVariable(ident), "Cannot declare a method named '", methodInfo.name->impl(), "'");
    19441916            methodInfo.name = isConstructor ? className : ident;
     
    27582730        ParserFunctionInfo<TreeBuilder> info;
    27592731        info.name = &m_vm->propertyNames->nullIdentifier;
    2760         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse function expression");
     2732        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, NormalFunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse function expression");
    27612733        return context.createFunctionExpr(location, info);
    27622734    }
     
    30032975}
    30042976
    3005 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    30062977template <typename LexerType>
    30072978template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrowFunctionExpression(TreeBuilder& context)
     
    30132984    ParserFunctionInfo<TreeBuilder> info;
    30142985    info.name = &m_vm->propertyNames->nullIdentifier;
    3015     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, ArrowFunctionParseType)), "Cannot parse arrow function expression");
     2986    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, ArrowFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, ArrowFunctionParseType)), "Cannot parse arrow function expression");
    30162987
    30172988    return context.createArrowFunctionExpr(location, info);
    30182989}
    3019 #endif
    30202990
    30212991static const char* operatorString(bool prefix, unsigned tok)
Note: See TracChangeset for help on using the changeset viewer.