Ignore:
Timestamp:
Nov 1, 2015, 9:46:17 PM (10 years ago)
Author:
Yusuke Suzuki
Message:

[ES6] Support Generator Syntax
https://bugs.webkit.org/show_bug.cgi?id=150769

Reviewed by Geoffrey Garen.

.:

Added ENABLE_ES6_GENERATORS flag.

  • Source/cmake/OptionsWin.cmake:
  • Source/cmake/WebKitFeatures.cmake:

Source/JavaScriptCore:

This patch implements syntax part of ES6 Generators.

  1. Add ENABLE_ES6_GENERATORS compile time flag. It is disabled by default, and will be enabled once ES6 generator functionality is implemented.
  2. Add lexer support for YIELD. It changes "yield" from reserved-if-strict word to keyword. And it is correct under the ES6 spec.
  3. Implement parsing functionality and YieldExprNode stub. YieldExprNode does not emit meaningful bytecodes yet. This should be implemented in the future patch.
  4. Accept "yield" Identifier as an label etc. under sloppy mode && non-generator code. http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions-static-semantics-early-errors
  • Configurations/FeatureDefines.xcconfig:
  • bytecompiler/NodesCodegen.cpp:

(JSC::YieldExprNode::emitBytecode):

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createYield):

  • parser/Keywords.table:
  • parser/NodeConstructors.h:

(JSC::YieldExprNode::YieldExprNode):

  • parser/Nodes.h:
  • parser/Parser.cpp:

(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::parseStatementListItem):
(JSC::Parser<LexerType>::parseVariableDeclarationList):
(JSC::Parser<LexerType>::parseDestructuringPattern):
(JSC::Parser<LexerType>::parseBreakStatement):
(JSC::Parser<LexerType>::parseContinueStatement):
(JSC::Parser<LexerType>::parseTryStatement):
(JSC::Parser<LexerType>::parseStatement):
(JSC::stringForFunctionMode):
(JSC::Parser<LexerType>::parseFunctionParameters):
(JSC::Parser<LexerType>::parseFunctionInfo):
(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseExpressionOrLabelStatement):
(JSC::Parser<LexerType>::parseExportDeclaration):
(JSC::Parser<LexerType>::parseAssignmentExpression):
(JSC::Parser<LexerType>::parseYieldExpression):
(JSC::Parser<LexerType>::parseProperty):
(JSC::Parser<LexerType>::parsePropertyMethod):
(JSC::Parser<LexerType>::parseGetterSetter):
(JSC::Parser<LexerType>::parseFunctionExpression):
(JSC::Parser<LexerType>::parsePrimaryExpression):
(JSC::Parser<LexerType>::parseArrowFunctionExpression):

  • parser/Parser.h:

(JSC::Scope::Scope):
(JSC::Scope::setSourceParseMode):
(JSC::Scope::isGenerator):
(JSC::Scope::setIsFunction):
(JSC::Scope::setIsGenerator):
(JSC::Scope::setIsModule):
(JSC::Parser::pushScope):
(JSC::Parser::isYIELDMaskedAsIDENT):
(JSC::Parser::matchSpecIdentifier):
(JSC::Parser::saveState):
(JSC::Parser::restoreState):

  • parser/ParserModes.h:

(JSC::isFunctionParseMode):
(JSC::isModuleParseMode):
(JSC::isProgramParseMode):

  • parser/ParserTokens.h:
  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createYield):

  • tests/stress/generator-methods.js: Added.

(Hello.prototype.gen):
(Hello.gen):
(Hello):
(Hello.prototype.set get string_appeared_here):
(Hello.string_appeared_here):
(Hello.prototype.20):
(Hello.20):
(Hello.prototype.42):
(Hello.42):
(let.object.gen):
(let.object.set get string_appeared_here):
(let.object.20):
(let.object.42):

  • tests/stress/generator-syntax.js: Added.

