Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
* vim: set ts=8 sts=2 et sw=2 tw=80:
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 <cstddef> // std::nullptr_t
14
#include <string.h>
15
16
#include "frontend/ParseNode.h"
17
#include "frontend/SharedContext.h"
18
#include "vm/JSContext.h"
19
20
namespace js {
21
22
class RegExpObject;
23
24
namespace frontend {
25
26
class TokenStreamAnyChars;
27
28
enum class SourceKind {
29
// We are parsing from a text source (Parser.h)
30
Text,
31
// We are parsing from a binary source (BinASTParser.h)
32
Binary,
33
};
34
35
// Parse handler used when generating a full parse tree for all code which the
36
// parser encounters.
37
class FullParseHandler {
38
ParseNodeAllocator allocator;
39
40
ParseNode* allocParseNode(size_t size) {
41
return static_cast<ParseNode*>(allocator.allocNode(size));
42
}
43
44
/*
45
* If this is a full parse to construct the bytecode for a function that
46
* was previously lazily parsed, we still don't want to full parse the
47
* inner functions. These members are used for this functionality:
48
*
49
* - lazyOuterFunction_ holds the lazyScript for this current parse
50
* - lazyInnerFunctionIndex is used as we skip over inner functions
51
* (see skipLazyInnerFunction),
52
*/
53
const Rooted<LazyScript*> lazyOuterFunction_;
54
size_t lazyInnerFunctionIndex;
55
56
size_t lazyClosedOverBindingIndex;
57
58
const SourceKind sourceKind_;
59
60
public:
61
/* new_ methods for creating parse nodes. These report OOM on context. */
62
JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
63
64
// FIXME: Use ListNode instead of ListNodeType as an alias (bug 1489008).
65
using Node = ParseNode*;
66
67
#define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
68
using longTypeName = typeName*;
69
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
70
#undef DECLARE_TYPE
71
72
using NullNode = std::nullptr_t;
73
74
bool isPropertyAccess(Node node) {
75
return node->isKind(ParseNodeKind::DotExpr) ||
76
node->isKind(ParseNodeKind::ElemExpr);
77
}
78
79
bool isFunctionCall(Node node) {
80
// Note: super() is a special form, *not* a function call.
81
return node->isKind(ParseNodeKind::CallExpr);
82
}
83
84
static bool isUnparenthesizedDestructuringPattern(Node node) {
85
return !node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) ||
86
node->isKind(ParseNodeKind::ArrayExpr));
87
}
88
89
static bool isParenthesizedDestructuringPattern(Node node) {
90
// Technically this isn't a destructuring pattern at all -- the grammar
91
// doesn't treat it as such. But we need to know when this happens to
92
// consider it a SyntaxError rather than an invalid-left-hand-side
93
// ReferenceError.
94
return node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) ||
95
node->isKind(ParseNodeKind::ArrayExpr));
96
}
97
98
FullParseHandler(JSContext* cx, LifoAlloc& alloc,
99
LazyScript* lazyOuterFunction,
100
SourceKind kind = SourceKind::Text)
101
: allocator(cx, alloc),
102
lazyOuterFunction_(cx, lazyOuterFunction),
103
lazyInnerFunctionIndex(0),
104
lazyClosedOverBindingIndex(0),
105
sourceKind_(kind) {}
106
107
static NullNode null() { return NullNode(); }
108
109
#define DECLARE_AS(typeName, longTypeName, asMethodName) \
110
static longTypeName asMethodName(Node node) { return &node->as<typeName>(); }
111
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
112
#undef DECLARE_AS
113
114
// The FullParseHandler may be used to create nodes for text sources
115
// (from Parser.h) or for binary sources (from BinASTParser.h). In the latter
116
// case, some common assumptions on offsets are incorrect, e.g. in `a + b`,
117
// `a`, `b` and `+` may be stored in any order. We use `sourceKind()`
118
// to determine whether we need to check these assumptions.
119
SourceKind sourceKind() const { return sourceKind_; }
120
121
NameNodeType newName(PropertyName* name, const TokenPos& pos, JSContext* cx) {
122
return new_<NameNode>(ParseNodeKind::Name, name, pos);
123
}
124
125
UnaryNodeType newComputedName(Node expr, uint32_t begin, uint32_t end) {
126
TokenPos pos(begin, end);
127
return new_<UnaryNode>(ParseNodeKind::ComputedName, pos, expr);
128
}
129
130
NameNodeType newObjectLiteralPropertyName(JSAtom* atom, const TokenPos& pos) {
131
return new_<NameNode>(ParseNodeKind::ObjectPropertyName, atom, pos);
132
}
133
134
NumericLiteralType newNumber(double value, DecimalPoint decimalPoint,
135
const TokenPos& pos) {
136
return new_<NumericLiteral>(value, decimalPoint, pos);
137
}
138
139
// The Boxer object here is any object that can allocate BigIntBoxes.
140
// Specifically, a Boxer has a .newBigIntBox(T) method that accepts a
141
// BigInt* argument and returns a BigIntBox*.
142
template <class Boxer>
143
BigIntLiteralType newBigInt(BigInt* bi, const TokenPos& pos, Boxer& boxer) {
144
BigIntBox* box = boxer.newBigIntBox(bi);
145
if (!box) {
146
return null();
147
}
148
return new_<BigIntLiteral>(box, pos);
149
}
150
151
BooleanLiteralType newBooleanLiteral(bool cond, const TokenPos& pos) {
152
return new_<BooleanLiteral>(cond, pos);
153
}
154
155
NameNodeType newStringLiteral(JSAtom* atom, const TokenPos& pos) {
156
return new_<NameNode>(ParseNodeKind::StringExpr, atom, pos);
157
}
158
159
NameNodeType newTemplateStringLiteral(JSAtom* atom, const TokenPos& pos) {
160
return new_<NameNode>(ParseNodeKind::TemplateStringExpr, atom, pos);
161
}
162
163
CallSiteNodeType newCallSiteObject(uint32_t begin) {
164
CallSiteNode* callSiteObj = new_<CallSiteNode>(begin);
165
if (!callSiteObj) {
166
return null();
167
}
168
169
ListNode* rawNodes = newArrayLiteral(callSiteObj->pn_pos.begin);
170
if (!rawNodes) {
171
return null();
172
}
173
174
addArrayElement(callSiteObj, rawNodes);
175
176
return callSiteObj;
177
}
178
179
void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode,
180
Node cookedNode) {
181
MOZ_ASSERT(callSiteObj->isKind(ParseNodeKind::CallSiteObj));
182
183
addArrayElement(callSiteObj, cookedNode);
184
addArrayElement(callSiteObj->rawNodes(), rawNode);
185
186
/*
187
* We don't know when the last noSubstTemplate will come in, and we
188
* don't want to deal with this outside this method
189
*/
190
setEndPosition(callSiteObj, callSiteObj->rawNodes());
191
}
192
193
ThisLiteralType newThisLiteral(const TokenPos& pos, Node thisName) {
194
return new_<ThisLiteral>(pos, thisName);
195
}
196
197
NullLiteralType newNullLiteral(const TokenPos& pos) {
198
return new_<NullLiteral>(pos);
199
}
200
201
RawUndefinedLiteralType newRawUndefinedLiteral(const TokenPos& pos) {
202
return new_<RawUndefinedLiteral>(pos);
203
}
204
205
// The Boxer object here is any object that can allocate ObjectBoxes.
206
// Specifically, a Boxer has a .newObjectBox(T) method that accepts a
207
// Rooted<RegExpObject*> argument and returns an ObjectBox*.
208
template <class Boxer>
209
RegExpLiteralType newRegExp(RegExpObject* reobj, const TokenPos& pos,
210
Boxer& boxer) {
211
ObjectBox* objbox = boxer.newObjectBox(reobj);
212
if (!objbox) {
213
return null();
214
}
215
return new_<RegExpLiteral>(objbox, pos);
216
}
217
218
ConditionalExpressionType newConditional(Node cond, Node thenExpr,
219
Node elseExpr) {
220
return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
221
}
222
223
UnaryNodeType newDelete(uint32_t begin, Node expr) {
224
if (expr->isKind(ParseNodeKind::Name)) {
225
return newUnary(ParseNodeKind::DeleteNameExpr, begin, expr);
226
}
227
228
if (expr->isKind(ParseNodeKind::DotExpr)) {
229
return newUnary(ParseNodeKind::DeletePropExpr, begin, expr);
230
}
231
232
if (expr->isKind(ParseNodeKind::ElemExpr)) {
233
return newUnary(ParseNodeKind::DeleteElemExpr, begin, expr);
234
}
235
236
return newUnary(ParseNodeKind::DeleteExpr, begin, expr);
237
}
238
239
UnaryNodeType newTypeof(uint32_t begin, Node kid) {
240
ParseNodeKind pnk = kid->isKind(ParseNodeKind::Name)
241
? ParseNodeKind::TypeOfNameExpr
242
: ParseNodeKind::TypeOfExpr;
243
return newUnary(pnk, begin, kid);
244
}
245
246
UnaryNodeType newUnary(ParseNodeKind kind, uint32_t begin, Node kid) {
247
TokenPos pos(begin, kid->pn_pos.end);
248
return new_<UnaryNode>(kind, pos, kid);
249
}
250
251
UnaryNodeType newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) {
252
TokenPos pos(begin, kid->pn_pos.end);
253
return new_<UnaryNode>(kind, pos, kid);
254
}
255
256
UnaryNodeType newSpread(uint32_t begin, Node kid) {
257
TokenPos pos(begin, kid->pn_pos.end);
258
return new_<UnaryNode>(ParseNodeKind::Spread, pos, kid);
259
}
260
261
private:
262
BinaryNodeType newBinary(ParseNodeKind kind, Node left, Node right) {
263
TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
264
return new_<BinaryNode>(kind, pos, left, right);
265
}
266
267
public:
268
Node appendOrCreateList(ParseNodeKind kind, Node left, Node right,
269
ParseContext* pc) {
270
return ParseNode::appendOrCreateList(kind, left, right, this, pc);
271
}
272
273
// Expressions
274
275
ListNodeType newArrayLiteral(uint32_t begin) {
276
return new_<ListNode>(ParseNodeKind::ArrayExpr, TokenPos(begin, begin + 1));
277
}
278
279
MOZ_MUST_USE bool addElision(ListNodeType literal, const TokenPos& pos) {
280
MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr));
281
282
NullaryNode* elision = new_<NullaryNode>(ParseNodeKind::Elision, pos);
283
if (!elision) {
284
return false;
285
}
286
addList(/* list = */ literal, /* kid = */ elision);
287
literal->setHasArrayHoleOrSpread();
288
literal->setHasNonConstInitializer();
289
return true;
290
}
291
292
MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin,
293
Node inner) {
294
MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr));
295
296
UnaryNodeType spread = newSpread(begin, inner);
297
if (!spread) {
298
return false;
299
}
300
addList(/* list = */ literal, /* kid = */ spread);
301
literal->setHasArrayHoleOrSpread();
302
literal->setHasNonConstInitializer();
303
return true;
304
}
305
306
void addArrayElement(ListNodeType literal, Node element) {
307
if (!element->isConstant()) {
308
literal->setHasNonConstInitializer();
309
}
310
addList(/* list = */ literal, /* kid = */ element);
311
}
312
313
CallNodeType newCall(Node callee, Node args, JSOp callOp) {
314
return new_<CallNode>(ParseNodeKind::CallExpr, callOp, callee, args);
315
}
316
317
ListNodeType newArguments(const TokenPos& pos) {
318
return new_<ListNode>(ParseNodeKind::Arguments, pos);
319
}
320
321
CallNodeType newSuperCall(Node callee, Node args, bool isSpread) {
322
return new_<CallNode>(ParseNodeKind::SuperCallExpr,
323
isSpread ? JSOP_SPREADSUPERCALL : JSOP_SUPERCALL,
324
callee, args);
325
}
326
327
CallNodeType newTaggedTemplate(Node tag, Node args, JSOp callOp) {
328
return new_<CallNode>(ParseNodeKind::TaggedTemplateExpr, callOp, tag, args);
329
}
330
331
ListNodeType newObjectLiteral(uint32_t begin) {
332
return new_<ListNode>(ParseNodeKind::ObjectExpr,
333
TokenPos(begin, begin + 1));
334
}
335
336
ClassNodeType newClass(Node name, Node heritage,
337
LexicalScopeNodeType memberBlock,
338
const TokenPos& pos) {
339
return new_<ClassNode>(name, heritage, memberBlock, pos);
340
}
341
ListNodeType newClassMemberList(uint32_t begin) {
342
return new_<ListNode>(ParseNodeKind::ClassMemberList,
343
TokenPos(begin, begin + 1));
344
}
345
ClassNamesType newClassNames(Node outer, Node inner, const TokenPos& pos) {
346
return new_<ClassNames>(outer, inner, pos);
347
}
348
BinaryNodeType newNewTarget(NullaryNodeType newHolder,
349
NullaryNodeType targetHolder) {
350
return new_<BinaryNode>(ParseNodeKind::NewTargetExpr, newHolder,
351
targetHolder);
352
}
353
NullaryNodeType newPosHolder(const TokenPos& pos) {
354
return new_<NullaryNode>(ParseNodeKind::PosHolder, pos);
355
}
356
UnaryNodeType newSuperBase(Node thisName, const TokenPos& pos) {
357
return new_<UnaryNode>(ParseNodeKind::SuperBase, pos, thisName);
358
}
359
MOZ_MUST_USE bool addPrototypeMutation(ListNodeType literal, uint32_t begin,
360
Node expr) {
361
MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
362
363
// Object literals with mutated [[Prototype]] are non-constant so that
364
// singleton objects will have Object.prototype as their [[Prototype]].
365
literal->setHasNonConstInitializer();
366
367
UnaryNode* mutation = newUnary(ParseNodeKind::MutateProto, begin, expr);
368
if (!mutation) {
369
return false;
370
}
371
addList(/* list = */ literal, /* kid = */ mutation);
372
return true;
373
}
374
375
BinaryNodeType newPropertyDefinition(Node key, Node val) {
376
MOZ_ASSERT(isUsableAsObjectPropertyName(key));
377
checkAndSetIsDirectRHSAnonFunction(val);
378
return new_<PropertyDefinition>(key, val, AccessorType::None);
379
}
380
381
void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) {
382
MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
383
MOZ_ASSERT(propdef->isKind(ParseNodeKind::PropertyDefinition));
384
385
if (!propdef->right()->isConstant()) {
386
literal->setHasNonConstInitializer();
387
}
388
389
addList(/* list = */ literal, /* kid = */ propdef);
390
}
391
392
MOZ_MUST_USE bool addPropertyDefinition(ListNodeType literal, Node key,
393
Node val) {
394
BinaryNode* propdef = newPropertyDefinition(key, val);
395
if (!propdef) {
396
return false;
397
}
398
addPropertyDefinition(literal, propdef);
399
return true;
400
}
401
402
MOZ_MUST_USE bool addShorthand(ListNodeType literal, NameNodeType name,
403
NameNodeType expr) {
404
MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
405
MOZ_ASSERT(name->isKind(ParseNodeKind::ObjectPropertyName));
406
MOZ_ASSERT(expr->isKind(ParseNodeKind::Name));
407
MOZ_ASSERT(name->atom() == expr->atom());
408
409
literal->setHasNonConstInitializer();
410
BinaryNode* propdef = newBinary(ParseNodeKind::Shorthand, name, expr);
411
if (!propdef) {
412
return false;
413
}
414
addList(/* list = */ literal, /* kid = */ propdef);
415
return true;
416
}
417
418
MOZ_MUST_USE bool addSpreadProperty(ListNodeType literal, uint32_t begin,
419
Node inner) {
420
MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
421
422
literal->setHasNonConstInitializer();
423
ParseNode* spread = newSpread(begin, inner);
424
if (!spread) {
425
return false;
426
}
427
addList(/* list = */ literal, /* kid = */ spread);
428
return true;
429
}
430
431
MOZ_MUST_USE bool addObjectMethodDefinition(ListNodeType literal, Node key,
432
FunctionNodeType funNode,
433
AccessorType atype) {
434
literal->setHasNonConstInitializer();
435
436
checkAndSetIsDirectRHSAnonFunction(funNode);
437
438
ParseNode* propdef =
439
newObjectMethodOrPropertyDefinition(key, funNode, atype);
440
if (!propdef) {
441
return false;
442
}
443
444
addList(/* list = */ literal, /* kid = */ propdef);
445
return true;
446
}
447
448
MOZ_MUST_USE ClassMethod* newClassMethodDefinition(Node key,
449
FunctionNodeType funNode,
450
AccessorType atype,
451
bool isStatic) {
452
MOZ_ASSERT(isUsableAsObjectPropertyName(key));
453
454
checkAndSetIsDirectRHSAnonFunction(funNode);
455
456
return new_<ClassMethod>(key, funNode, atype, isStatic);
457
}
458
459
MOZ_MUST_USE ClassField* newClassFieldDefinition(
460
Node name, FunctionNodeType initializer) {
461
MOZ_ASSERT(isUsableAsObjectPropertyName(name));
462
463
return new_<ClassField>(name, initializer);
464
}
465
466
MOZ_MUST_USE bool addClassMemberDefinition(ListNodeType memberList,
467
Node member) {
468
MOZ_ASSERT(memberList->isKind(ParseNodeKind::ClassMemberList));
469
// Constructors can be surrounded by LexicalScopes.
470
MOZ_ASSERT(member->isKind(ParseNodeKind::ClassMethod) ||
471
member->isKind(ParseNodeKind::ClassField) ||
472
(member->isKind(ParseNodeKind::LexicalScope) &&
473
member->as<LexicalScopeNode>().scopeBody()->isKind(
474
ParseNodeKind::ClassMethod)));
475
476
addList(/* list = */ memberList, /* kid = */ member);
477
return true;
478
}
479
480
void deleteConstructorScope(JSContext* cx, ListNodeType memberList) {
481
for (ParseNode* member : memberList->contents()) {
482
if (member->is<LexicalScopeNode>()) {
483
LexicalScopeNode* node = &member->as<LexicalScopeNode>();
484
MOZ_ASSERT(node->scopeBody()->isKind(ParseNodeKind::ClassMethod));
485
MOZ_ASSERT(node->scopeBody()->as<ClassMethod>().method().syntaxKind() ==
486
FunctionSyntaxKind::ClassConstructor ||
487
node->scopeBody()->as<ClassMethod>().method().syntaxKind() ==
488
FunctionSyntaxKind::DerivedClassConstructor);
489
// Check isEmptyScope instead of asserting, because this function must
490
// be idempotent: when parsing via asm.js, this function is called, then
491
// later, after asm.js parsing fails, this function is called again on
492
// the same scope. (See bug 1555979)
493
if (!node->isEmptyScope()) {
494
MOZ_ASSERT(node->scopeBindings()->length == 1);
495
MOZ_ASSERT(node->scopeBindings()->trailingNames[0].name() ==
496
cx->names().dotInitializers);
497
node->clearScopeBindings();
498
}
499
}
500
}
501
}
502
503
UnaryNodeType newInitialYieldExpression(uint32_t begin, Node gen) {
504
TokenPos pos(begin, begin + 1);
505
return new_<UnaryNode>(ParseNodeKind::InitialYield, pos, gen);
506
}
507
508
UnaryNodeType newYieldExpression(uint32_t begin, Node value) {
509
TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
510
return new_<UnaryNode>(ParseNodeKind::YieldExpr, pos, value);
511
}
512
513
UnaryNodeType newYieldStarExpression(uint32_t begin, Node value) {
514
TokenPos pos(begin, value->pn_pos.end);
515
return new_<UnaryNode>(ParseNodeKind::YieldStarExpr, pos, value);
516
}
517
518
UnaryNodeType newAwaitExpression(uint32_t begin, Node value) {
519
TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
520
return new_<UnaryNode>(ParseNodeKind::AwaitExpr, pos, value);
521
}
522
523
// Statements
524
525
ListNodeType newStatementList(const TokenPos& pos) {
526
return new_<ListNode>(ParseNodeKind::StatementList, pos);
527
}
528
529
MOZ_MUST_USE bool isFunctionStmt(Node stmt) {
530
while (stmt->isKind(ParseNodeKind::LabelStmt)) {
531
stmt = stmt->as<LabeledStatement>().statement();
532
}
533
return stmt->is<FunctionNode>();
534
}
535
536
void addStatementToList(ListNodeType list, Node stmt) {
537
MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList));
538
539
addList(/* list = */ list, /* kid = */ stmt);
540
541
if (isFunctionStmt(stmt)) {
542
// Notify the emitter that the block contains body-level function
543
// definitions that should be processed before the rest of nodes.
544
list->setHasTopLevelFunctionDeclarations();
545
}
546
}
547
548
void setListEndPosition(ListNodeType list, const TokenPos& pos) {
549
MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList));
550
list->pn_pos.end = pos.end;
551
}
552
553
void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) {
554
MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList));
555
556
addList(/* list = */ list, /* kid = */ caseClause);
557
558
if (caseClause->statementList()->hasTopLevelFunctionDeclarations()) {
559
list->setHasTopLevelFunctionDeclarations();
560
}
561
}
562
563
MOZ_MUST_USE bool prependInitialYield(ListNodeType stmtList, Node genName) {
564
MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList));
565
566
TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1);
567
NullaryNode* makeGen =
568
new_<NullaryNode>(ParseNodeKind::Generator, yieldPos);
569
if (!makeGen) {
570
return false;
571
}
572
573
ParseNode* genInit =
574
newAssignment(ParseNodeKind::AssignExpr, /* lhs = */ genName,
575
/* rhs = */ makeGen);
576
if (!genInit) {
577
return false;
578
}
579
580
UnaryNode* initialYield =
581
newInitialYieldExpression(yieldPos.begin, genInit);
582
if (!initialYield) {
583
return false;
584
}
585
586
stmtList->prepend(initialYield);
587
return true;
588
}
589
590
BinaryNodeType newSetThis(Node thisName, Node value) {
591
return newBinary(ParseNodeKind::SetThis, thisName, value);
592
}
593
594
NullaryNodeType newEmptyStatement(const TokenPos& pos) {
595
return new_<NullaryNode>(ParseNodeKind::EmptyStmt, pos);
596
}
597
598
BinaryNodeType newImportDeclaration(Node importSpecSet, Node moduleSpec,
599
const TokenPos& pos) {
600
return new_<BinaryNode>(ParseNodeKind::ImportDecl, pos, importSpecSet,
601
moduleSpec);
602
}
603
604
BinaryNodeType newImportSpec(Node importNameNode, Node bindingName) {
605
return newBinary(ParseNodeKind::ImportSpec, importNameNode, bindingName);
606
}
607
608
UnaryNodeType newExportDeclaration(Node kid, const TokenPos& pos) {
609
return new_<UnaryNode>(ParseNodeKind::ExportStmt, pos, kid);
610
}
611
612
BinaryNodeType newExportFromDeclaration(uint32_t begin, Node exportSpecSet,
613
Node moduleSpec) {
614
BinaryNode* decl = new_<BinaryNode>(ParseNodeKind::ExportFromStmt,
615
exportSpecSet, moduleSpec);
616
if (!decl) {
617
return nullptr;
618
}
619
decl->pn_pos.begin = begin;
620
return decl;
621
}
622
623
BinaryNodeType newExportDefaultDeclaration(Node kid, Node maybeBinding,
624
const TokenPos& pos) {
625
if (maybeBinding) {
626
MOZ_ASSERT(maybeBinding->isKind(ParseNodeKind::Name));
627
MOZ_ASSERT(!maybeBinding->isInParens());
628
629
checkAndSetIsDirectRHSAnonFunction(kid);
630
}
631
632
return new_<BinaryNode>(ParseNodeKind::ExportDefaultStmt, pos, kid,
633
maybeBinding);
634
}
635
636
BinaryNodeType newExportSpec(Node bindingName, Node exportName) {
637
return newBinary(ParseNodeKind::ExportSpec, bindingName, exportName);
638
}
639
640
NullaryNodeType newExportBatchSpec(const TokenPos& pos) {
641
return new_<NullaryNode>(ParseNodeKind::ExportBatchSpecStmt, pos);
642
}
643
644
BinaryNodeType newImportMeta(NullaryNodeType importHolder,
645
NullaryNodeType metaHolder) {
646
return new_<BinaryNode>(ParseNodeKind::ImportMetaExpr, importHolder,
647
metaHolder);
648
}
649
650
BinaryNodeType newCallImport(NullaryNodeType importHolder, Node singleArg) {
651
return new_<BinaryNode>(ParseNodeKind::CallImportExpr, importHolder,
652
singleArg);
653
}
654
655
UnaryNodeType newExprStatement(Node expr, uint32_t end) {
656
MOZ_ASSERT_IF(sourceKind() == SourceKind::Text, expr->pn_pos.end <= end);
657
return new_<UnaryNode>(ParseNodeKind::ExpressionStmt,
658
TokenPos(expr->pn_pos.begin, end), expr);
659
}
660
661
UnaryNodeType newExprStatement(Node expr) {
662
return newExprStatement(expr, expr->pn_pos.end);
663
}
664
665
TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch,
666
Node elseBranch) {
667
TernaryNode* node =
668
new_<TernaryNode>(ParseNodeKind::IfStmt, cond, thenBranch, elseBranch);
669
if (!node) {
670
return nullptr;
671
}
672
node->pn_pos.begin = begin;
673
return node;
674
}
675
676
BinaryNodeType newDoWhileStatement(Node body, Node cond,
677
const TokenPos& pos) {
678
return new_<BinaryNode>(ParseNodeKind::DoWhileStmt, pos, body, cond);
679
}
680
681
BinaryNodeType newWhileStatement(uint32_t begin, Node cond, Node body) {
682
TokenPos pos(begin, body->pn_pos.end);
683
return new_<BinaryNode>(ParseNodeKind::WhileStmt, pos, cond, body);
684
}
685
686
ForNodeType newForStatement(uint32_t begin, TernaryNodeType forHead,
687
Node body, unsigned iflags) {
688
return new_<ForNode>(TokenPos(begin, body->pn_pos.end), forHead, body,
689
iflags);
690
}
691
692
TernaryNodeType newForHead(Node init, Node test, Node update,
693
const TokenPos& pos) {
694
return new_<TernaryNode>(ParseNodeKind::ForHead, init, test, update, pos);
695
}
696
697
TernaryNodeType newForInOrOfHead(ParseNodeKind kind, Node target,
698
Node iteratedExpr, const TokenPos& pos) {
699
MOZ_ASSERT(kind == ParseNodeKind::ForIn || kind == ParseNodeKind::ForOf);
700
return new_<TernaryNode>(kind, target, nullptr, iteratedExpr, pos);
701
}
702
703
SwitchStatementType newSwitchStatement(
704
uint32_t begin, Node discriminant,
705
LexicalScopeNodeType lexicalForCaseList, bool hasDefault) {
706
return new_<SwitchStatement>(begin, discriminant, lexicalForCaseList,
707
hasDefault);
708
}
709
710
CaseClauseType newCaseOrDefault(uint32_t begin, Node expr, Node body) {
711
return new_<CaseClause>(expr, body, begin);
712
}
713
714
ContinueStatementType newContinueStatement(PropertyName* label,
715
const TokenPos& pos) {
716
return new_<ContinueStatement>(label, pos);
717
}
718
719
BreakStatementType newBreakStatement(PropertyName* label,
720
const TokenPos& pos) {
721
return new_<BreakStatement>(label, pos);
722
}
723
724
UnaryNodeType newReturnStatement(Node expr, const TokenPos& pos) {
725
MOZ_ASSERT_IF(expr && sourceKind() == SourceKind::Text,
726
pos.encloses(expr->pn_pos));
727
return new_<UnaryNode>(ParseNodeKind::ReturnStmt, pos, expr);
728
}
729
730
UnaryNodeType newExpressionBody(Node expr) {
731
return new_<UnaryNode>(ParseNodeKind::ReturnStmt, expr->pn_pos, expr);
732
}
733
734
BinaryNodeType newWithStatement(uint32_t begin, Node expr, Node body) {
735
return new_<BinaryNode>(ParseNodeKind::WithStmt,
736
TokenPos(begin, body->pn_pos.end), expr, body);
737
}
738
739
LabeledStatementType newLabeledStatement(PropertyName* label, Node stmt,
740
uint32_t begin) {
741
return new_<LabeledStatement>(label, stmt, begin);
742
}
743
744
UnaryNodeType newThrowStatement(Node expr, const TokenPos& pos) {
745
MOZ_ASSERT_IF(sourceKind() == SourceKind::Text, pos.encloses(expr->pn_pos));
746
return new_<UnaryNode>(ParseNodeKind::ThrowStmt, pos, expr);
747
}
748
749
TernaryNodeType newTryStatement(uint32_t begin, Node body,
750
LexicalScopeNodeType catchScope,
751
Node finallyBlock) {
752
return new_<TryNode>(begin, body, catchScope, finallyBlock);
753
}
754
755
DebuggerStatementType newDebuggerStatement(const TokenPos& pos) {
756
return new_<DebuggerStatement>(pos);
757
}
758
759
NameNodeType newPropertyName(PropertyName* name, const TokenPos& pos) {
760
return new_<NameNode>(ParseNodeKind::PropertyNameExpr, name, pos);
761
}
762
763
PropertyAccessType newPropertyAccess(Node expr, NameNodeType key) {
764
return new_<PropertyAccess>(expr, key, expr->pn_pos.begin, key->pn_pos.end);
765
}
766
767
PropertyByValueType newPropertyByValue(Node lhs, Node index, uint32_t end) {
768
return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
769
}
770
771
bool setupCatchScope(LexicalScopeNodeType lexicalScope, Node catchName,
772
Node catchBody) {
773
BinaryNode* catchClause;
774
if (catchName) {
775
catchClause =
776
new_<BinaryNode>(ParseNodeKind::Catch, catchName, catchBody);
777
} else {
778
catchClause = new_<BinaryNode>(ParseNodeKind::Catch, catchBody->pn_pos,
779
catchName, catchBody);
780
}
781
if (!catchClause) {
782
return false;
783
}
784
lexicalScope->setScopeBody(catchClause);
785
return true;
786
}
787
788
inline MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(
789
FunctionNodeType funNode, Node defaultValue);
790
791
void checkAndSetIsDirectRHSAnonFunction(Node pn) {
792
if (IsAnonymousFunctionDefinition(pn)) {
793
pn->setDirectRHSAnonFunction(true);
794
}
795
}
796
797
FunctionNodeType newFunction(FunctionSyntaxKind syntaxKind,
798
const TokenPos& pos) {
799
return new_<FunctionNode>(syntaxKind, pos);
800
}
801
802
BinaryNodeType newObjectMethodOrPropertyDefinition(Node key, Node value,
803
AccessorType atype) {
804
MOZ_ASSERT(isUsableAsObjectPropertyName(key));
805
806
return new_<PropertyDefinition>(key, value, atype);
807
}
808
809
BinaryNodeType newShorthandPropertyDefinition(Node key, Node value) {
810
MOZ_ASSERT(isUsableAsObjectPropertyName(key));
811
812
return newBinary(ParseNodeKind::Shorthand, key, value);
813
}
814
815
ListNodeType newParamsBody(const TokenPos& pos) {
816
return new_<ListNode>(ParseNodeKind::ParamsBody, pos);
817
}
818
819
void setFunctionFormalParametersAndBody(FunctionNodeType funNode,
820
ListNodeType paramsBody) {
821
MOZ_ASSERT_IF(paramsBody, paramsBody->isKind(ParseNodeKind::ParamsBody));
822
funNode->setBody(paramsBody);
823
}
824
void setFunctionBox(FunctionNodeType funNode, FunctionBox* funbox) {
825
funNode->setFunbox(funbox);
826
funbox->functionNode = funNode;
827
}
828
void addFunctionFormalParameter(FunctionNodeType funNode, Node argpn) {
829
addList(/* list = */ funNode->body(), /* kid = */ argpn);
830
}
831
void setFunctionBody(FunctionNodeType funNode, LexicalScopeNodeType body) {
832
MOZ_ASSERT(funNode->body()->isKind(ParseNodeKind::ParamsBody));
833
addList(/* list = */ funNode->body(), /* kid = */ body);
834
}
835
836
ModuleNodeType newModule(const TokenPos& pos) {
837
return new_<ModuleNode>(pos);
838
}
839
840
LexicalScopeNodeType newLexicalScope(LexicalScope::Data* bindings, Node body,
841
ScopeKind kind = ScopeKind::Lexical) {
842
return new_<LexicalScopeNode>(bindings, body, kind);
843
}
844
845
CallNodeType newNewExpression(uint32_t begin, Node ctor, Node args,
846
bool isSpread) {
847
return new_<CallNode>(ParseNodeKind::NewExpr,
848
isSpread ? JSOP_SPREADNEW : JSOP_NEW,
849
TokenPos(begin, args->pn_pos.end), ctor, args);
850
}
851
852
AssignmentNodeType newAssignment(ParseNodeKind kind, Node lhs, Node rhs) {
853
if ((kind == ParseNodeKind::AssignExpr ||
854
kind == ParseNodeKind::InitExpr) &&
855
lhs->isKind(ParseNodeKind::Name) && !lhs->isInParens()) {
856
checkAndSetIsDirectRHSAnonFunction(rhs);
857
}
858
859
return new_<AssignmentNode>(kind, lhs, rhs);
860
}
861
862
bool isUnparenthesizedAssignment(Node node) {
863
if ((node->isKind(ParseNodeKind::AssignExpr)) && !node->isInParens()) {
864
return true;
865
}
866
867
return false;
868
}
869
870
bool isUnparenthesizedUnaryExpression(Node node) {
871
if (!node->isInParens()) {
872
ParseNodeKind kind = node->getKind();
873
return kind == ParseNodeKind::VoidExpr ||
874
kind == ParseNodeKind::NotExpr ||
875
kind == ParseNodeKind::BitNotExpr ||
876
kind == ParseNodeKind::PosExpr || kind == ParseNodeKind::NegExpr ||
877
IsTypeofKind(kind) || IsDeleteKind(kind);
878
}
879
return false;
880
}
881
882
bool isReturnStatement(Node node) {
883
return node->isKind(ParseNodeKind::ReturnStmt);
884
}
885
886
bool isStatementPermittedAfterReturnStatement(Node node) {
887
ParseNodeKind kind = node->getKind();
888
return kind == ParseNodeKind::Function || kind == ParseNodeKind::VarStmt ||
889
kind == ParseNodeKind::BreakStmt ||
890
kind == ParseNodeKind::ThrowStmt || kind == ParseNodeKind::EmptyStmt;
891
}
892
893
bool isSuperBase(Node node) { return node->isKind(ParseNodeKind::SuperBase); }
894
895
bool isUsableAsObjectPropertyName(Node node) {
896
return node->isKind(ParseNodeKind::NumberExpr) ||
897
node->isKind(ParseNodeKind::ObjectPropertyName) ||
898
node->isKind(ParseNodeKind::StringExpr) ||
899
node->isKind(ParseNodeKind::ComputedName);
900
}
901
902
AssignmentNodeType finishInitializerAssignment(NameNodeType nameNode,
903
Node init) {
904
MOZ_ASSERT(nameNode->isKind(ParseNodeKind::Name));
905
MOZ_ASSERT(!nameNode->isInParens());
906
907
checkAndSetIsDirectRHSAnonFunction(init);
908
909
return newAssignment(ParseNodeKind::AssignExpr, nameNode, init);
910
}
911
912
void setBeginPosition(Node pn, Node oth) {
913
setBeginPosition(pn, oth->pn_pos.begin);
914
}
915
void setBeginPosition(Node pn, uint32_t begin) {
916
pn->pn_pos.begin = begin;
917
MOZ_ASSERT_IF(sourceKind() == SourceKind::Text,
918
pn->pn_pos.begin <= pn->pn_pos.end);
919
}
920
921
void setEndPosition(Node pn, Node oth) {
922
setEndPosition(pn, oth->pn_pos.end);
923
}
924
void setEndPosition(Node pn, uint32_t end) {
925
pn->pn_pos.end = end;
926
MOZ_ASSERT_IF(sourceKind() == SourceKind::Text,
927
pn->pn_pos.begin <= pn->pn_pos.end);
928
}
929
930
uint32_t getFunctionNameOffset(Node func, TokenStreamAnyChars& ts) {
931
return func->pn_pos.begin;
932
}
933
934
bool isDeclarationKind(ParseNodeKind kind) {
935
return kind == ParseNodeKind::VarStmt || kind == ParseNodeKind::LetDecl ||
936
kind == ParseNodeKind::ConstDecl;
937
}
938
939
ListNodeType newList(ParseNodeKind kind, const TokenPos& pos) {
940
MOZ_ASSERT(!isDeclarationKind(kind));
941
return new_<ListNode>(kind, pos);
942
}
943
944
public:
945
ListNodeType newList(ParseNodeKind kind, Node kid) {
946
MOZ_ASSERT(!isDeclarationKind(kind));
947
return new_<ListNode>(kind, kid);
948
}
949
950
ListNodeType newDeclarationList(ParseNodeKind kind, const TokenPos& pos) {
951
MOZ_ASSERT(isDeclarationKind(kind));
952
return new_<ListNode>(kind, pos);
953
}
954
955
bool isDeclarationList(Node node) {
956
return isDeclarationKind(node->getKind());
957
}
958
959
Node singleBindingFromDeclaration(ListNodeType decl) {
960
MOZ_ASSERT(isDeclarationList(decl));
961
MOZ_ASSERT(decl->count() == 1);
962
return decl->head();
963
}
964
965
ListNodeType newCommaExpressionList(Node kid) {
966
return new_<ListNode>(ParseNodeKind::CommaExpr, kid);
967
}
968
969
void addList(ListNodeType list, Node kid) {
970
if (sourceKind_ == SourceKind::Text) {
971
list->append(kid);
972
} else {
973
list->appendWithoutOrderAssumption(kid);
974
}
975
}
976
977
void setListHasNonConstInitializer(ListNodeType literal) {
978
literal->setHasNonConstInitializer();
979
}
980
template <typename NodeType>
981
MOZ_MUST_USE NodeType parenthesize(NodeType node) {
982
node->setInParens(true);
983
return node;
984
}
985
template <typename NodeType>
986
MOZ_MUST_USE NodeType setLikelyIIFE(NodeType node) {
987
return parenthesize(node);
988
}
989
void setInDirectivePrologue(UnaryNodeType exprStmt) {
990
exprStmt->setIsDirectivePrologueMember();
991
}
992
993
bool isName(Node node) { return node->isKind(ParseNodeKind::Name); }
994
995
bool isArgumentsName(Node node, JSContext* cx) {
996
return node->isKind(ParseNodeKind::Name) &&
997
node->as<NameNode>().atom() == cx->names().arguments;
998
}
999
1000
bool isEvalName(Node node, JSContext* cx) {
1001
return node->isKind(ParseNodeKind::Name) &&
1002
node->as<NameNode>().atom() == cx->names().eval;
1003
}
1004
1005
bool isAsyncKeyword(Node node, JSContext* cx) {
1006
return node->isKind(ParseNodeKind::Name) &&
1007
node->pn_pos.begin + strlen("async") == node->pn_pos.end &&
1008
node->as<NameNode>().atom() == cx->names().async;
1009
}
1010
1011
PropertyName* maybeDottedProperty(Node pn) {
1012
return pn->is<PropertyAccess>() ? &pn->as<PropertyAccess>().name()
1013
: nullptr;
1014
}
1015
JSAtom* isStringExprStatement(Node pn, TokenPos* pos) {
1016
if (pn->is<UnaryNode>()) {
1017
UnaryNode* unary = &pn->as<UnaryNode>();
1018
if (JSAtom* atom = unary->isStringExprStatement()) {
1019
*pos = unary->kid()->pn_pos;
1020
return atom;
1021
}
1022
}
1023
return nullptr;
1024
}
1025
1026
bool canSkipLazyInnerFunctions() { return !!lazyOuterFunction_; }
1027
bool canSkipLazyClosedOverBindings() { return !!lazyOuterFunction_; }
1028
JSFunction* nextLazyInnerFunction() {
1029
MOZ_ASSERT(lazyInnerFunctionIndex <
1030
lazyOuterFunction_->numInnerFunctions());
1031
return lazyOuterFunction_->innerFunctions()[lazyInnerFunctionIndex++];
1032
}
1033
JSAtom* nextLazyClosedOverBinding() {
1034
MOZ_ASSERT(lazyClosedOverBindingIndex <
1035
lazyOuterFunction_->numClosedOverBindings());
1036
return lazyOuterFunction_
1037
->closedOverBindings()[lazyClosedOverBindingIndex++];
1038
}
1039
};
1040
1041
inline bool FullParseHandler::setLastFunctionFormalParameterDefault(
1042
FunctionNodeType funNode, Node defaultValue) {
1043
ListNode* body = funNode->body();
1044
ParseNode* arg = body->last();
1045
ParseNode* pn = newAssignment(ParseNodeKind::AssignExpr, arg, defaultValue);
1046
if (!pn) {
1047
return false;
1048
}
1049
1050
body->replaceLast(pn);
1051
return true;
1052
}
1053
1054
} // namespace frontend
1055
} // namespace js
1056
1057
#endif /* frontend_FullParseHandler_h */