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 */
|