(testSyntax):
(testSyntaxError):
(testSyntaxError.Hello.prototype.get gen):
(testSyntaxError.Hello):
(SyntaxError.Unexpected.token.string_appeared_here.Expected.an.opening.string_appeared_here.before.a.method.testSyntaxError.Hello.prototype.set gen):
(SyntaxError.Unexpected.token.string_appeared_here.Expected.an.opening.string_appeared_here.before.a.method.testSyntaxError.Hello):
(SyntaxError.Unexpected.token.string_appeared_here.Expected.an.opening.string_appeared_here.before.a.method.testSyntaxError.gen):
(testSyntaxError.value):
(testSyntaxError.gen.ng):
(testSyntaxError.gen):
(testSyntax.gen):

  • tests/stress/yield-and-line-terminator.js: Added.

(testSyntax):
(testSyntaxError):
(testSyntax.gen):
(testSyntaxError.gen):

  • tests/stress/yield-label-generator.js: Added.

(testSyntax):
(testSyntaxError):
(testSyntaxError.test):
(SyntaxError.Unexpected.keyword.string_appeared_here.Expected.an.identifier.as.the.target.a.continue.statement.testSyntax.test):

  • tests/stress/yield-label.js: Added.

(yield):
(testSyntaxError):
(testSyntaxError.test):

  • tests/stress/yield-named-accessors-generator.js: Added.

(t1.let.object.get yield):
(t1.let.object.set yield):
(t1):
(t2.let.object.get yield):
(t2.let.object.set yield):
(t2):

  • tests/stress/yield-named-accessors.js: Added.

(t1.let.object.get yield):
(t1.let.object.set yield):
(t1):
(t2.let.object.get yield):
(t2.let.object.set yield):
(t2):

  • tests/stress/yield-named-variable-generator.js: Added.

(testSyntax):
(testSyntaxError):
(testSyntaxError.t1):
(testSyntaxError.t1.yield):
(testSyntax.t1.yield):
(testSyntax.t1):

  • tests/stress/yield-named-variable.js: Added.

(testSyntax):
(testSyntaxError):
(testSyntax.t1):
(testSyntaxError.t1):
(testSyntax.t1.yield):
(testSyntaxError.t1.yield):

  • tests/stress/yield-out-of-generator.js: Added.

(testSyntax):
(testSyntaxError):
(testSyntaxError.hello):
(testSyntaxError.gen.hello):
(testSyntaxError.gen):
(testSyntax.gen):
(testSyntax.gen.ok):
(testSyntaxError.gen.ok):

Source/WebCore:

Added ENABLE_ES6_GENERATORS flag.

  • Configurations/FeatureDefines.xcconfig:

Source/WebKit/mac:

Added ENABLE_ES6_GENERATORS flag.

  • Configurations/FeatureDefines.xcconfig:

Source/WebKit2:

Added ENABLE_ES6_GENERATORS flag.

  • Configurations/FeatureDefines.xcconfig:

Source/WTF:

Added ENABLE_ES6_GENERATORS flag.

  • wtf/FeatureDefines.h:

Tools:

Added ENABLE_ES6_GENERATORS flag.

  • Scripts/webkitperl/FeatureList.pm:

WebKitLibraries:

Added ENABLE_ES6_GENERATORS flag.

  • win/tools/vsprops/FeatureDefines.props:
  • win/tools/vsprops/FeatureDefinesCairo.props:

LayoutTests:

Change "yield" from reserved-if-strict word to keyword.
http://ecma-international.org/ecma-262/6.0/#sec-keywords

  • js/dom/reserved-words-as-property-expected.txt:
  • js/keywords-and-reserved_words-expected.txt:
  • js/let-syntax-expected.txt:
  • js/reserved-words-strict-expected.txt:
  • js/script-tests/keywords-and-reserved_words.js:
  • js/script-tests/reserved-words-strict.js:
File:
1 edited

