LCOV - code coverage report
Current view: top level - js/src/frontend - FullParseHandler.h (source / functions) Hit Total Coverage
Test: output.info Lines: 432 532 81.2 %
Date: 2017-07-14 16:53:18 Functions: 167 192 87.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef frontend_FullParseHandler_h
       8             : #define frontend_FullParseHandler_h
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : #include "mozilla/PodOperations.h"
      12             : 
      13             : #include <string.h>
      14             : 
      15             : #include "frontend/ParseNode.h"
      16             : #include "frontend/SharedContext.h"
      17             : 
      18             : namespace js {
      19             : namespace frontend {
      20             : 
      21             : // Parse handler used when generating a full parse tree for all code which the
      22             : // parser encounters.
      23        1691 : class FullParseHandler
      24             : {
      25             :     ParseNodeAllocator allocator;
      26             : 
      27      310719 :     ParseNode* allocParseNode(size_t size) {
      28      310719 :         MOZ_ASSERT(size == sizeof(ParseNode));
      29      310719 :         return static_cast<ParseNode*>(allocator.allocNode());
      30             :     }
      31             : 
      32             :     ParseNode* cloneNode(const ParseNode& other) {
      33             :         ParseNode* node = allocParseNode(sizeof(ParseNode));
      34             :         if (!node)
      35             :             return nullptr;
      36             :         mozilla::PodAssign(node, &other);
      37             :         return node;
      38             :     }
      39             : 
      40             :     /*
      41             :      * If this is a full parse to construct the bytecode for a function that
      42             :      * was previously lazily parsed, that lazy function and the current index
      43             :      * into its inner functions. We do not want to reparse the inner functions.
      44             :      */
      45             :     const Rooted<LazyScript*> lazyOuterFunction_;
      46             :     size_t lazyInnerFunctionIndex;
      47             :     size_t lazyClosedOverBindingIndex;
      48             : 
      49             :   public:
      50             :     /* new_ methods for creating parse nodes. These report OOM on context. */
      51      310666 :     JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
      52             : 
      53             :     typedef ParseNode* Node;
      54             : 
      55       14443 :     bool isPropertyAccess(ParseNode* node) {
      56       14443 :         return node->isKind(PNK_DOT) || node->isKind(PNK_ELEM);
      57             :     }
      58             : 
      59           0 :     bool isFunctionCall(ParseNode* node) {
      60             :         // Note: super() is a special form, *not* a function call.
      61           0 :         return node->isKind(PNK_CALL);
      62             :     }
      63             : 
      64        9189 :     static bool isUnparenthesizedDestructuringPattern(ParseNode* node) {
      65        9189 :         return !node->isInParens() && (node->isKind(PNK_OBJECT) || node->isKind(PNK_ARRAY));
      66             :     }
      67             : 
      68        2079 :     static bool isParenthesizedDestructuringPattern(ParseNode* node) {
      69             :         // Technically this isn't a destructuring pattern at all -- the grammar
      70             :         // doesn't treat it as such.  But we need to know when this happens to
      71             :         // consider it a SyntaxError rather than an invalid-left-hand-side
      72             :         // ReferenceError.
      73        2079 :         return node->isInParens() && (node->isKind(PNK_OBJECT) || node->isKind(PNK_ARRAY));
      74             :     }
      75             : 
      76             :     static bool isDestructuringPatternAnyParentheses(ParseNode* node) {
      77             :         return isUnparenthesizedDestructuringPattern(node) ||
      78             :                isParenthesizedDestructuringPattern(node);
      79             :     }
      80             : 
      81        1690 :     FullParseHandler(JSContext* cx, LifoAlloc& alloc, LazyScript* lazyOuterFunction)
      82        1690 :       : allocator(cx, alloc),
      83             :         lazyOuterFunction_(cx, lazyOuterFunction),
      84             :         lazyInnerFunctionIndex(0),
      85        1690 :         lazyClosedOverBindingIndex(0)
      86        1690 :     {}
      87             : 
      88       17952 :     static ParseNode* null() { return nullptr; }
      89             : 
      90        3645 :     ParseNode* freeTree(ParseNode* pn) { return allocator.freeTree(pn); }
      91         455 :     void prepareNodeForMutation(ParseNode* pn) { return allocator.prepareNodeForMutation(pn); }
      92             : 
      93       91188 :     ParseNode* newName(PropertyName* name, const TokenPos& pos, JSContext* cx)
      94             :     {
      95       91188 :         return new_<NameNode>(PNK_NAME, JSOP_GETNAME, name, pos);
      96             :     }
      97             : 
      98           5 :     ParseNode* newComputedName(ParseNode* expr, uint32_t begin, uint32_t end) {
      99           5 :         TokenPos pos(begin, end);
     100           5 :         return new_<UnaryNode>(PNK_COMPUTED_NAME, JSOP_NOP, pos, expr);
     101             :     }
     102             : 
     103        7851 :     ParseNode* newObjectLiteralPropertyName(JSAtom* atom, const TokenPos& pos) {
     104        7851 :         return new_<NullaryNode>(PNK_OBJECT_PROPERTY_NAME, JSOP_NOP, pos, atom);
     105             :     }
     106             : 
     107        9347 :     ParseNode* newNumber(double value, DecimalPoint decimalPoint, const TokenPos& pos) {
     108        9347 :         ParseNode* pn = new_<NullaryNode>(PNK_NUMBER, pos);
     109        9347 :         if (!pn)
     110           0 :             return nullptr;
     111        9347 :         pn->initNumber(value, decimalPoint);
     112        9347 :         return pn;
     113             :     }
     114             : 
     115        2325 :     ParseNode* newBooleanLiteral(bool cond, const TokenPos& pos) {
     116        2325 :         return new_<BooleanLiteral>(cond, pos);
     117             :     }
     118             : 
     119       17859 :     ParseNode* newStringLiteral(JSAtom* atom, const TokenPos& pos) {
     120       17859 :         return new_<NullaryNode>(PNK_STRING, JSOP_NOP, pos, atom);
     121             :     }
     122             : 
     123         863 :     ParseNode* newTemplateStringLiteral(JSAtom* atom, const TokenPos& pos) {
     124         863 :         return new_<NullaryNode>(PNK_TEMPLATE_STRING, JSOP_NOP, pos, atom);
     125             :     }
     126             : 
     127           1 :     ParseNode* newCallSiteObject(uint32_t begin) {
     128           1 :         ParseNode* callSite = new_<CallSiteNode>(begin);
     129           1 :         if (!callSite)
     130           0 :             return null();
     131             : 
     132           1 :         Node propExpr = newArrayLiteral(callSite->pn_pos.begin);
     133           1 :         if (!propExpr)
     134           0 :             return null();
     135             : 
     136           1 :         addArrayElement(callSite, propExpr);
     137             : 
     138           1 :         return callSite;
     139             :     }
     140             : 
     141           3 :     void addToCallSiteObject(ParseNode* callSiteObj, ParseNode* rawNode, ParseNode* cookedNode) {
     142           3 :         MOZ_ASSERT(callSiteObj->isKind(PNK_CALLSITEOBJ));
     143             : 
     144           3 :         addArrayElement(callSiteObj, cookedNode);
     145           3 :         addArrayElement(callSiteObj->pn_head, rawNode);
     146             : 
     147             :         /*
     148             :          * We don't know when the last noSubstTemplate will come in, and we
     149             :          * don't want to deal with this outside this method
     150             :          */
     151           3 :         setEndPosition(callSiteObj, callSiteObj->pn_head);
     152           3 :     }
     153             : 
     154        7628 :     ParseNode* newThisLiteral(const TokenPos& pos, ParseNode* thisName) {
     155        7628 :         return new_<ThisLiteral>(pos, thisName);
     156             :     }
     157             : 
     158        2043 :     ParseNode* newNullLiteral(const TokenPos& pos) {
     159        2043 :         return new_<NullLiteral>(pos);
     160             :     }
     161             : 
     162           0 :     ParseNode* newRawUndefinedLiteral(const TokenPos& pos) {
     163           0 :         return new_<RawUndefinedLiteral>(pos);
     164             :     }
     165             : 
     166             :     // The Boxer object here is any object that can allocate ObjectBoxes.
     167             :     // Specifically, a Boxer has a .newObjectBox(T) method that accepts a
     168             :     // Rooted<RegExpObject*> argument and returns an ObjectBox*.
     169             :     template <class Boxer>
     170         169 :     ParseNode* newRegExp(RegExpObject* reobj, const TokenPos& pos, Boxer& boxer) {
     171         169 :         ObjectBox* objbox = boxer.newObjectBox(reobj);
     172         169 :         if (!objbox)
     173           0 :             return null();
     174         169 :         return new_<RegExpLiteral>(objbox, pos);
     175             :     }
     176             : 
     177         652 :     ParseNode* newConditional(ParseNode* cond, ParseNode* thenExpr, ParseNode* elseExpr) {
     178         652 :         return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
     179             :     }
     180             : 
     181          80 :     ParseNode* newDelete(uint32_t begin, ParseNode* expr) {
     182          80 :         if (expr->isKind(PNK_NAME)) {
     183           0 :             expr->setOp(JSOP_DELNAME);
     184           0 :             return newUnary(PNK_DELETENAME, JSOP_NOP, begin, expr);
     185             :         }
     186             : 
     187          80 :         if (expr->isKind(PNK_DOT))
     188          51 :             return newUnary(PNK_DELETEPROP, JSOP_NOP, begin, expr);
     189             : 
     190          29 :         if (expr->isKind(PNK_ELEM))
     191          29 :             return newUnary(PNK_DELETEELEM, JSOP_NOP, begin, expr);
     192             : 
     193           0 :         return newUnary(PNK_DELETEEXPR, JSOP_NOP, begin, expr);
     194             :     }
     195             : 
     196         502 :     ParseNode* newTypeof(uint32_t begin, ParseNode* kid) {
     197         502 :         TokenPos pos(begin, kid->pn_pos.end);
     198         502 :         ParseNodeKind kind = kid->isKind(PNK_NAME) ? PNK_TYPEOFNAME : PNK_TYPEOFEXPR;
     199         502 :         return new_<UnaryNode>(kind, JSOP_NOP, pos, kid);
     200             :     }
     201             : 
     202           0 :     ParseNode* newNullary(ParseNodeKind kind, JSOp op, const TokenPos& pos) {
     203           0 :         return new_<NullaryNode>(kind, op, pos);
     204             :     }
     205             : 
     206        3405 :     ParseNode* newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, ParseNode* kid) {
     207        3405 :         TokenPos pos(begin, kid ? kid->pn_pos.end : begin + 1);
     208        3405 :         return new_<UnaryNode>(kind, op, pos, kid);
     209             :     }
     210             : 
     211         702 :     ParseNode* newUpdate(ParseNodeKind kind, uint32_t begin, ParseNode* kid) {
     212         702 :         TokenPos pos(begin, kid->pn_pos.end);
     213         702 :         return new_<UnaryNode>(kind, JSOP_NOP, pos, kid);
     214             :     }
     215             : 
     216          58 :     ParseNode* newSpread(uint32_t begin, ParseNode* kid) {
     217          58 :         TokenPos pos(begin, kid->pn_pos.end);
     218          58 :         return new_<UnaryNode>(PNK_SPREAD, JSOP_NOP, pos, kid);
     219             :     }
     220             : 
     221           0 :     ParseNode* newArrayPush(uint32_t begin, ParseNode* kid) {
     222           0 :         TokenPos pos(begin, kid->pn_pos.end);
     223           0 :         return new_<UnaryNode>(PNK_ARRAYPUSH, JSOP_ARRAYPUSH, pos, kid);
     224             :     }
     225             : 
     226       15083 :     ParseNode* newBinary(ParseNodeKind kind, ParseNode* left, ParseNode* right,
     227             :                          JSOp op = JSOP_NOP)
     228             :     {
     229       15083 :         TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
     230       15083 :         return new_<BinaryNode>(kind, op, pos, left, right);
     231             :     }
     232       13783 :     ParseNode* appendOrCreateList(ParseNodeKind kind, ParseNode* left, ParseNode* right,
     233             :                                   ParseContext* pc, JSOp op = JSOP_NOP)
     234             :     {
     235       13783 :         return ParseNode::appendOrCreateList(kind, op, left, right, this, pc);
     236             :     }
     237             : 
     238         461 :     ParseNode* newTernary(ParseNodeKind kind,
     239             :                           ParseNode* first, ParseNode* second, ParseNode* third,
     240             :                           JSOp op = JSOP_NOP)
     241             :     {
     242         461 :         return new_<TernaryNode>(kind, op, first, second, third);
     243             :     }
     244             : 
     245             :     // Expressions
     246             : 
     247             :     ParseNode* newArrayComprehension(ParseNode* body, const TokenPos& pos) {
     248             :         MOZ_ASSERT(pos.begin <= body->pn_pos.begin);
     249             :         MOZ_ASSERT(body->pn_pos.end <= pos.end);
     250             :         ParseNode* pn = new_<ListNode>(PNK_ARRAYCOMP, pos);
     251             :         if (!pn)
     252             :             return nullptr;
     253             :         pn->append(body);
     254             :         return pn;
     255             :     }
     256             : 
     257        1284 :     ParseNode* newArrayLiteral(uint32_t begin) {
     258        1284 :         ParseNode* literal = new_<ListNode>(PNK_ARRAY, TokenPos(begin, begin + 1));
     259             :         // Later in this stack: remove dependency on this opcode.
     260        1284 :         if (literal)
     261        1284 :             literal->setOp(JSOP_NEWINIT);
     262        1284 :         return literal;
     263             :     }
     264             : 
     265           5 :     MOZ_MUST_USE bool addElision(ParseNode* literal, const TokenPos& pos) {
     266           5 :         ParseNode* elision = new_<NullaryNode>(PNK_ELISION, pos);
     267           5 :         if (!elision)
     268           0 :             return false;
     269           5 :         literal->append(elision);
     270           5 :         literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST;
     271           5 :         return true;
     272             :     }
     273             : 
     274          11 :     MOZ_MUST_USE bool addSpreadElement(ParseNode* literal, uint32_t begin, ParseNode* inner) {
     275          11 :         ParseNode* spread = newSpread(begin, inner);
     276          11 :         if (!spread)
     277           0 :             return false;
     278          11 :         literal->append(spread);
     279          11 :         literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST;
     280          11 :         return true;
     281             :     }
     282             : 
     283        3051 :     void addArrayElement(ParseNode* literal, ParseNode* element) {
     284        3051 :         if (!element->isConstant())
     285         818 :             literal->pn_xflags |= PNX_NONCONST;
     286        3051 :         literal->append(element);
     287        3051 :     }
     288             : 
     289       21069 :     ParseNode* newCall(const TokenPos& pos) {
     290       21069 :         return newList(PNK_CALL, pos, JSOP_CALL);
     291             :     }
     292             : 
     293           1 :     ParseNode* newTaggedTemplate(const TokenPos& pos) {
     294           1 :         return newList(PNK_TAGGED_TEMPLATE, pos, JSOP_CALL);
     295             :     }
     296             : 
     297        2530 :     ParseNode* newObjectLiteral(uint32_t begin) {
     298        2530 :         ParseNode* literal = new_<ListNode>(PNK_OBJECT, TokenPos(begin, begin + 1));
     299             :         // Later in this stack: remove dependency on this opcode.
     300        2530 :         if (literal)
     301        2530 :             literal->setOp(JSOP_NEWINIT);
     302        2530 :         return literal;
     303             :     }
     304             : 
     305          32 :     ParseNode* newClass(ParseNode* name, ParseNode* heritage, ParseNode* methodBlock,
     306             :                         const TokenPos& pos)
     307             :     {
     308          32 :         return new_<ClassNode>(name, heritage, methodBlock, pos);
     309             :     }
     310          32 :     ParseNode* newClassMethodList(uint32_t begin) {
     311          32 :         return new_<ListNode>(PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1));
     312             :     }
     313          26 :     ParseNode* newClassNames(ParseNode* outer, ParseNode* inner, const TokenPos& pos) {
     314          26 :         return new_<ClassNames>(outer, inner, pos);
     315             :     }
     316          12 :     ParseNode* newNewTarget(ParseNode* newHolder, ParseNode* targetHolder) {
     317          12 :         return new_<BinaryNode>(PNK_NEWTARGET, JSOP_NOP, newHolder, targetHolder);
     318             :     }
     319        1007 :     ParseNode* newPosHolder(const TokenPos& pos) {
     320        1007 :         return new_<NullaryNode>(PNK_POSHOLDER, pos);
     321             :     }
     322          26 :     ParseNode* newSuperBase(ParseNode* thisName, const TokenPos& pos) {
     323          26 :         return new_<UnaryNode>(PNK_SUPERBASE, JSOP_NOP, pos, thisName);
     324             :     }
     325             : 
     326          38 :     MOZ_MUST_USE bool addPrototypeMutation(ParseNode* literal, uint32_t begin, ParseNode* expr) {
     327             :         // Object literals with mutated [[Prototype]] are non-constant so that
     328             :         // singleton objects will have Object.prototype as their [[Prototype]].
     329          38 :         setListFlag(literal, PNX_NONCONST);
     330             : 
     331          38 :         ParseNode* mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr);
     332          38 :         if (!mutation)
     333           0 :             return false;
     334          38 :         literal->append(mutation);
     335          38 :         return true;
     336             :     }
     337             : 
     338        6418 :     MOZ_MUST_USE bool addPropertyDefinition(ParseNode* literal, ParseNode* key, ParseNode* val) {
     339        6418 :         MOZ_ASSERT(literal->isKind(PNK_OBJECT));
     340        6418 :         MOZ_ASSERT(literal->isArity(PN_LIST));
     341        6418 :         MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
     342             :                    key->isKind(PNK_OBJECT_PROPERTY_NAME) ||
     343             :                    key->isKind(PNK_STRING) ||
     344             :                    key->isKind(PNK_COMPUTED_NAME));
     345             : 
     346        6418 :         ParseNode* propdef = newBinary(PNK_COLON, key, val, JSOP_INITPROP);
     347        6418 :         if (!propdef)
     348           0 :             return false;
     349        6418 :         literal->append(propdef);
     350        6418 :         return true;
     351             :     }
     352             : 
     353         611 :     MOZ_MUST_USE bool addShorthand(ParseNode* literal, ParseNode* name, ParseNode* expr) {
     354         611 :         MOZ_ASSERT(literal->isKind(PNK_OBJECT));
     355         611 :         MOZ_ASSERT(literal->isArity(PN_LIST));
     356         611 :         MOZ_ASSERT(name->isKind(PNK_OBJECT_PROPERTY_NAME));
     357         611 :         MOZ_ASSERT(expr->isKind(PNK_NAME));
     358         611 :         MOZ_ASSERT(name->pn_atom == expr->pn_atom);
     359             : 
     360         611 :         setListFlag(literal, PNX_NONCONST);
     361         611 :         ParseNode* propdef = newBinary(PNK_SHORTHAND, name, expr, JSOP_INITPROP);
     362         611 :         if (!propdef)
     363           0 :             return false;
     364         611 :         literal->append(propdef);
     365         611 :         return true;
     366             :     }
     367             : 
     368           0 :     MOZ_MUST_USE bool addSpreadProperty(ParseNode* literal, uint32_t begin, ParseNode* inner) {
     369           0 :         MOZ_ASSERT(literal->isKind(PNK_OBJECT));
     370           0 :         MOZ_ASSERT(literal->isArity(PN_LIST));
     371             : 
     372           0 :         setListFlag(literal, PNX_NONCONST);
     373           0 :         ParseNode* spread = newSpread(begin, inner);
     374           0 :         if (!spread)
     375           0 :             return false;
     376           0 :         literal->append(spread);
     377           0 :         return true;
     378             :     }
     379             : 
     380        1988 :     MOZ_MUST_USE bool addObjectMethodDefinition(ParseNode* literal, ParseNode* key, ParseNode* fn,
     381             :                                                 JSOp op)
     382             :     {
     383        1988 :         MOZ_ASSERT(literal->isArity(PN_LIST));
     384        1988 :         MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
     385             :                    key->isKind(PNK_OBJECT_PROPERTY_NAME) ||
     386             :                    key->isKind(PNK_STRING) ||
     387             :                    key->isKind(PNK_COMPUTED_NAME));
     388        1988 :         literal->pn_xflags |= PNX_NONCONST;
     389             : 
     390        1988 :         ParseNode* propdef = newBinary(PNK_COLON, key, fn, op);
     391        1988 :         if (!propdef)
     392           0 :             return false;
     393        1988 :         literal->append(propdef);
     394        1988 :         return true;
     395             :     }
     396             : 
     397         156 :     MOZ_MUST_USE bool addClassMethodDefinition(ParseNode* methodList, ParseNode* key, ParseNode* fn,
     398             :                                                JSOp op, bool isStatic)
     399             :     {
     400         156 :         MOZ_ASSERT(methodList->isKind(PNK_CLASSMETHODLIST));
     401         156 :         MOZ_ASSERT(key->isKind(PNK_NUMBER) ||
     402             :                    key->isKind(PNK_OBJECT_PROPERTY_NAME) ||
     403             :                    key->isKind(PNK_STRING) ||
     404             :                    key->isKind(PNK_COMPUTED_NAME));
     405             : 
     406         156 :         ParseNode* classMethod = new_<ClassMethod>(key, fn, op, isStatic);
     407         156 :         if (!classMethod)
     408           0 :             return false;
     409         156 :         methodList->append(classMethod);
     410         156 :         return true;
     411             :     }
     412             : 
     413         127 :     ParseNode* newInitialYieldExpression(uint32_t begin, ParseNode* gen) {
     414         127 :         TokenPos pos(begin, begin + 1);
     415         127 :         return new_<UnaryNode>(PNK_INITIALYIELD, JSOP_INITIALYIELD, pos, gen);
     416             :     }
     417             : 
     418          15 :     ParseNode* newYieldExpression(uint32_t begin, ParseNode* value) {
     419          15 :         TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
     420          15 :         return new_<UnaryNode>(PNK_YIELD, JSOP_YIELD, pos, value);
     421             :     }
     422             : 
     423           3 :     ParseNode* newYieldStarExpression(uint32_t begin, ParseNode* value) {
     424           3 :         TokenPos pos(begin, value->pn_pos.end);
     425           3 :         return new_<UnaryNode>(PNK_YIELD_STAR, JSOP_NOP, pos, value);
     426             :     }
     427             : 
     428         235 :     ParseNode* newAwaitExpression(uint32_t begin, ParseNode* value) {
     429         235 :         TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
     430         235 :         return new_<UnaryNode>(PNK_AWAIT, JSOP_AWAIT, pos, value);
     431             :     }
     432             : 
     433             :     // Statements
     434             : 
     435       12856 :     ParseNode* newStatementList(const TokenPos& pos) {
     436       12856 :         return new_<ListNode>(PNK_STATEMENTLIST, pos);
     437             :     }
     438             : 
     439       36996 :     MOZ_MUST_USE bool isFunctionStmt(ParseNode* stmt) {
     440       36996 :         while (stmt->isKind(PNK_LABEL))
     441           0 :             stmt = stmt->as<LabeledStatement>().statement();
     442       36996 :         return stmt->isKind(PNK_FUNCTION);
     443             :     }
     444             : 
     445       36996 :     void addStatementToList(ParseNode* list, ParseNode* stmt) {
     446       36996 :         MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
     447             : 
     448       36996 :         list->append(stmt);
     449             : 
     450       36996 :         if (isFunctionStmt(stmt)) {
     451             :             // PNX_FUNCDEFS notifies the emitter that the block contains
     452             :             // body-level function definitions that should be processed
     453             :             // before the rest of nodes.
     454        1816 :             list->pn_xflags |= PNX_FUNCDEFS;
     455             :         }
     456       36996 :     }
     457             : 
     458        1112 :     void addCaseStatementToList(ParseNode* list, ParseNode* casepn) {
     459        1112 :         MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST));
     460        1112 :         MOZ_ASSERT(casepn->isKind(PNK_CASE));
     461        1112 :         MOZ_ASSERT(casepn->pn_right->isKind(PNK_STATEMENTLIST));
     462             : 
     463        1112 :         list->append(casepn);
     464             : 
     465        1112 :         if (casepn->pn_right->pn_xflags & PNX_FUNCDEFS)
     466           0 :             list->pn_xflags |= PNX_FUNCDEFS;
     467        1112 :     }
     468             : 
     469         127 :     MOZ_MUST_USE bool prependInitialYield(ParseNode* stmtList, ParseNode* genName) {
     470         127 :         MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
     471             : 
     472         127 :         TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1);
     473         127 :         ParseNode* makeGen = new_<NullaryNode>(PNK_GENERATOR, yieldPos);
     474         127 :         if (!makeGen)
     475           0 :             return false;
     476             : 
     477         127 :         MOZ_ASSERT(genName->getOp() == JSOP_GETNAME);
     478         127 :         genName->setOp(JSOP_SETNAME);
     479         127 :         ParseNode* genInit = newBinary(PNK_ASSIGN, genName, makeGen);
     480         127 :         if (!genInit)
     481           0 :             return false;
     482             : 
     483         127 :         ParseNode* initialYield = newInitialYieldExpression(yieldPos.begin, genInit);
     484         127 :         if (!initialYield)
     485           0 :             return false;
     486             : 
     487         127 :         stmtList->prepend(initialYield);
     488         127 :         return true;
     489             :     }
     490             : 
     491          13 :     ParseNode* newSetThis(ParseNode* thisName, ParseNode* val) {
     492          13 :         MOZ_ASSERT(thisName->getOp() == JSOP_GETNAME);
     493          13 :         thisName->setOp(JSOP_SETNAME);
     494          13 :         return newBinary(PNK_SETTHIS, thisName, val);
     495             :     }
     496             : 
     497          11 :     ParseNode* newEmptyStatement(const TokenPos& pos) {
     498          11 :         return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode*) nullptr);
     499             :     }
     500             : 
     501           0 :     ParseNode* newImportDeclaration(ParseNode* importSpecSet,
     502             :                                     ParseNode* moduleSpec, const TokenPos& pos)
     503             :     {
     504           0 :         ParseNode* pn = new_<BinaryNode>(PNK_IMPORT, JSOP_NOP, pos,
     505           0 :                                          importSpecSet, moduleSpec);
     506           0 :         if (!pn)
     507           0 :             return null();
     508           0 :         return pn;
     509             :     }
     510             : 
     511           0 :     ParseNode* newExportDeclaration(ParseNode* kid, const TokenPos& pos) {
     512           0 :         return new_<UnaryNode>(PNK_EXPORT, JSOP_NOP, pos, kid);
     513             :     }
     514             : 
     515           0 :     ParseNode* newExportFromDeclaration(uint32_t begin, ParseNode* exportSpecSet,
     516             :                                         ParseNode* moduleSpec)
     517             :     {
     518           0 :         ParseNode* pn = new_<BinaryNode>(PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet, moduleSpec);
     519           0 :         if (!pn)
     520           0 :             return null();
     521           0 :         pn->pn_pos.begin = begin;
     522           0 :         return pn;
     523             :     }
     524             : 
     525           0 :     ParseNode* newExportDefaultDeclaration(ParseNode* kid, ParseNode* maybeBinding,
     526             :                                            const TokenPos& pos) {
     527           0 :         return new_<BinaryNode>(PNK_EXPORT_DEFAULT, JSOP_NOP, pos, kid, maybeBinding);
     528             :     }
     529             : 
     530       14230 :     ParseNode* newExprStatement(ParseNode* expr, uint32_t end) {
     531       14230 :         MOZ_ASSERT(expr->pn_pos.end <= end);
     532       14230 :         return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr);
     533             :     }
     534             : 
     535        7035 :     ParseNode* newIfStatement(uint32_t begin, ParseNode* cond, ParseNode* thenBranch,
     536             :                               ParseNode* elseBranch)
     537             :     {
     538        7035 :         ParseNode* pn = new_<TernaryNode>(PNK_IF, JSOP_NOP, cond, thenBranch, elseBranch);
     539        7035 :         if (!pn)
     540           0 :             return null();
     541        7035 :         pn->pn_pos.begin = begin;
     542        7035 :         return pn;
     543             :     }
     544             : 
     545          20 :     ParseNode* newDoWhileStatement(ParseNode* body, ParseNode* cond, const TokenPos& pos) {
     546          20 :         return new_<BinaryNode>(PNK_DOWHILE, JSOP_NOP, pos, body, cond);
     547             :     }
     548             : 
     549         182 :     ParseNode* newWhileStatement(uint32_t begin, ParseNode* cond, ParseNode* body) {
     550         182 :         TokenPos pos(begin, body->pn_pos.end);
     551         182 :         return new_<BinaryNode>(PNK_WHILE, JSOP_NOP, pos, cond, body);
     552             :     }
     553             : 
     554         808 :     ParseNode* newForStatement(uint32_t begin, ParseNode* forHead, ParseNode* body,
     555             :                                unsigned iflags)
     556             :     {
     557             :         /* A FOR node is binary, left is loop control and right is the body. */
     558         808 :         JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP;
     559        1616 :         BinaryNode* pn = new_<BinaryNode>(PNK_FOR, op, TokenPos(begin, body->pn_pos.end),
     560         808 :                                           forHead, body);
     561         808 :         if (!pn)
     562           0 :             return null();
     563         808 :         pn->pn_iflags = iflags;
     564         808 :         return pn;
     565             :     }
     566             : 
     567           0 :     ParseNode* newComprehensionFor(uint32_t begin, ParseNode* forHead, ParseNode* body) {
     568             :         // A PNK_COMPREHENSIONFOR node is binary: left is loop control, right
     569             :         // is the body.
     570           0 :         MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF));
     571           0 :         JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP;
     572           0 :         BinaryNode* pn = new_<BinaryNode>(PNK_COMPREHENSIONFOR, op,
     573           0 :                                           TokenPos(begin, body->pn_pos.end), forHead, body);
     574           0 :         if (!pn)
     575           0 :             return null();
     576           0 :         pn->pn_iflags = JSOP_ITER;
     577           0 :         return pn;
     578             :     }
     579             : 
     580           0 :     ParseNode* newComprehensionBinding(ParseNode* kid) {
     581           0 :         MOZ_ASSERT(kid->isKind(PNK_NAME));
     582           0 :         return new_<ListNode>(PNK_LET, JSOP_NOP, kid);
     583             :     }
     584             : 
     585         439 :     ParseNode* newForHead(ParseNode* init, ParseNode* test, ParseNode* update,
     586             :                           const TokenPos& pos)
     587             :     {
     588         439 :         return new_<TernaryNode>(PNK_FORHEAD, JSOP_NOP, init, test, update, pos);
     589             :     }
     590             : 
     591         369 :     ParseNode* newForInOrOfHead(ParseNodeKind kind, ParseNode* target, ParseNode* iteratedExpr,
     592             :                                 const TokenPos& pos)
     593             :     {
     594         369 :         MOZ_ASSERT(kind == PNK_FORIN || kind == PNK_FOROF);
     595         369 :         return new_<TernaryNode>(kind, JSOP_NOP, target, nullptr, iteratedExpr, pos);
     596             :     }
     597             : 
     598         209 :     ParseNode* newSwitchStatement(uint32_t begin, ParseNode* discriminant, ParseNode* caseList) {
     599         209 :         TokenPos pos(begin, caseList->pn_pos.end);
     600         209 :         return new_<BinaryNode>(PNK_SWITCH, JSOP_NOP, pos, discriminant, caseList);
     601             :     }
     602             : 
     603        1112 :     ParseNode* newCaseOrDefault(uint32_t begin, ParseNode* expr, ParseNode* body) {
     604        1112 :         return new_<CaseClause>(expr, body, begin);
     605             :     }
     606             : 
     607         121 :     ParseNode* newContinueStatement(PropertyName* label, const TokenPos& pos) {
     608         121 :         return new_<ContinueStatement>(label, pos);
     609             :     }
     610             : 
     611         476 :     ParseNode* newBreakStatement(PropertyName* label, const TokenPos& pos) {
     612         476 :         return new_<BreakStatement>(label, pos);
     613             :     }
     614             : 
     615        5768 :     ParseNode* newReturnStatement(ParseNode* expr, const TokenPos& pos) {
     616        5768 :         MOZ_ASSERT_IF(expr, pos.encloses(expr->pn_pos));
     617        5768 :         return new_<UnaryNode>(PNK_RETURN, JSOP_RETURN, pos, expr);
     618             :     }
     619             : 
     620         348 :     ParseNode* newExpressionBody(ParseNode* expr) {
     621         348 :         return new_<UnaryNode>(PNK_RETURN, JSOP_RETURN, expr->pn_pos, expr);
     622             :     }
     623             : 
     624           0 :     ParseNode* newWithStatement(uint32_t begin, ParseNode* expr, ParseNode* body) {
     625           0 :         return new_<BinaryNode>(PNK_WITH, JSOP_NOP, TokenPos(begin, body->pn_pos.end),
     626           0 :                                 expr, body);
     627             :     }
     628             : 
     629           0 :     ParseNode* newLabeledStatement(PropertyName* label, ParseNode* stmt, uint32_t begin) {
     630           0 :         return new_<LabeledStatement>(label, stmt, begin);
     631             :     }
     632             : 
     633         396 :     ParseNode* newThrowStatement(ParseNode* expr, const TokenPos& pos) {
     634         396 :         MOZ_ASSERT(pos.encloses(expr->pn_pos));
     635         396 :         return new_<UnaryNode>(PNK_THROW, JSOP_THROW, pos, expr);
     636             :     }
     637             : 
     638         483 :     ParseNode* newTryStatement(uint32_t begin, ParseNode* body, ParseNode* catchList,
     639             :                                ParseNode* finallyBlock) {
     640         483 :         TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end);
     641         483 :         return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos);
     642             :     }
     643             : 
     644           0 :     ParseNode* newDebuggerStatement(const TokenPos& pos) {
     645           0 :         return new_<DebuggerStatement>(pos);
     646             :     }
     647             : 
     648       28199 :     ParseNode* newPropertyAccess(ParseNode* pn, PropertyName* name, uint32_t end) {
     649       28199 :         return new_<PropertyAccess>(pn, name, pn->pn_pos.begin, end);
     650             :     }
     651             : 
     652        3043 :     ParseNode* newPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) {
     653        3043 :         return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
     654             :     }
     655             : 
     656             :     inline MOZ_MUST_USE bool addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope,
     657             :                                            ParseNode* catchName, ParseNode* catchGuard,
     658             :                                            ParseNode* catchBody);
     659             : 
     660             :     inline MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(ParseNode* funcpn,
     661             :                                                                    ParseNode* pn);
     662             :     inline void setLastFunctionFormalParameterDestructuring(ParseNode* funcpn, ParseNode* pn);
     663             : 
     664       22880 :     void checkAndSetIsDirectRHSAnonFunction(ParseNode* pn) {
     665       22880 :         if (IsAnonymousFunctionDefinition(pn))
     666         491 :             pn->setDirectRHSAnonFunction(true);
     667       22880 :     }
     668             : 
     669        3238 :     ParseNode* newFunctionStatement(const TokenPos& pos) {
     670        3238 :         return new_<CodeNode>(PNK_FUNCTION, JSOP_NOP, pos);
     671             :     }
     672             : 
     673        3211 :     ParseNode* newFunctionExpression(const TokenPos& pos) {
     674        3211 :         return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA, pos);
     675             :     }
     676             : 
     677         712 :     ParseNode* newArrowFunction(const TokenPos& pos) {
     678         712 :         return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA_ARROW, pos);
     679             :     }
     680             : 
     681           0 :     bool setComprehensionLambdaBody(ParseNode* pn, ParseNode* body) {
     682           0 :         MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
     683           0 :         ParseNode* paramsBody = newList(PNK_PARAMSBODY, body);
     684           0 :         if (!paramsBody)
     685           0 :             return false;
     686           0 :         setFunctionFormalParametersAndBody(pn, paramsBody);
     687           0 :         return true;
     688             :     }
     689        5350 :     void setFunctionFormalParametersAndBody(ParseNode* pn, ParseNode* kid) {
     690        5350 :         MOZ_ASSERT_IF(kid, kid->isKind(PNK_PARAMSBODY));
     691        5350 :         pn->pn_body = kid;
     692        5350 :     }
     693        7161 :     void setFunctionBox(ParseNode* pn, FunctionBox* funbox) {
     694        7161 :         MOZ_ASSERT(pn->isKind(PNK_FUNCTION));
     695        7161 :         pn->pn_funbox = funbox;
     696        7161 :         funbox->functionNode = pn;
     697        7161 :     }
     698        6301 :     void addFunctionFormalParameter(ParseNode* pn, ParseNode* argpn) {
     699        6301 :         pn->pn_body->append(argpn);
     700        6301 :     }
     701        5350 :     void setFunctionBody(ParseNode* fn, ParseNode* body) {
     702        5350 :         MOZ_ASSERT(fn->pn_body->isKind(PNK_PARAMSBODY));
     703        5350 :         fn->pn_body->append(body);
     704        5350 :     }
     705             : 
     706           0 :     ParseNode* newModule(const TokenPos& pos) {
     707           0 :         return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos);
     708             :     }
     709             : 
     710       12798 :     ParseNode* newLexicalScope(LexicalScope::Data* bindings, ParseNode* body) {
     711       12798 :         return new_<LexicalScopeNode>(bindings, body);
     712             :     }
     713             : 
     714         983 :     Node newNewExpression(uint32_t begin, ParseNode* ctor) {
     715         983 :         ParseNode* newExpr = newList(PNK_NEW, begin, JSOP_NEW);
     716         983 :         if (!newExpr)
     717           0 :             return nullptr;
     718             : 
     719         983 :         addList(newExpr, ctor);
     720         983 :         return newExpr;
     721             :     }
     722             : 
     723        5583 :     ParseNode* newAssignment(ParseNodeKind kind, ParseNode* lhs, ParseNode* rhs,
     724             :                              JSOp op)
     725             :     {
     726        5583 :         return newBinary(kind, lhs, rhs, op);
     727             :     }
     728             : 
     729             :     bool isUnparenthesizedYieldExpression(ParseNode* node) {
     730             :         return node->isKind(PNK_YIELD) && !node->isInParens();
     731             :     }
     732             : 
     733             :     bool isUnparenthesizedCommaExpression(ParseNode* node) {
     734             :         return node->isKind(PNK_COMMA) && !node->isInParens();
     735             :     }
     736             : 
     737       16382 :     bool isUnparenthesizedAssignment(Node node) {
     738       16382 :         if (node->isKind(PNK_ASSIGN) && !node->isInParens()) {
     739             :             // PNK_ASSIGN is also (mis)used for things like |var name = expr;|.
     740             :             // But this method is only called on actual expressions, so we can
     741             :             // just assert the node's op is the one used for plain assignment.
     742           3 :             MOZ_ASSERT(node->isOp(JSOP_NOP));
     743           3 :             return true;
     744             :         }
     745             : 
     746       16379 :         return false;
     747             :     }
     748             : 
     749           0 :     bool isUnparenthesizedUnaryExpression(ParseNode* node) {
     750           0 :         if (!node->isInParens()) {
     751           0 :             ParseNodeKind kind = node->getKind();
     752           0 :             return kind == PNK_VOID || kind == PNK_NOT || kind == PNK_BITNOT || kind == PNK_POS ||
     753           0 :                    kind == PNK_NEG || IsTypeofKind(kind) || IsDeleteKind(kind);
     754             :         }
     755           0 :         return false;
     756             :     }
     757             : 
     758       36995 :     bool isReturnStatement(ParseNode* node) {
     759       36995 :         return node->isKind(PNK_RETURN);
     760             :     }
     761             : 
     762           0 :     bool isStatementPermittedAfterReturnStatement(ParseNode *node) {
     763           0 :         ParseNodeKind kind = node->getKind();
     764           0 :         return kind == PNK_FUNCTION || kind == PNK_VAR || kind == PNK_BREAK || kind == PNK_THROW ||
     765           0 :                (kind == PNK_SEMI && !node->pn_kid);
     766             :     }
     767             : 
     768      196317 :     bool isSuperBase(ParseNode* node) {
     769      196317 :         return node->isKind(PNK_SUPERBASE);
     770             :     }
     771             : 
     772             :     inline MOZ_MUST_USE bool finishInitializerAssignment(ParseNode* pn, ParseNode* init);
     773             : 
     774       21070 :     void setBeginPosition(ParseNode* pn, ParseNode* oth) {
     775       21070 :         setBeginPosition(pn, oth->pn_pos.begin);
     776       21070 :     }
     777       21070 :     void setBeginPosition(ParseNode* pn, uint32_t begin) {
     778       21070 :         pn->pn_pos.begin = begin;
     779       21070 :         MOZ_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
     780       21070 :     }
     781             : 
     782           4 :     void setEndPosition(ParseNode* pn, ParseNode* oth) {
     783           4 :         setEndPosition(pn, oth->pn_pos.end);
     784           4 :     }
     785       37710 :     void setEndPosition(ParseNode* pn, uint32_t end) {
     786       37710 :         pn->pn_pos.end = end;
     787       37710 :         MOZ_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
     788       37710 :     }
     789             : 
     790           0 :     uint32_t getFunctionNameOffset(ParseNode* func, TokenStreamAnyChars& ts) {
     791           0 :         return func->pn_pos.begin;
     792             :     }
     793             : 
     794       38434 :     bool isDeclarationKind(ParseNodeKind kind) {
     795       38434 :         return kind == PNK_VAR || kind == PNK_LET || kind == PNK_CONST;
     796             :     }
     797             : 
     798       27418 :     ParseNode* newList(ParseNodeKind kind, const TokenPos& pos, JSOp op = JSOP_NOP) {
     799       27418 :         MOZ_ASSERT(!isDeclarationKind(kind));
     800       27418 :         return new_<ListNode>(kind, op, pos);
     801             :     }
     802             : 
     803             :   private:
     804         983 :     ParseNode* newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
     805         983 :         return newList(kind, TokenPos(begin, begin + 1), op);
     806             :     }
     807             : 
     808             :     template<typename T>
     809             :     ParseNode* newList(ParseNodeKind kind, const T& begin, JSOp op = JSOP_NOP) = delete;
     810             : 
     811             :   public:
     812         360 :     ParseNode* newList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
     813         360 :         MOZ_ASSERT(!isDeclarationKind(kind));
     814         360 :         return new_<ListNode>(kind, op, kid);
     815             :     }
     816             : 
     817        9834 :     ParseNode* newDeclarationList(ParseNodeKind kind, const TokenPos& pos, JSOp op) {
     818        9834 :         MOZ_ASSERT(isDeclarationKind(kind));
     819        9834 :         return new_<ListNode>(kind, op, pos);
     820             :     }
     821             : 
     822         816 :     bool isDeclarationList(ParseNode* node) {
     823         816 :         return isDeclarationKind(node->getKind());
     824             :     }
     825             : 
     826         408 :     ParseNode* singleBindingFromDeclaration(ParseNode* decl) {
     827         408 :         MOZ_ASSERT(isDeclarationList(decl));
     828         408 :         MOZ_ASSERT(decl->pn_count == 1);
     829         408 :         return decl->pn_head;
     830             :     }
     831             : 
     832         461 :     ParseNode* newCatchList(const TokenPos& pos) {
     833         461 :         return new_<ListNode>(PNK_CATCHLIST, JSOP_NOP, pos);
     834             :     }
     835             : 
     836          97 :     ParseNode* newCommaExpressionList(ParseNode* kid) {
     837          97 :         return newList(PNK_COMMA, kid, JSOP_NOP);
     838             :     }
     839             : 
     840       69963 :     void addList(ParseNode* list, ParseNode* kid) {
     841       69963 :         list->append(kid);
     842       69963 :     }
     843             : 
     844       21073 :     void setOp(ParseNode* pn, JSOp op) {
     845       21073 :         pn->setOp(op);
     846       21073 :     }
     847        3081 :     void setListFlag(ParseNode* pn, unsigned flag) {
     848        3081 :         MOZ_ASSERT(pn->isArity(PN_LIST));
     849        3081 :         pn->pn_xflags |= flag;
     850        3081 :     }
     851        1808 :     MOZ_MUST_USE ParseNode* parenthesize(ParseNode* pn) {
     852        1808 :         pn->setInParens(true);
     853        1808 :         return pn;
     854             :     }
     855          26 :     MOZ_MUST_USE ParseNode* setLikelyIIFE(ParseNode* pn) {
     856          26 :         return parenthesize(pn);
     857             :     }
     858         112 :     void setInDirectivePrologue(ParseNode* pn) {
     859         112 :         pn->pn_prologue = true;
     860         112 :     }
     861             : 
     862        6207 :     bool isConstant(ParseNode* pn) {
     863        6207 :         return pn->isConstant();
     864             :     }
     865             : 
     866             :     bool isUnparenthesizedName(ParseNode* node) {
     867             :         return node->isKind(PNK_NAME) && !node->isInParens();
     868             :     }
     869             : 
     870       17092 :     bool isNameAnyParentheses(ParseNode* node) {
     871       17092 :         return node->isKind(PNK_NAME);
     872             :     }
     873             : 
     874        7828 :     bool isArgumentsAnyParentheses(ParseNode* node, JSContext* cx) {
     875        7828 :         return node->isKind(PNK_NAME) && node->pn_atom == cx->names().arguments;
     876             :     }
     877             : 
     878       18033 :     bool isEvalAnyParentheses(ParseNode* node, JSContext* cx) {
     879       18033 :         return node->isKind(PNK_NAME) && node->pn_atom == cx->names().eval;
     880             :     }
     881             : 
     882        5025 :     const char* nameIsArgumentsEvalAnyParentheses(ParseNode* node, JSContext* cx) {
     883        5025 :         MOZ_ASSERT(isNameAnyParentheses(node),
     884             :                    "must only call this function on known names");
     885             : 
     886        5025 :         if (isEvalAnyParentheses(node, cx))
     887           0 :             return js_eval_str;
     888        5025 :         if (isArgumentsAnyParentheses(node, cx))
     889           0 :             return js_arguments_str;
     890        5025 :         return nullptr;
     891             :     }
     892             : 
     893       10231 :     bool isAsyncKeyword(ParseNode* node, JSContext* cx) {
     894       20407 :         return node->isKind(PNK_NAME) &&
     895       10309 :                node->pn_pos.begin + strlen("async") == node->pn_pos.end &&
     896       10309 :                node->pn_atom == cx->names().async;
     897             :     }
     898             : 
     899             :     bool isCall(ParseNode* pn) {
     900             :         return pn->isKind(PNK_CALL);
     901             :     }
     902       21070 :     PropertyName* maybeDottedProperty(ParseNode* pn) {
     903       21070 :         return pn->is<PropertyAccess>() ? &pn->as<PropertyAccess>().name() : nullptr;
     904             :     }
     905        5289 :     JSAtom* isStringExprStatement(ParseNode* pn, TokenPos* pos) {
     906        5289 :         if (JSAtom* atom = pn->isStringExprStatement()) {
     907         112 :             *pos = pn->pn_kid->pn_pos;
     908         112 :             return atom;
     909             :         }
     910        5177 :         return nullptr;
     911             :     }
     912             : 
     913        2515 :     void adjustGetToSet(ParseNode* node) {
     914        2515 :         node->setOp(node->isOp(JSOP_GETLOCAL) ? JSOP_SETLOCAL : JSOP_SETNAME);
     915        2515 :     }
     916             : 
     917        5739 :     bool canSkipLazyInnerFunctions() {
     918        5739 :         return !!lazyOuterFunction_;
     919             :     }
     920       96716 :     bool canSkipLazyClosedOverBindings() {
     921       96716 :         return !!lazyOuterFunction_;
     922             :     }
     923        8144 :     LazyScript* lazyOuterFunction() {
     924        8144 :         return lazyOuterFunction_;
     925             :     }
     926         260 :     JSFunction* nextLazyInnerFunction() {
     927         260 :         MOZ_ASSERT(lazyInnerFunctionIndex < lazyOuterFunction()->numInnerFunctions());
     928         260 :         return lazyOuterFunction()->innerFunctions()[lazyInnerFunctionIndex++];
     929             :     }
     930        3682 :     JSAtom* nextLazyClosedOverBinding() {
     931        3682 :         MOZ_ASSERT(lazyClosedOverBindingIndex < lazyOuterFunction()->numClosedOverBindings());
     932        3682 :         return lazyOuterFunction()->closedOverBindings()[lazyClosedOverBindingIndex++];
     933             :     }
     934             : };
     935             : 
     936             : inline bool
     937         461 : FullParseHandler::addCatchBlock(ParseNode* catchList, ParseNode* lexicalScope,
     938             :                                 ParseNode* catchName, ParseNode* catchGuard,
     939             :                                 ParseNode* catchBody)
     940             : {
     941         461 :     ParseNode* catchpn = newTernary(PNK_CATCH, catchName, catchGuard, catchBody);
     942         461 :     if (!catchpn)
     943           0 :         return false;
     944         461 :     catchList->append(lexicalScope);
     945         461 :     lexicalScope->setScopeBody(catchpn);
     946         461 :     return true;
     947             : }
     948             : 
     949             : inline bool
     950         213 : FullParseHandler::setLastFunctionFormalParameterDefault(ParseNode* funcpn,
     951             :                                                         ParseNode* defaultValue)
     952             : {
     953         213 :     ParseNode* arg = funcpn->pn_body->last();
     954         213 :     ParseNode* pn = newBinary(PNK_ASSIGN, arg, defaultValue, JSOP_NOP);
     955         213 :     if (!pn)
     956           0 :         return false;
     957             : 
     958         213 :     checkAndSetIsDirectRHSAnonFunction(defaultValue);
     959             : 
     960         213 :     funcpn->pn_body->pn_pos.end = pn->pn_pos.end;
     961         213 :     ParseNode* pnchild = funcpn->pn_body->pn_head;
     962         213 :     ParseNode* pnlast = funcpn->pn_body->last();
     963         213 :     MOZ_ASSERT(pnchild);
     964         213 :     if (pnchild == pnlast) {
     965          38 :         funcpn->pn_body->pn_head = pn;
     966             :     } else {
     967         409 :         while (pnchild->pn_next != pnlast) {
     968         117 :             MOZ_ASSERT(pnchild->pn_next);
     969         117 :             pnchild = pnchild->pn_next;
     970             :         }
     971         175 :         pnchild->pn_next = pn;
     972             :     }
     973         213 :     funcpn->pn_body->pn_tail = &pn->pn_next;
     974             : 
     975         213 :     return true;
     976             : }
     977             : 
     978             : inline bool
     979        8996 : FullParseHandler::finishInitializerAssignment(ParseNode* pn, ParseNode* init)
     980             : {
     981        8996 :     pn->pn_expr = init;
     982        8996 :     pn->setOp(JSOP_SETNAME);
     983             : 
     984             :     /* The declarator's position must include the initializer. */
     985        8996 :     pn->pn_pos.end = init->pn_pos.end;
     986        8996 :     return true;
     987             : }
     988             : 
     989             : } // namespace frontend
     990             : } // namespace js
     991             : 
     992             : #endif /* frontend_FullParseHandler_h */

Generated by: LCOV version 1.13