LCOV - code coverage report
Current view: top level - js/src/frontend - SyntaxParseHandler.h (source / functions) Hit Total Coverage
Test: output.info Lines: 191 253 75.5 %
Date: 2017-07-14 16:53:18 Functions: 98 133 73.7 %
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_SyntaxParseHandler_h
       8             : #define frontend_SyntaxParseHandler_h
       9             : 
      10             : #include "mozilla/Assertions.h"
      11             : #include "mozilla/Attributes.h"
      12             : 
      13             : #include <string.h>
      14             : 
      15             : #include "jscntxt.h"
      16             : 
      17             : #include "frontend/ParseNode.h"
      18             : 
      19             : namespace js {
      20             : 
      21             : namespace frontend {
      22             : 
      23             : // Parse handler used when processing the syntax in a block of code, to generate
      24             : // the minimal information which is required to detect syntax errors and allow
      25             : // bytecode to be emitted for outer functions.
      26             : //
      27             : // When parsing, we start at the top level with a full parse, and when possible
      28             : // only check the syntax for inner functions, so that they can be lazily parsed
      29             : // into bytecode when/if they first run. Checking the syntax of a function is
      30             : // several times faster than doing a full parse/emit, and lazy parsing improves
      31             : // both performance and memory usage significantly when pages contain large
      32             : // amounts of code that never executes (which happens often).
      33             : class SyntaxParseHandler
      34             : {
      35             :     // Remember the last encountered name or string literal during syntax parses.
      36             :     JSAtom* lastAtom;
      37             :     TokenPos lastStringPos;
      38             : 
      39             :   public:
      40             :     enum Node {
      41             :         NodeFailure = 0,
      42             :         NodeGeneric,
      43             :         NodeGetProp,
      44             :         NodeStringExprStatement,
      45             :         NodeReturn,
      46             :         NodeBreak,
      47             :         NodeThrow,
      48             :         NodeEmptyStatement,
      49             : 
      50             :         NodeVarDeclaration,
      51             :         NodeLexicalDeclaration,
      52             : 
      53             :         NodeFunctionDefinition,
      54             : 
      55             :         // This is needed for proper assignment-target handling.  ES6 formally
      56             :         // requires function calls *not* pass IsValidSimpleAssignmentTarget,
      57             :         // but at last check there were still sites with |f() = 5| and similar
      58             :         // in code not actually executed (or at least not executed enough to be
      59             :         // noticed).
      60             :         NodeFunctionCall,
      61             : 
      62             :         // Nodes representing *parenthesized* IsValidSimpleAssignmentTarget
      63             :         // nodes.  We can't simply treat all such parenthesized nodes
      64             :         // identically, because in assignment and increment/decrement contexts
      65             :         // ES6 says that parentheses constitute a syntax error.
      66             :         //
      67             :         //   var obj = {};
      68             :         //   var val;
      69             :         //   (val) = 3; (obj.prop) = 4;       // okay per ES5's little mind
      70             :         //   [(a)] = [3]; [(obj.prop)] = [4]; // invalid ES6 syntax
      71             :         //   // ...and so on for the other IsValidSimpleAssignmentTarget nodes
      72             :         //
      73             :         // We don't know in advance in the current parser when we're parsing
      74             :         // in a place where name parenthesization changes meaning, so we must
      75             :         // have multiple node values for these cases.
      76             :         NodeParenthesizedArgumentsName,
      77             :         NodeParenthesizedEvalName,
      78             :         NodeParenthesizedName,
      79             : 
      80             :         NodeDottedProperty,
      81             :         NodeElement,
      82             : 
      83             :         // Destructuring target patterns can't be parenthesized: |([a]) = [3];|
      84             :         // must be a syntax error.  (We can't use NodeGeneric instead of these
      85             :         // because that would trigger invalid-left-hand-side ReferenceError
      86             :         // semantics when SyntaxError semantics are desired.)
      87             :         NodeParenthesizedArray,
      88             :         NodeParenthesizedObject,
      89             : 
      90             :         // In rare cases a parenthesized |node| doesn't have the same semantics
      91             :         // as |node|.  Each such node has a special Node value, and we use a
      92             :         // different Node value to represent the parenthesized form.  See also
      93             :         // is{Unp,P}arenthesized*(Node), parenthesize(Node), and the various
      94             :         // functions that deal in NodeUnparenthesized* below.
      95             : 
      96             :         // Nodes representing unparenthesized names.
      97             :         NodeUnparenthesizedArgumentsName,
      98             :         NodeUnparenthesizedEvalName,
      99             :         NodeUnparenthesizedName,
     100             : 
     101             :         // Node representing the "async" name, which may actually be a
     102             :         // contextual keyword.
     103             :         NodePotentialAsyncKeyword,
     104             : 
     105             :         // Valuable for recognizing potential destructuring patterns.
     106             :         NodeUnparenthesizedArray,
     107             :         NodeUnparenthesizedObject,
     108             : 
     109             :         // The directive prologue at the start of a FunctionBody or ScriptBody
     110             :         // is the longest sequence (possibly empty) of string literal
     111             :         // expression statements at the start of a function.  Thus we need this
     112             :         // to treat |"use strict";| as a possible Use Strict Directive and
     113             :         // |("use strict");| as a useless statement.
     114             :         NodeUnparenthesizedString,
     115             : 
     116             :         // Legacy generator expressions of the form |(expr for (...))| and
     117             :         // array comprehensions of the form |[expr for (...)]|) don't permit
     118             :         // |expr| to be a comma expression.  Thus we need this to treat
     119             :         // |(a(), b for (x in []))| as a syntax error and
     120             :         // |((a(), b) for (x in []))| as a generator that calls |a| and then
     121             :         // yields |b| each time it's resumed.
     122             :         NodeUnparenthesizedCommaExpr,
     123             : 
     124             :         // Assignment expressions in condition contexts could be typos for
     125             :         // equality checks.  (Think |if (x = y)| versus |if (x == y)|.)  Thus
     126             :         // we need this to treat |if (x = y)| as a possible typo and
     127             :         // |if ((x = y))| as a deliberate assignment within a condition.
     128             :         //
     129             :         // (Technically this isn't needed, as these are *only* extraWarnings
     130             :         // warnings, and parsing with that option disables syntax parsing.  But
     131             :         // it seems best to be consistent, and perhaps the syntax parser will
     132             :         // eventually enforce extraWarnings and will require this then.)
     133             :         NodeUnparenthesizedAssignment,
     134             : 
     135             :         // This node is necessary to determine if the base operand in an
     136             :         // exponentiation operation is an unparenthesized unary expression.
     137             :         // We want to reject |-2 ** 3|, but still need to allow |(-2) ** 3|.
     138             :         NodeUnparenthesizedUnary,
     139             : 
     140             :         // This node is necessary to determine if the LHS of a property access is
     141             :         // super related.
     142             :         NodeSuperBase
     143             :     };
     144             : 
     145        1719 :     bool isPropertyAccess(Node node) {
     146        1719 :         return node == NodeDottedProperty || node == NodeElement;
     147             :     }
     148             : 
     149           0 :     bool isFunctionCall(Node node) {
     150             :         // Note: super() is a special form, *not* a function call.
     151           0 :         return node == NodeFunctionCall;
     152             :     }
     153             : 
     154        2575 :     static bool isUnparenthesizedDestructuringPattern(Node node) {
     155        2575 :         return node == NodeUnparenthesizedArray || node == NodeUnparenthesizedObject;
     156             :     }
     157             : 
     158         257 :     static bool isParenthesizedDestructuringPattern(Node node) {
     159             :         // Technically this isn't a destructuring target at all -- the grammar
     160             :         // doesn't treat it as such.  But we need to know when this happens to
     161             :         // consider it a SyntaxError rather than an invalid-left-hand-side
     162             :         // ReferenceError.
     163         257 :         return node == NodeParenthesizedArray || node == NodeParenthesizedObject;
     164             :     }
     165             : 
     166             :     static bool isDestructuringPatternAnyParentheses(Node node) {
     167             :         return isUnparenthesizedDestructuringPattern(node) ||
     168             :                 isParenthesizedDestructuringPattern(node);
     169             :     }
     170             : 
     171             :   public:
     172         212 :     SyntaxParseHandler(JSContext* cx, LifoAlloc& alloc, LazyScript* lazyOuterFunction)
     173         212 :       : lastAtom(nullptr)
     174         212 :     {}
     175             : 
     176        6488 :     static Node null() { return NodeFailure; }
     177             : 
     178           0 :     void prepareNodeForMutation(Node node) {}
     179           0 :     void freeTree(Node node) {}
     180             : 
     181             :     void trace(JSTracer* trc) {}
     182             : 
     183       22871 :     Node newName(PropertyName* name, const TokenPos& pos, JSContext* cx) {
     184       22871 :         lastAtom = name;
     185       22871 :         if (name == cx->names().arguments)
     186           7 :             return NodeUnparenthesizedArgumentsName;
     187       22864 :         if (pos.begin + strlen("async") == pos.end && name == cx->names().async)
     188          14 :             return NodePotentialAsyncKeyword;
     189       22850 :         if (name == cx->names().eval)
     190           0 :             return NodeUnparenthesizedEvalName;
     191       22850 :         return NodeUnparenthesizedName;
     192             :     }
     193             : 
     194           0 :     Node newComputedName(Node expr, uint32_t start, uint32_t end) {
     195           0 :         return NodeGeneric;
     196             :     }
     197             : 
     198        1166 :     Node newObjectLiteralPropertyName(JSAtom* atom, const TokenPos& pos) {
     199        1166 :         return NodeUnparenthesizedName;
     200             :     }
     201             : 
     202         625 :     Node newNumber(double value, DecimalPoint decimalPoint, const TokenPos& pos) { return NodeGeneric; }
     203         774 :     Node newBooleanLiteral(bool cond, const TokenPos& pos) { return NodeGeneric; }
     204             : 
     205        2993 :     Node newStringLiteral(JSAtom* atom, const TokenPos& pos) {
     206        2993 :         lastAtom = atom;
     207        2993 :         lastStringPos = pos;
     208        2993 :         return NodeUnparenthesizedString;
     209             :     }
     210             : 
     211         116 :     Node newTemplateStringLiteral(JSAtom* atom, const TokenPos& pos) {
     212         116 :         return NodeGeneric;
     213             :     }
     214             : 
     215           0 :     Node newCallSiteObject(uint32_t begin) {
     216           0 :         return NodeGeneric;
     217             :     }
     218             : 
     219           0 :     void addToCallSiteObject(Node callSiteObj, Node rawNode, Node cookedNode) {}
     220             : 
     221        3391 :     Node newThisLiteral(const TokenPos& pos, Node thisName) { return NodeGeneric; }
     222         593 :     Node newNullLiteral(const TokenPos& pos) { return NodeGeneric; }
     223           0 :     Node newRawUndefinedLiteral(const TokenPos& pos) { return NodeGeneric; }
     224             : 
     225             :     template <class Boxer>
     226          41 :     Node newRegExp(Node reobj, const TokenPos& pos, Boxer& boxer) { return NodeGeneric; }
     227             : 
     228          86 :     Node newConditional(Node cond, Node thenExpr, Node elseExpr) { return NodeGeneric; }
     229             : 
     230             :     Node newElision() { return NodeGeneric; }
     231             : 
     232          37 :     Node newDelete(uint32_t begin, Node expr) {
     233          37 :         return NodeUnparenthesizedUnary;
     234             :     }
     235             : 
     236         117 :     Node newTypeof(uint32_t begin, Node kid) {
     237         117 :         return NodeUnparenthesizedUnary;
     238             :     }
     239             : 
     240           0 :     Node newNullary(ParseNodeKind kind, JSOp op, const TokenPos& pos) {
     241           0 :         return NodeGeneric;
     242             :     }
     243             : 
     244         703 :     Node newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, Node kid) {
     245         703 :         return NodeUnparenthesizedUnary;
     246             :     }
     247             : 
     248          82 :     Node newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) {
     249          82 :         return NodeGeneric;
     250             :     }
     251             : 
     252          11 :     Node newSpread(uint32_t begin, Node kid) {
     253          11 :         return NodeGeneric;
     254             :     }
     255             : 
     256           0 :     Node newArrayPush(uint32_t begin, Node kid) {
     257           0 :         return NodeGeneric;
     258             :     }
     259             : 
     260          64 :     Node newBinary(ParseNodeKind kind, Node left, Node right, JSOp op = JSOP_NOP) {
     261          64 :         return NodeGeneric;
     262             :     }
     263        2616 :     Node appendOrCreateList(ParseNodeKind kind, Node left, Node right,
     264             :                             ParseContext* pc, JSOp op = JSOP_NOP) {
     265        2616 :         return NodeGeneric;
     266             :     }
     267             : 
     268             :     Node newTernary(ParseNodeKind kind, Node first, Node second, Node third, JSOp op = JSOP_NOP) {
     269             :         return NodeGeneric;
     270             :     }
     271             : 
     272             :     // Expressions
     273             : 
     274             :     Node newArrayComprehension(Node body, const TokenPos& pos) { return NodeGeneric; }
     275         208 :     Node newArrayLiteral(uint32_t begin) { return NodeUnparenthesizedArray; }
     276           2 :     MOZ_MUST_USE bool addElision(Node literal, const TokenPos& pos) { return true; }
     277           6 :     MOZ_MUST_USE bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
     278         278 :     void addArrayElement(Node literal, Node element) { }
     279             : 
     280        5555 :     Node newCall(const TokenPos& pos) { return NodeFunctionCall; }
     281           0 :     Node newTaggedTemplate(const TokenPos& pos) { return NodeGeneric; }
     282             : 
     283         635 :     Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
     284           0 :     Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
     285           0 :     Node newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; }
     286           0 :     Node newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; }
     287             : 
     288           0 :     Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; }
     289         349 :     Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
     290           4 :     Node newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; }
     291             : 
     292           0 :     MOZ_MUST_USE bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
     293         877 :     MOZ_MUST_USE bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
     294         316 :     MOZ_MUST_USE bool addShorthand(Node literal, Node name, Node expr) { return true; }
     295           0 :     MOZ_MUST_USE bool addSpreadProperty(Node literal, uint32_t begin, Node inner) { return true; }
     296          33 :     MOZ_MUST_USE bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
     297           0 :     MOZ_MUST_USE bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
     298           6 :     Node newYieldExpression(uint32_t begin, Node value) { return NodeGeneric; }
     299           0 :     Node newYieldStarExpression(uint32_t begin, Node value) { return NodeGeneric; }
     300          83 :     Node newAwaitExpression(uint32_t begin, Node value) { return NodeGeneric; }
     301             : 
     302             :     // Statements
     303             : 
     304        4504 :     Node newStatementList(const TokenPos& pos) { return NodeGeneric; }
     305       10036 :     void addStatementToList(Node list, Node stmt) {}
     306         253 :     void addCaseStatementToList(Node list, Node stmt) {}
     307          45 :     MOZ_MUST_USE bool prependInitialYield(Node stmtList, Node gen) { return true; }
     308           1 :     Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; }
     309             : 
     310           0 :     Node newExportDeclaration(Node kid, const TokenPos& pos) {
     311           0 :         return NodeGeneric;
     312             :     }
     313           0 :     Node newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) {
     314           0 :         return NodeGeneric;
     315             :     }
     316           0 :     Node newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) {
     317           0 :         return NodeGeneric;
     318             :     }
     319             : 
     320           4 :     Node newSetThis(Node thisName, Node value) { return value; }
     321             : 
     322        4230 :     Node newExprStatement(Node expr, uint32_t end) {
     323        4230 :         return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric;
     324             :     }
     325             : 
     326        1755 :     Node newIfStatement(uint32_t begin, Node cond, Node then, Node else_) { return NodeGeneric; }
     327           0 :     Node newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return NodeGeneric; }
     328          22 :     Node newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; }
     329          66 :     Node newSwitchStatement(uint32_t begin, Node discriminant, Node caseList) { return NodeGeneric; }
     330         253 :     Node newCaseOrDefault(uint32_t begin, Node expr, Node body) { return NodeGeneric; }
     331          44 :     Node newContinueStatement(PropertyName* label, const TokenPos& pos) { return NodeGeneric; }
     332         200 :     Node newBreakStatement(PropertyName* label, const TokenPos& pos) { return NodeBreak; }
     333        1544 :     Node newReturnStatement(Node expr, const TokenPos& pos) { return NodeReturn; }
     334         177 :     Node newExpressionBody(Node expr) { return NodeReturn; }
     335           0 :     Node newWithStatement(uint32_t begin, Node expr, Node body) { return NodeGeneric; }
     336             : 
     337           0 :     Node newLabeledStatement(PropertyName* label, Node stmt, uint32_t begin) {
     338           0 :         return NodeGeneric;
     339             :     }
     340             : 
     341         183 :     Node newThrowStatement(Node expr, const TokenPos& pos) { return NodeThrow; }
     342         201 :     Node newTryStatement(uint32_t begin, Node body, Node catchList, Node finallyBlock) {
     343         201 :         return NodeGeneric;
     344             :     }
     345           0 :     Node newDebuggerStatement(const TokenPos& pos) { return NodeGeneric; }
     346             : 
     347       12338 :     Node newPropertyAccess(Node pn, PropertyName* name, uint32_t end) {
     348       12338 :         lastAtom = name;
     349       12338 :         return NodeDottedProperty;
     350             :     }
     351             : 
     352         514 :     Node newPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeElement; }
     353             : 
     354         194 :     MOZ_MUST_USE bool addCatchBlock(Node catchList, Node letBlock, Node catchName,
     355         194 :                                     Node catchGuard, Node catchBody) { return true; }
     356             : 
     357          94 :     MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(Node funcpn, Node pn) { return true; }
     358             : 
     359        4360 :     void checkAndSetIsDirectRHSAnonFunction(Node pn) {}
     360             : 
     361          15 :     Node newFunctionStatement(const TokenPos& pos) { return NodeFunctionDefinition; }
     362         155 :     Node newFunctionExpression(const TokenPos& pos) { return NodeFunctionDefinition; }
     363         302 :     Node newArrowFunction(const TokenPos& pos) { return NodeFunctionDefinition; }
     364             : 
     365           0 :     bool setComprehensionLambdaBody(Node pn, Node body) { return true; }
     366        2023 :     void setFunctionFormalParametersAndBody(Node pn, Node kid) {}
     367        2023 :     void setFunctionBody(Node pn, Node kid) {}
     368         472 :     void setFunctionBox(Node pn, FunctionBox* funbox) {}
     369        2115 :     void addFunctionFormalParameter(Node pn, Node argpn) {}
     370             : 
     371         183 :     Node newForStatement(uint32_t begin, Node forHead, Node body, unsigned iflags) {
     372         183 :         return NodeGeneric;
     373             :     }
     374             : 
     375           0 :     Node newComprehensionFor(uint32_t begin, Node forHead, Node body) {
     376           0 :         return NodeGeneric;
     377             :     }
     378             : 
     379           0 :     Node newComprehensionBinding(Node kid) {
     380             :         // Careful: we're asking this well after the name was parsed, so the
     381             :         // value returned may not correspond to |kid|'s actual name.  But it
     382             :         // *will* be truthy iff |kid| was a name, so we're safe.
     383           0 :         MOZ_ASSERT(isUnparenthesizedName(kid));
     384           0 :         return NodeGeneric;
     385             :     }
     386             : 
     387          51 :     Node newForHead(Node init, Node test, Node update, const TokenPos& pos) {
     388          51 :         return NodeGeneric;
     389             :     }
     390             : 
     391         132 :     Node newForInOrOfHead(ParseNodeKind kind, Node target, Node iteratedExpr, const TokenPos& pos) {
     392         132 :         return NodeGeneric;
     393             :     }
     394             : 
     395        1802 :     MOZ_MUST_USE bool finishInitializerAssignment(Node pn, Node init) { return true; }
     396             : 
     397        5555 :     void setBeginPosition(Node pn, Node oth) {}
     398           0 :     void setBeginPosition(Node pn, uint32_t begin) {}
     399             : 
     400           0 :     void setEndPosition(Node pn, Node oth) {}
     401       11251 :     void setEndPosition(Node pn, uint32_t end) {}
     402             : 
     403           0 :     uint32_t getFunctionNameOffset(Node func, TokenStreamAnyChars& ts) {
     404             :         // XXX This offset isn't relevant to the offending function name.  But
     405             :         //     we may not *have* that function name around, because of how lazy
     406             :         //     parsing works -- the actual name could be outside
     407             :         //     |tokenStream.userbuf|'s observed region.  So the current offset
     408             :         //     is the best we can do.
     409           0 :         return ts.currentToken().pos.begin;
     410             :     }
     411             : 
     412        2612 :     Node newList(ParseNodeKind kind, const TokenPos& pos, JSOp op = JSOP_NOP) {
     413        2612 :         MOZ_ASSERT(kind != PNK_VAR);
     414        2612 :         MOZ_ASSERT(kind != PNK_LET);
     415        2612 :         MOZ_ASSERT(kind != PNK_CONST);
     416        2612 :         return NodeGeneric;
     417             :     }
     418             : 
     419             :   private:
     420         349 :     Node newList(ParseNodeKind kind, uint32_t begin, JSOp op = JSOP_NOP) {
     421         349 :         return newList(kind, TokenPos(begin, begin + 1), op);
     422             :     }
     423             : 
     424             :     template<typename T>
     425             :     Node newList(ParseNodeKind kind, const T& begin, JSOp op = JSOP_NOP) = delete;
     426             : 
     427             :   public:
     428          46 :     Node newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
     429          46 :         return newList(kind, TokenPos(), op);
     430             :     }
     431             : 
     432        2033 :     Node newDeclarationList(ParseNodeKind kind, const TokenPos& pos, JSOp op = JSOP_NOP) {
     433        2033 :         if (kind == PNK_VAR)
     434         326 :             return NodeVarDeclaration;
     435        1707 :         MOZ_ASSERT(kind == PNK_LET || kind == PNK_CONST);
     436        1707 :         return NodeLexicalDeclaration;
     437             :     }
     438             : 
     439             :     bool isDeclarationList(Node node) {
     440             :         return node == NodeVarDeclaration || node == NodeLexicalDeclaration;
     441             :     }
     442             : 
     443             :     Node singleBindingFromDeclaration(Node decl) {
     444             :         MOZ_ASSERT(isDeclarationList(decl));
     445             : 
     446             :         // This is, unfortunately, very dodgy.  Obviously NodeVarDeclaration
     447             :         // and NodeLexicalDeclaration can store no info on the arbitrary
     448             :         // number of bindings it could contain.
     449             :         //
     450             :         // But this method is called only for cloning for-in/of declarations
     451             :         // as initialization targets.  That context simplifies matters.  If the
     452             :         // binding is a single name, it'll always syntax-parse (or it would
     453             :         // already have been rejected as assigning/binding a forbidden name).
     454             :         // Otherwise the binding is a destructuring pattern.  But syntax
     455             :         // parsing would *already* have aborted when it saw a destructuring
     456             :         // pattern.  So we can just say any old thing here, because the only
     457             :         // time we'll be wrong is a case that syntax parsing has already
     458             :         // rejected.  Use NodeUnparenthesizedName so the SyntaxParseHandler
     459             :         // Parser::cloneLeftHandSide can assert it sees only this.
     460             :         return NodeUnparenthesizedName;
     461             :     }
     462             : 
     463         194 :     Node newCatchList(const TokenPos& pos) {
     464         194 :         return newList(PNK_CATCHLIST, pos, JSOP_NOP);
     465             :     }
     466             : 
     467          45 :     Node newCommaExpressionList(Node kid) {
     468          45 :         return NodeUnparenthesizedCommaExpr;
     469             :     }
     470             : 
     471       15886 :     void addList(Node list, Node kid) {
     472       15886 :         MOZ_ASSERT(list == NodeGeneric ||
     473             :                    list == NodeUnparenthesizedArray ||
     474             :                    list == NodeUnparenthesizedObject ||
     475             :                    list == NodeUnparenthesizedCommaExpr ||
     476             :                    list == NodeVarDeclaration ||
     477             :                    list == NodeLexicalDeclaration ||
     478             :                    list == NodeFunctionCall);
     479       15886 :     }
     480             : 
     481         349 :     Node newNewExpression(uint32_t begin, Node ctor) {
     482         349 :         Node newExpr = newList(PNK_NEW, begin, JSOP_NEW);
     483         349 :         if (!newExpr)
     484           0 :             return newExpr;
     485             : 
     486         349 :         addList(newExpr, ctor);
     487         349 :         return newExpr;
     488             :     }
     489             : 
     490        1688 :     Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) {
     491        1688 :         if (kind == PNK_ASSIGN)
     492        1649 :             return NodeUnparenthesizedAssignment;
     493          39 :         return newBinary(kind, lhs, rhs, op);
     494             :     }
     495             : 
     496             :     bool isUnparenthesizedCommaExpression(Node node) {
     497             :         return node == NodeUnparenthesizedCommaExpr;
     498             :     }
     499             : 
     500        2856 :     bool isUnparenthesizedAssignment(Node node) {
     501        2856 :         return node == NodeUnparenthesizedAssignment;
     502             :     }
     503             : 
     504           0 :     bool isUnparenthesizedUnaryExpression(Node node) {
     505           0 :         return node == NodeUnparenthesizedUnary;
     506             :     }
     507             : 
     508       10036 :     bool isReturnStatement(Node node) {
     509       10036 :         return node == NodeReturn;
     510             :     }
     511             : 
     512           0 :     bool isStatementPermittedAfterReturnStatement(Node pn) {
     513           0 :         return pn == NodeFunctionDefinition || pn == NodeVarDeclaration ||
     514           0 :                pn == NodeBreak ||
     515           0 :                pn == NodeThrow ||
     516           0 :                pn == NodeEmptyStatement;
     517             :     }
     518             : 
     519       54079 :     bool isSuperBase(Node pn) {
     520       54079 :         return pn == NodeSuperBase;
     521             :     }
     522             : 
     523        5555 :     void setOp(Node pn, JSOp op) {}
     524         929 :     void setListFlag(Node pn, unsigned flag) {}
     525         371 :     MOZ_MUST_USE Node parenthesize(Node node) {
     526             :         // A number of nodes have different behavior upon parenthesization, but
     527             :         // only in some circumstances.  Convert these nodes to special
     528             :         // parenthesized forms.
     529         371 :         if (node == NodeUnparenthesizedArgumentsName)
     530           0 :             return NodeParenthesizedArgumentsName;
     531         371 :         if (node == NodeUnparenthesizedEvalName)
     532           0 :             return NodeParenthesizedEvalName;
     533         371 :         if (node == NodeUnparenthesizedName || node == NodePotentialAsyncKeyword)
     534          46 :             return NodeParenthesizedName;
     535             : 
     536         325 :         if (node == NodeUnparenthesizedArray)
     537           1 :             return NodeParenthesizedArray;
     538         324 :         if (node == NodeUnparenthesizedObject)
     539           4 :             return NodeParenthesizedObject;
     540             : 
     541             :         // Other nodes need not be recognizable after parenthesization; convert
     542             :         // them to a generic node.
     543         320 :         if (node == NodeUnparenthesizedString ||
     544         276 :             node == NodeUnparenthesizedCommaExpr ||
     545         270 :             node == NodeUnparenthesizedAssignment ||
     546             :             node == NodeUnparenthesizedUnary)
     547             :         {
     548          52 :             return NodeGeneric;
     549             :         }
     550             : 
     551             :         // In all other cases, the parenthesized form of |node| is equivalent
     552             :         // to the unparenthesized form: return |node| unchanged.
     553         268 :         return node;
     554             :     }
     555           2 :     MOZ_MUST_USE Node setLikelyIIFE(Node pn) {
     556           2 :         return pn; // Remain in syntax-parse mode.
     557             :     }
     558           0 :     void setInDirectivePrologue(Node pn) {}
     559             : 
     560         851 :     bool isConstant(Node pn) { return false; }
     561             : 
     562        3327 :     bool isUnparenthesizedName(Node node) {
     563        3327 :         return node == NodeUnparenthesizedArgumentsName ||
     564        3327 :                node == NodeUnparenthesizedEvalName ||
     565        5083 :                node == NodeUnparenthesizedName ||
     566        3327 :                node == NodePotentialAsyncKeyword;
     567             :     }
     568             : 
     569        3327 :     bool isNameAnyParentheses(Node node) {
     570        3327 :         if (isUnparenthesizedName(node))
     571        1571 :             return true;
     572        1756 :         return node == NodeParenthesizedArgumentsName ||
     573        3512 :                node == NodeParenthesizedEvalName ||
     574        1756 :                node == NodeParenthesizedName;
     575             :     }
     576             : 
     577        1295 :     bool isArgumentsAnyParentheses(Node node, JSContext* cx) {
     578        1295 :         return node == NodeUnparenthesizedArgumentsName || node == NodeParenthesizedArgumentsName;
     579             :     }
     580             : 
     581        2038 :     bool isEvalAnyParentheses(Node node, JSContext* cx) {
     582        2038 :         return node == NodeUnparenthesizedEvalName || node == NodeParenthesizedEvalName;
     583             :     }
     584             : 
     585         596 :     const char* nameIsArgumentsEvalAnyParentheses(Node node, JSContext* cx) {
     586         596 :         MOZ_ASSERT(isNameAnyParentheses(node),
     587             :                    "must only call this method on known names");
     588             : 
     589         596 :         if (isEvalAnyParentheses(node, cx))
     590           0 :             return js_eval_str;
     591         596 :         if (isArgumentsAnyParentheses(node, cx))
     592           0 :             return js_arguments_str;
     593         596 :         return nullptr;
     594             :     }
     595             : 
     596         757 :     bool isAsyncKeyword(Node node, JSContext* cx) {
     597         757 :         return node == NodePotentialAsyncKeyword;
     598             :     }
     599             : 
     600        5555 :     PropertyName* maybeDottedProperty(Node node) {
     601             :         // Note: |super.apply(...)| is a special form that calls an "apply"
     602             :         // method retrieved from one value, but using a *different* value as
     603             :         // |this|.  It's not really eligible for the funapply/funcall
     604             :         // optimizations as they're currently implemented (assuming a single
     605             :         // value is used for both retrieval and |this|).
     606        5555 :         if (node != NodeDottedProperty)
     607         757 :             return nullptr;
     608        4798 :         return lastAtom->asPropertyName();
     609             :     }
     610             : 
     611        1800 :     JSAtom* isStringExprStatement(Node pn, TokenPos* pos) {
     612        1800 :         if (pn == NodeStringExprStatement) {
     613           0 :             *pos = lastStringPos;
     614           0 :             return lastAtom;
     615             :         }
     616        1800 :         return nullptr;
     617             :     }
     618             : 
     619         472 :     bool canSkipLazyInnerFunctions() {
     620         472 :         return false;
     621             :     }
     622       26944 :     bool canSkipLazyClosedOverBindings() {
     623       26944 :         return false;
     624             :     }
     625           0 :     JSAtom* nextLazyClosedOverBinding() {
     626           0 :         MOZ_CRASH("SyntaxParseHandler::canSkipLazyClosedOverBindings must return false");
     627             :     }
     628             : 
     629         487 :     void adjustGetToSet(Node node) {}
     630             : };
     631             : 
     632             : } // namespace frontend
     633             : } // namespace js
     634             : 
     635             : #endif /* frontend_SyntaxParseHandler_h */

Generated by: LCOV version 1.13