Legend:

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

    r191110 r191875  
    3030#include "Lexer.h"
    3131#include "JSCInlines.h"
     32#include "SetForScope.h"
    3233#include "SourceProvider.h"
    3334#include "VM.h"
     
    204205    , m_statementDepth(0)
    205206    , m_nonTrivialExpressionCount(0)
     207    , m_functionParsePhase(FunctionParsePhase::Body)
    206208    , m_lastIdentifier(0)
    207209    , m_lastFunctionName(nullptr)
     
    218220    m_token.m_location.lineStartOffset = source.startOffset();
    219221    m_functionCache = vm->addSourceProviderCache(source.provider());
     222
    220223    ScopeRef scope = pushScope();
    221     if (isFunctionParseMode(parseMode))
    222         scope->setIsFunction();
    223     if (isModuleParseMode(parseMode))
    224         scope->setIsModule();
     224    scope->setSourceParseMode(parseMode);
     225
    225226    if (strictMode == JSParserStrictMode::Strict)
    226227        scope->setStrictMode();
     
    242243    ScopeRef scope = currentScope();
    243244    scope->setIsLexicalScope();
     245    SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_functionParsePhase, FunctionParsePhase::Body);
    244246
    245247    bool isArrowFunctionBodyExpression = false;
     
    474476            SavePoint savePoint = createSavePoint();
    475477            next();
    476             if (!match(IDENT) && !match(OPENBRACE) && !match(OPENBRACKET))
     478            // Intentionally use `match(IDENT) || match(LET) || match(YIELD)` and don't use `matchSpecIdentifier()`.
     479            // We would like to fall into parseVariableDeclaration path even if "yield" is not treated as an Identifier.
     480            // For example, under a generator context, matchSpecIdentifier() for "yield" returns `false`.
     481            // But we would like to enter parseVariableDeclaration and raise an error under the context of parseVariableDeclaration
     482            // to raise consistent errors between "var", "const" and "let".
     483            if (!(match(IDENT) || match(LET) || match(YIELD)) && !match(OPENBRACE) && !match(OPENBRACKET))
    477484                shouldParseVariableDeclaration = false;
    478485            restoreSavePoint(savePoint);
     
    586593        declarations++;
    587594        bool hasInitializer = false;
    588         if (match(IDENT) || isLETMaskedAsIDENT()) {
     595        if (matchSpecIdentifier()) {
    589596            failIfTrue(match(LET) && (declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::ConstDeclaration),
    590597                "Can't use 'let' as an identifier name for a LexicalDeclaration");
     
    835842            TreeDestructuringPattern innerPattern = 0;
    836843            JSTokenLocation location = m_token.m_location;
    837             if (match(IDENT) || isLETMaskedAsIDENT()) {
     844            if (matchSpecIdentifier()) {
    838845                failIfTrue(match(LET) && (kind == DestructureToLet || kind == DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
    839846                propertyName = m_token.m_data.ident;
     
    892899
    893900    default: {
    894         if (!match(IDENT) && !isLETMaskedAsIDENT()) {
     901        if (!matchSpecIdentifier()) {
    895902            if (kind == DestructureToExpressions)
    896903                return 0;
     
    11291136        return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
    11301137    }
    1131     failIfFalse(match(IDENT) || isLETMaskedAsIDENT(), "Expected an identifier as the target for a break statement");
     1138    failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a break statement");
    11321139    const Identifier* ident = m_token.m_data.ident;
    11331140    semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
     
    11511158        return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
    11521159    }
    1153     failIfFalse(match(IDENT) || isLETMaskedAsIDENT(), "Expected an identifier as the target for a continue statement");
     1160    failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a continue statement");
    11541161    const Identifier* ident = m_token.m_data.ident;
    11551162    ScopeLabelInfo* label = getLabel(ident);
     
    13331340       
    13341341        handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
    1335         if (!(match(IDENT) || isLETMaskedAsIDENT())) {
     1342        if (!matchSpecIdentifier()) {
    13361343            semanticFailureDueToKeyword("catch variable name");
    13371344            failWithMessage("Expected identifier name as catch target");
     
    14921499        return 0;
    14931500    case IDENT:
     1501    case YIELD:
    14941502        result = parseExpressionOrLabelStatement(context);
    14951503        break;
     
    15811589    case SourceParseMode::MethodMode:
    15821590        return "method";
     1591    case SourceParseMode::GeneratorMode:
     1592        return "generator";
    15831593    case SourceParseMode::ArrowFunctionMode:
    15841594        return "arrow function";
     
    16001610    functionInfo.parameters = parameterList;
    16011611    functionInfo.startOffset = parametersStart;
     1612    SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_functionParsePhase, FunctionParsePhase::Parameters);
    16021613   
    16031614    if (mode == SourceParseMode::ArrowFunctionMode) {
     
    16581669
    16591670template <typename LexerType>
    1660 template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionParseType parseType)
     1671template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionDefinitionType functionDefinitionType)
    16611672{
    16621673    RELEASE_ASSERT(isFunctionParseMode(mode));
    16631674
     1675    bool upperScopeIsGenerator = currentScope()->isGenerator();
    16641676    AutoPopScopeRef functionScope(this, pushScope());
    1665     functionScope->setIsFunction();
     1677    functionScope->setSourceParseMode(mode);
     1678    SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_functionParsePhase, FunctionParsePhase::Body);
    16661679    int functionNameStart = m_token.m_location.startOffset;
    16671680    const Identifier* lastFunctionName = m_lastFunctionName;
     
    16711684    int startColumn;
    16721685    FunctionBodyType functionBodyType;
    1673    
    1674     switch (parseType) {
    1675     case StandardFunctionParseType: {
    1676         RELEASE_ASSERT(mode != SourceParseMode::ArrowFunctionMode);
    1677         if (match(IDENT) || isLETMaskedAsIDENT()) {
     1686
     1687    if (mode == SourceParseMode::ArrowFunctionMode) {
     1688        startLocation = tokenLocation();
     1689        functionInfo.startLine = tokenLine();
     1690        startColumn = tokenColumn();
     1691
     1692        parametersStart = parseFunctionParameters(context, mode, functionInfo);
     1693        propagateError();
     1694
     1695        matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
     1696
     1697        if (m_lexer->prevTerminator())
     1698            failDueToUnexpectedToken();
     1699
     1700        ASSERT(constructorKind == ConstructorKind::None);
     1701
     1702        // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
     1703        // and we need use common approach to parse function body
     1704        next();
     1705        functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
     1706    } else {
     1707        // http://ecma-international.org/ecma-262/6.0/#sec-function-definitions
     1708        // FunctionExpression :
     1709        //     function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
     1710        //
     1711        // FunctionDeclaration[Yield, Default] :
     1712        //     function BindingIdentifier[?Yield] ( FormalParameters ) { FunctionBody }
     1713        //     [+Default] function ( FormalParameters ) { FunctionBody }
     1714        //
     1715        // GeneratorDeclaration[Yield, Default] :
     1716        //     function * BindingIdentifier[?Yield] ( FormalParameters[Yield] ) { GeneratorBody }
     1717        //     [+Default] function * ( FormalParameters[Yield] ) { GeneratorBody }
     1718        //
     1719        // GeneratorExpression :
     1720        //     function * BindingIdentifier[Yield]opt ( FormalParameters[Yield] ) { GeneratorBody }
     1721        //
     1722        // The name of FunctionExpression can accept "yield" even in the context of generator.
     1723        if (functionDefinitionType == FunctionDefinitionType::Expression && mode == SourceParseMode::NormalFunctionMode)
     1724            upperScopeIsGenerator = false;
     1725
     1726        if (matchSpecIdentifier(upperScopeIsGenerator)) {
    16781727            functionInfo.name = m_token.m_data.ident;
    16791728            m_lastFunctionName = functionInfo.name;
     
    17071756
    17081757        functionBodyType = StandardFunctionBodyBlock;
    1709        
    1710         break;
    1711     }
    1712 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    1713     case ArrowFunctionParseType: {
    1714         RELEASE_ASSERT(mode == SourceParseMode::ArrowFunctionMode);
    1715 
    1716         startLocation = tokenLocation();
    1717         functionInfo.startLine = tokenLine();
    1718         startColumn = tokenColumn();
    1719 
    1720         parametersStart = parseFunctionParameters(context, mode, functionInfo);
    1721         propagateError();
    1722        
    1723         matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
    1724        
    1725         if (m_lexer->prevTerminator())
    1726             failDueToUnexpectedToken();
    1727 
    1728         ASSERT(constructorKind == ConstructorKind::None);
    1729        
    1730         // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
    1731         // and we need use common approach to parse function body
    1732         next();
    1733         functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
    1734        
    1735         break;
    1736     }
    1737 #else
    1738     default:
    1739         RELEASE_ASSERT_NOT_REACHED();
    1740 #endif
    1741     }
    1742    
     1758    }
     1759
    17431760    bool isClassConstructor = constructorKind != ConstructorKind::None;
    17441761   
     
    17621779        unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
    17631780       
    1764         bool isArrowFunction = parseType == ArrowFunctionParseType;
     1781        bool isArrowFunction = mode == SourceParseMode::ArrowFunctionMode;
    17651782       
    17661783        functionInfo.body = context.createFunctionMetadata(
     
    18101827    context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
    18111828    if (functionScope->strictMode() && functionInfo.name) {
    1812         RELEASE_ASSERT(mode == SourceParseMode::NormalFunctionMode || mode == SourceParseMode::MethodMode || mode == SourceParseMode::ArrowFunctionMode);
     1829        RELEASE_ASSERT(mode == SourceParseMode::NormalFunctionMode || mode == SourceParseMode::MethodMode || mode == SourceParseMode::ArrowFunctionMode || mode == SourceParseMode::GeneratorMode);
    18131830        semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
    18141831        semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
     
    18751892    next();
    18761893    ParserFunctionInfo<TreeBuilder> functionInfo;
    1877     failIfFalse((parseFunctionInfo(context, FunctionNeedsName, SourceParseMode::NormalFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded,
    1878         functionKeywordStart, functionInfo, StandardFunctionParseType)), "Cannot parse this function");
     1894    SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
     1895#if ENABLE(ES6_GENERATORS)
     1896    if (consume(TIMES))
     1897        parseMode = SourceParseMode::GeneratorMode;
     1898#endif
     1899    failIfFalse((parseFunctionInfo(context, FunctionNeedsName, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
    18791900    failIfFalse(functionInfo.name, "Function statements must have a name");
     1901
    18801902    DeclarationResultMask declarationResult = declareVariable(functionInfo.name);
    18811903    failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
     
    19771999        bool isGetter = false;
    19782000        bool isSetter = false;
     2001        bool isGenerator = false;
     2002#if ENABLE(ES6_GENERATORS)
     2003        if (consume(TIMES))
     2004            isGenerator = true;
     2005#endif
    19792006        switch (m_token.m_type) {
    19802007        case STRING:
     
    19872014            ASSERT(ident);
    19882015            next();
    1989             if (match(IDENT) || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET)) {
     2016            if (!isGenerator && (match(IDENT) || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET))) {
    19902017                isGetter = *ident == propertyNames.get;
    19912018                isSetter = *ident == propertyNames.set;
     
    20172044            ParserFunctionInfo<TreeBuilder> methodInfo;
    20182045            bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
    2019             failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
     2046            SourceParseMode parseMode = SourceParseMode::MethodMode;
     2047            if (isGenerator) {
     2048                isConstructor = false;
     2049                parseMode = SourceParseMode::GeneratorMode;
     2050                semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare a generator named 'prototype'");
     2051                semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare a generator named 'constructor'");
     2052            }
     2053            failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
    20202054            methodInfo.name = isConstructor ? className : ident;
    20212055
     
    21042138            labels.append(LabelInfo(ident, start, end));
    21052139        }
    2106     } while (match(IDENT) || isLETMaskedAsIDENT());
     2140    } while (matchSpecIdentifier());
    21072141    bool isLoop = false;
    21082142    switch (m_token.m_type) {
     
    24672501        const Identifier* localName = nullptr;
    24682502        SavePoint savePoint = createSavePoint();
    2469         if (match(FUNCTION)
     2503
     2504        bool startsWithFunction = match(FUNCTION);
     2505        if (startsWithFunction
    24702506#if ENABLE(ES6_CLASS_SYNTAX)
    24712507                || match(CLASSTOKEN)
     
    24742510            isFunctionOrClassDeclaration = true;
    24752511            next();
    2476             // FIXME: When landing ES6 generators, we need to take care of that '*' comes.
     2512
     2513#if ENABLE(ES6_GENERATORS)
     2514            // ES6 Generators
     2515            if (startsWithFunction && match(TIMES))
     2516                next();
     2517#endif
    24772518            if (match(IDENT))
    24782519                localName = m_token.m_data.ident;
     
    26632704        restoreSavePoint(savePoint);
    26642705    }
    2665    
     2706
     2707#if ENABLE(ES6_GENERATORS)
     2708    if (match(YIELD))
     2709        return parseYieldExpression(context);
     2710#endif
     2711
    26662712#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
    26672713    if (isArrowFunctionParamters())
     
    27292775   
    27302776    return lhs;
     2777}
     2778
     2779template <typename LexerType>
     2780template <class TreeBuilder> TreeExpression Parser<LexerType>::parseYieldExpression(TreeBuilder& context)
     2781{
     2782    // YieldExpression[In] :
     2783    //     yield
     2784    //     yield [no LineTerminator here] AssignmentExpression[?In, Yield]
     2785    //     yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
     2786
     2787    // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions
     2788    failIfFalse(currentScope()->isGenerator(), "Cannot use yield expression out of generator");
     2789
     2790    // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions-static-semantics-early-errors
     2791    failIfTrue(m_functionParsePhase == FunctionParsePhase::Parameters, "Cannot use yield expression within parameters");
     2792
     2793    JSTokenLocation location(tokenLocation());
     2794    ASSERT(match(YIELD));
     2795    SavePoint savePoint = createSavePoint();
     2796    next();
     2797    if (m_lexer->prevTerminator())
     2798        return context.createYield(location);
     2799
     2800    bool delegate = consume(TIMES);
     2801    TreeExpression argument = parseAssignmentExpression(context);
     2802    if (!argument) {
     2803        restoreSavePoint(savePoint);
     2804        next();
     2805        return context.createYield(location);
     2806    }
     2807    return context.createYield(location, argument, delegate);
    27312808}
    27322809
     
    28152892{
    28162893    bool wasIdent = false;
     2894    bool isGenerator = false;
     2895#if ENABLE(ES6_GENERATORS)
     2896    if (consume(TIMES))
     2897        isGenerator = true;
     2898#endif
    28172899    switch (m_token.m_type) {
    28182900    namedProperty:
     
    28232905        const Identifier* ident = m_token.m_data.ident;
    28242906        unsigned getterOrSetterStartOffset = tokenStart();
    2825         if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
     2907        if (complete || (wasIdent && !isGenerator && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
    28262908            nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
    28272909        else
    28282910            nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
    28292911
    2830         if (match(COLON)) {
     2912        if (!isGenerator && match(COLON)) {
    28312913            next();
    28322914            TreeExpression node = parseAssignmentExpression(context);
     
    28372919
    28382920        if (match(OPENPAREN)) {
    2839             auto method = parsePropertyMethod(context, ident);
     2921            auto method = parsePropertyMethod(context, ident, isGenerator);
    28402922            propagateError();
    28412923            return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete);
    28422924        }
     2925        failIfTrue(isGenerator, "Expected a parenthesis for argument list");
    28432926
    28442927        failIfFalse(wasIdent, "Expected an identifier as property name");
     
    28682951        if (match(OPENPAREN)) {
    28692952            const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
    2870             auto method = parsePropertyMethod(context, &ident);
     2953            auto method = parsePropertyMethod(context, &ident, isGenerator);
    28712954            propagateError();
    28722955            return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete);
    28732956        }
     2957        failIfTrue(isGenerator, "Expected a parenthesis for argument list");
    28742958
    28752959        consumeOrFail(COLON, "Expected ':' after property name");
     
    28862970
    28872971        if (match(OPENPAREN)) {
    2888             auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier);
     2972            auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier, isGenerator);
    28892973            propagateError();
    28902974            return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete);
    28912975        }
     2976        failIfTrue(isGenerator, "Expected a parenthesis for argument list");
    28922977
    28932978        consumeOrFail(COLON, "Expected ':' after property name");
     
    29042989
    29052990template <typename LexerType>
    2906 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName)
     2991template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, bool isGenerator)
    29072992{
    29082993    JSTokenLocation methodLocation(tokenLocation());
    29092994    unsigned methodStart = tokenStart();
    29102995    ParserFunctionInfo<TreeBuilder> methodInfo;
    2911     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::MethodMode, false, ConstructorKind::None, SuperBinding::NotNeeded, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method");
     2996    SourceParseMode parseMode = isGenerator ? SourceParseMode::GeneratorMode : SourceParseMode::MethodMode;
     2997    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
    29122998    methodInfo.name = methodName;
    29132999    return context.createFunctionExpr(methodLocation, methodInfo);
     
    29243010    JSTokenLocation location(tokenLocation());
    29253011
    2926     if (match(IDENT) || match(STRING) || isLETMaskedAsIDENT()) {
     3012    if (matchSpecIdentifier() || match(STRING)) {
    29273013        stringPropertyName = m_token.m_data.ident;
    29283014        semanticFailIfTrue(superBinding == SuperBinding::Needed && *stringPropertyName == m_vm->propertyNames->prototype,
     
    29453031    if (type & PropertyNode::Getter) {
    29463032        failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
    2947         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::GetterMode, false, constructorKind, superBinding,
    2948             getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse getter definition");
     3033        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::GetterMode, false, constructorKind, superBinding, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse getter definition");
    29493034    } else {
    29503035        failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
    2951         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::SetterMode, false, constructorKind, superBinding,
    2952             getterOrSetterStartOffset, info, StandardFunctionParseType)), "Cannot parse setter definition");
     3036        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::SetterMode, false, constructorKind, superBinding, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse setter definition");
    29533037    }
    29543038
     
    31513235}
    31523236
     3237template <typename LexerType>
     3238template <class TreeBuilder> TreeExpression Parser<LexerType>::parseFunctionExpression(TreeBuilder& context)
     3239{
     3240    ASSERT(match(FUNCTION));
     3241    JSTokenLocation location(tokenLocation());
     3242    unsigned functionKeywordStart = tokenStart();
     3243    next();
     3244    ParserFunctionInfo<TreeBuilder> functionInfo;
     3245    functionInfo.name = &m_vm->propertyNames->nullIdentifier;
     3246    SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
     3247#if ENABLE(ES6_GENERATORS)
     3248    if (consume(TIMES))
     3249        parseMode = SourceParseMode::GeneratorMode;
     3250#endif
     3251    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Expression)), "Cannot parse function expression");
     3252    return context.createFunctionExpr(location, functionInfo);
     3253}
     3254
    31533255#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
    31543256template <typename LexerType>
     
    32163318    failIfStackOverflow();
    32173319    switch (m_token.m_type) {
    3218     case FUNCTION: {
    3219         JSTokenLocation location(tokenLocation());
    3220         unsigned functionKeywordStart = tokenStart();
    3221         next();
    3222         ParserFunctionInfo<TreeBuilder> info;
    3223         info.name = &m_vm->propertyNames->nullIdentifier;
    3224         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::NormalFunctionMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, StandardFunctionParseType)), "Cannot parse function expression");
    3225         return context.createFunctionExpr(location, info);
    3226     }
     3320    case FUNCTION:
     3321        return parseFunctionExpression(context);
    32273322#if ENABLE(ES6_CLASS_SYNTAX)
    32283323    case CLASSTOKEN: {
     
    33173412        return parseTemplateLiteral(context, LexerType::RawStringsBuildMode::DontBuildRawStrings);
    33183413#endif
     3414    case YIELD:
     3415        if (!strictMode() && !currentScope()->isGenerator())
     3416            goto identifierExpression;
     3417        failDueToUnexpectedToken();
    33193418    case LET:
    33203419        if (!strictMode())
     
    34943593    ParserFunctionInfo<TreeBuilder> info;
    34953594    info.name = &m_vm->propertyNames->nullIdentifier;
    3496     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::ArrowFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, ArrowFunctionParseType)), "Cannot parse arrow function expression");
     3595    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::ArrowFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, FunctionDefinitionType::Expression)), "Cannot parse arrow function expression");
    34973596
    34983597    return context.createArrowFunctionExpr(location, info);
Note: See TracChangeset for help on using the changeset viewer.