diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 594e9f53e6df..aceacf4d55fa 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -192,6 +192,33 @@ class FullParseHandler return new_(kind, op, first, second, third); } + ParseNode *newStatementList(unsigned blockid, const TokenPos &pos) { + ParseNode *pn = new_(PNK_STATEMENTLIST, pos); + if (pn) + pn->pn_blockid = blockid; + return pn; + } + + template + void addStatementToList(ParseNode *list, ParseNode *stmt, PC *pc) { + JS_ASSERT(list->isKind(PNK_STATEMENTLIST)); + + if (stmt->isKind(PNK_FUNCTION)) { + if (pc->atBodyLevel()) { + // PNX_FUNCDEFS notifies the emitter that the block contains + // body-level function definitions that should be processed + // before the rest of nodes. + list->pn_xflags |= PNX_FUNCDEFS; + } else { + // General deoptimization was done in Parser::functionDef. + JS_ASSERT_IF(pc->sc->isFunctionBox(), + pc->sc->asFunctionBox()->hasExtensibleScope()); + } + } + + list->append(stmt); + } + ParseNode *newEmptyStatement(const TokenPos &pos) { return new_(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) NULL); } diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 03f9cd81d927..835de022d68f 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -927,10 +927,15 @@ struct TernaryNode : public ParseNode struct ListNode : public ParseNode { - ListNode(ParseNodeKind kind, JSOp op, ParseNode *kid) - : ParseNode(kind, op, PN_LIST) + ListNode(ParseNodeKind kind, const TokenPos &pos) + : ParseNode(kind, JSOP_NOP, PN_LIST, pos) + { + makeEmpty(); + } + + ListNode(ParseNodeKind kind, JSOp op, ParseNode *kid) + : ParseNode(kind, op, PN_LIST, kid->pn_pos) { - pn_pos = kid->pn_pos; initList(kid); } diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 491450929fa9..6ed6306691ba 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1718,17 +1718,16 @@ Parser::checkFunctionDefinition(HandlePropertyName funName, return false; } - /* - * As a SpiderMonkey-specific extension, non-body-level function - * statements (e.g., functions in an "if" or "while" block) are - * dynamically bound when control flow reaches the statement. The - * emitter normally emits functions in two passes (see PNK_ARGSBODY). - */ if (bodyLevel) { JS_ASSERT(pn->functionIsHoisted()); JS_ASSERT_IF(pc->sc->isFunctionBox(), !pn->pn_cookie.isFree()); JS_ASSERT_IF(!pc->sc->isFunctionBox(), pn->pn_cookie.isFree()); } else { + /* + * As a SpiderMonkey-specific extension, non-body-level function + * statements (e.g., functions in an "if" or "while" block) are + * dynamically bound when control flow reaches the statement. + */ JS_ASSERT(!pc->sc->strict); JS_ASSERT(pn->pn_cookie.isFree()); if (pc->sc->isFunctionBox()) { @@ -2450,40 +2449,10 @@ Parser::maybeParseDirective(Node pn, bool *cont) return true; } -template <> -void -Parser::addStatementToList(ParseNode *pn, ParseNode *kid) -{ - JS_ASSERT(pn->isKind(PNK_STATEMENTLIST)); - - if (kid->isKind(PNK_FUNCTION)) { - /* - * PNX_FUNCDEFS notifies the emitter that the block contains body- - * level function definitions that should be processed before the - * rest of nodes. - */ - if (pc->atBodyLevel()) { - pn->pn_xflags |= PNX_FUNCDEFS; - } else { - /* General deoptimization was done in functionDef. */ - JS_ASSERT_IF(pc->sc->isFunctionBox(), pc->sc->asFunctionBox()->hasExtensibleScope()); - } - } - - pn->append(kid); - pn->pn_pos.end = kid->pn_pos.end; -} - -template <> -void -Parser::addStatementToList(Node pn, Node kid) -{ -} - /* - * Parse the statements in a block, creating a TOK_LC node that lists the - * statements' trees. If called from block-parsing code, the caller must - * match { before and } after. + * Parse the statements in a block, creating a StatementList node that lists + * the statements. If called from block-parsing code, the caller must match + * '{' before and '}' after. */ template typename ParseHandler::Node @@ -2491,10 +2460,9 @@ Parser::statements() { JS_CHECK_RECURSION(context, return null()); - Node pn = handler.newList(PNK_STATEMENTLIST); + Node pn = handler.newStatementList(pc->blockid(), pos()); if (!pn) return null(); - handler.setBlockId(pn, pc->blockid()); Node saveBlock = pc->blockNode; pc->blockNode = pn; @@ -2522,7 +2490,7 @@ Parser::statements() return null(); } - addStatementToList(pn, next); + handler.addStatementToList(pn, next, pc); } /* @@ -2533,8 +2501,6 @@ Parser::statements() if (pc->blockNode != pn) pn = pc->blockNode; pc->blockNode = saveBlock; - - handler.setEndPosition(pn, pos().end); return pn; } @@ -4255,11 +4221,9 @@ Parser::switchStatement() if (!GenerateBlockId(pc, pc->topStmt->blockid)) return null(); - /* The default case has pn_left == NULL */ - Node caseList = handler.newList(PNK_STATEMENTLIST); + Node caseList = handler.newStatementList(pc->blockid(), pos()); if (!caseList) return null(); - handler.setBlockId(caseList, pc->blockid()); Node saveBlock = pc->blockNode; pc->blockNode = caseList; @@ -4277,7 +4241,7 @@ Parser::switchStatement() return null(); } seenDefault = true; - caseExpr = null(); + caseExpr = null(); // The default case has pn_left == NULL. break; case TOK_CASE: @@ -4296,10 +4260,9 @@ Parser::switchStatement() MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE); - Node body = handler.newList(PNK_STATEMENTLIST); + Node body = handler.newStatementList(pc->blockid(), pos()); if (!body) return null(); - handler.setBlockId(body, pc->blockid()); while ((tt = tokenStream.peekToken(TSF_OPERAND)) != TOK_RC && tt != TOK_CASE && tt != TOK_DEFAULT) { diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index c54c39bd7f1e..f0a7fb8b7d7f 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -486,7 +486,6 @@ struct Parser : private AutoGCRooter, public StrictModeGetter bool setAssignmentLhsOps(Node pn, JSOp op); bool matchInOrOf(bool *isForOfp); - void addStatementToList(Node pn, Node kid); bool checkFunctionArguments(); bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom); bool checkFunctionDefinition(HandlePropertyName funName, Node *pn, FunctionSyntaxKind kind, diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 684427a6796e..388ede9af3bf 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -100,6 +100,8 @@ class SyntaxParseHandler return NodeGeneric; } + Node newStatementList(unsigned blockid, const TokenPos &pos) { return NodeGeneric; } + void addStatementToList(Node list, Node stmt, ParseContext *pc) {} Node newEmptyStatement(const TokenPos &pos) { return NodeGeneric; } Node newExprStatement(Node expr, uint32_t end) {