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
/* JS reflection package. */
8
9
#include "mozilla/DebugOnly.h"
10
#include "mozilla/Maybe.h"
11
#include "mozilla/Move.h"
12
13
#include <stdlib.h>
14
15
#include "jspubtd.h"
16
17
#include "builtin/Array.h"
18
#include "builtin/Reflect.h"
19
#include "frontend/ModuleSharedContext.h"
20
#include "frontend/ParseInfo.h"
21
#include "frontend/ParseNode.h"
22
#include "frontend/Parser.h"
23
#include "js/CharacterEncoding.h"
24
#include "js/StableStringChars.h"
25
#include "vm/BigIntType.h"
26
#include "vm/JSAtom.h"
27
#include "vm/JSObject.h"
28
#include "vm/ModuleBuilder.h" // js::ModuleBuilder
29
#include "vm/RegExpObject.h"
30
31
#include "vm/JSObject-inl.h"
32
33
using namespace js;
34
using namespace js::frontend;
35
36
using JS::AutoStableStringChars;
37
using JS::AutoValueArray;
38
using JS::CompileOptions;
39
using mozilla::DebugOnly;
40
41
enum ASTType {
42
AST_ERROR = -1,
43
#define ASTDEF(ast, str, method) ast,
44
#include "jsast.tbl"
45
#undef ASTDEF
46
AST_LIMIT
47
};
48
49
enum AssignmentOperator {
50
AOP_ERR = -1,
51
52
/* assign */
53
AOP_ASSIGN = 0,
54
/* operator-assign */
55
AOP_PLUS,
56
AOP_MINUS,
57
AOP_STAR,
58
AOP_DIV,
59
AOP_MOD,
60
AOP_POW,
61
/* shift-assign */
62
AOP_LSH,
63
AOP_RSH,
64
AOP_URSH,
65
/* binary */
66
AOP_BITOR,
67
AOP_BITXOR,
68
AOP_BITAND,
69
70
AOP_LIMIT
71
};
72
73
enum BinaryOperator {
74
BINOP_ERR = -1,
75
76
/* eq */
77
BINOP_EQ = 0,
78
BINOP_NE,
79
BINOP_STRICTEQ,
80
BINOP_STRICTNE,
81
/* rel */
82
BINOP_LT,
83
BINOP_LE,
84
BINOP_GT,
85
BINOP_GE,
86
/* shift */
87
BINOP_LSH,
88
BINOP_RSH,
89
BINOP_URSH,
90
/* arithmetic */
91
BINOP_ADD,
92
BINOP_SUB,
93
BINOP_STAR,
94
BINOP_DIV,
95
BINOP_MOD,
96
BINOP_POW,
97
/* binary */
98
BINOP_BITOR,
99
BINOP_BITXOR,
100
BINOP_BITAND,
101
/* misc */
102
BINOP_IN,
103
BINOP_INSTANCEOF,
104
BINOP_PIPELINE,
105
BINOP_COALESCE,
106
107
BINOP_LIMIT
108
};
109
110
enum UnaryOperator {
111
UNOP_ERR = -1,
112
113
UNOP_DELETE = 0,
114
UNOP_NEG,
115
UNOP_POS,
116
UNOP_NOT,
117
UNOP_BITNOT,
118
UNOP_TYPEOF,
119
UNOP_VOID,
120
UNOP_AWAIT,
121
122
UNOP_LIMIT
123
};
124
125
enum VarDeclKind {
126
VARDECL_ERR = -1,
127
VARDECL_VAR = 0,
128
VARDECL_CONST,
129
VARDECL_LET,
130
VARDECL_LIMIT
131
};
132
133
enum PropKind {
134
PROP_ERR = -1,
135
PROP_INIT = 0,
136
PROP_GETTER,
137
PROP_SETTER,
138
PROP_MUTATEPROTO,
139
PROP_LIMIT
140
};
141
142
static const char* const aopNames[] = {
143
"=", /* AOP_ASSIGN */
144
"+=", /* AOP_PLUS */
145
"-=", /* AOP_MINUS */
146
"*=", /* AOP_STAR */
147
"/=", /* AOP_DIV */
148
"%=", /* AOP_MOD */
149
"**=", /* AOP_POW */
150
"<<=", /* AOP_LSH */
151
">>=", /* AOP_RSH */
152
">>>=", /* AOP_URSH */
153
"|=", /* AOP_BITOR */
154
"^=", /* AOP_BITXOR */
155
"&=" /* AOP_BITAND */
156
};
157
158
static const char* const binopNames[] = {
159
"==", /* BINOP_EQ */
160
"!=", /* BINOP_NE */
161
"===", /* BINOP_STRICTEQ */
162
"!==", /* BINOP_STRICTNE */
163
"<", /* BINOP_LT */
164
"<=", /* BINOP_LE */
165
">", /* BINOP_GT */
166
">=", /* BINOP_GE */
167
"<<", /* BINOP_LSH */
168
">>", /* BINOP_RSH */
169
">>>", /* BINOP_URSH */
170
"+", /* BINOP_PLUS */
171
"-", /* BINOP_MINUS */
172
"*", /* BINOP_STAR */
173
"/", /* BINOP_DIV */
174
"%", /* BINOP_MOD */
175
"**", /* BINOP_POW */
176
"|", /* BINOP_BITOR */
177
"^", /* BINOP_BITXOR */
178
"&", /* BINOP_BITAND */
179
"in", /* BINOP_IN */
180
"instanceof", /* BINOP_INSTANCEOF */
181
"|>", /* BINOP_PIPELINE */
182
"??", /* BINOP_COALESCE */
183
};
184
185
static const char* const unopNames[] = {
186
"delete", /* UNOP_DELETE */
187
"-", /* UNOP_NEG */
188
"+", /* UNOP_POS */
189
"!", /* UNOP_NOT */
190
"~", /* UNOP_BITNOT */
191
"typeof", /* UNOP_TYPEOF */
192
"void", /* UNOP_VOID */
193
"await" /* UNOP_AWAIT */
194
};
195
196
static const char* const nodeTypeNames[] = {
197
#define ASTDEF(ast, str, method) str,
198
#include "jsast.tbl"
199
#undef ASTDEF
200
nullptr};
201
202
static const char* const callbackNames[] = {
203
#define ASTDEF(ast, str, method) method,
204
#include "jsast.tbl"
205
#undef ASTDEF
206
nullptr};
207
208
enum YieldKind { Delegating, NotDelegating };
209
210
typedef RootedValueVector NodeVector;
211
212
/*
213
* ParseNode is a somewhat intricate data structure, and its invariants have
214
* evolved, making it more likely that there could be a disconnect between the
215
* parser and the AST serializer. We use these macros to check invariants on a
216
* parse node and raise a dynamic error on failure.
217
*/
218
#define LOCAL_ASSERT(expr) \
219
JS_BEGIN_MACRO \
220
MOZ_ASSERT(expr); \
221
if (!(expr)) { \
222
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, \
223
JSMSG_BAD_PARSE_NODE); \
224
return false; \
225
} \
226
JS_END_MACRO
227
228
#define LOCAL_NOT_REACHED(expr) \
229
JS_BEGIN_MACRO \
230
MOZ_ASSERT(false); \
231
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, \
232
JSMSG_BAD_PARSE_NODE); \
233
return false; \
234
JS_END_MACRO
235
236
namespace {
237
238
/* Set 'result' to obj[id] if any such property exists, else defaultValue. */
239
static bool GetPropertyDefault(JSContext* cx, HandleObject obj, HandleId id,
240
HandleValue defaultValue,
241
MutableHandleValue result) {
242
bool found;
243
if (!HasProperty(cx, obj, id, &found)) {
244
return false;
245
}
246
if (!found) {
247
result.set(defaultValue);
248
return true;
249
}
250
return GetProperty(cx, obj, obj, id, result);
251
}
252
253
enum class GeneratorStyle { None, ES6 };
254
255
/*
256
* Builder class that constructs JavaScript AST node objects. See:
257
*
259
*
260
* Bug 569487: generalize builder interface
261
*/
262
class NodeBuilder {
263
typedef AutoValueArray<AST_LIMIT> CallbackArray;
264
265
JSContext* cx;
266
frontend::Parser<frontend::FullParseHandler, char16_t>* parser;
267
bool saveLoc; /* save source location information? */
268
char const* src; /* source filename or null */
269
RootedValue srcval; /* source filename JS value or null */
270
CallbackArray callbacks; /* user-specified callbacks */
271
RootedValue userv; /* user-specified builder object or null */
272
273
public:
274
NodeBuilder(JSContext* c, bool l, char const* s)
275
: cx(c),
276
parser(nullptr),
277
saveLoc(l),
278
src(s),
279
srcval(c),
280
callbacks(cx),
281
userv(c) {}
282
283
MOZ_MUST_USE bool init(HandleObject userobj = nullptr) {
284
if (src) {
285
if (!atomValue(src, &srcval)) {
286
return false;
287
}
288
} else {
289
srcval.setNull();
290
}
291
292
if (!userobj) {
293
userv.setNull();
294
for (unsigned i = 0; i < AST_LIMIT; i++) {
295
callbacks[i].setNull();
296
}
297
return true;
298
}
299
300
userv.setObject(*userobj);
301
302
RootedValue nullVal(cx, NullValue());
303
RootedValue funv(cx);
304
for (unsigned i = 0; i < AST_LIMIT; i++) {
305
const char* name = callbackNames[i];
306
RootedAtom atom(cx, Atomize(cx, name, strlen(name)));
307
if (!atom) {
308
return false;
309
}
310
RootedId id(cx, AtomToId(atom));
311
if (!GetPropertyDefault(cx, userobj, id, nullVal, &funv)) {
312
return false;
313
}
314
315
if (funv.isNullOrUndefined()) {
316
callbacks[i].setNull();
317
continue;
318
}
319
320
if (!funv.isObject() || !funv.toObject().is<JSFunction>()) {
321
ReportValueError(cx, JSMSG_NOT_FUNCTION, JSDVG_SEARCH_STACK, funv,
322
nullptr);
323
return false;
324
}
325
326
callbacks[i].set(funv);
327
}
328
329
return true;
330
}
331
332
void setParser(frontend::Parser<frontend::FullParseHandler, char16_t>* p) {
333
parser = p;
334
}
335
336
private:
337
MOZ_MUST_USE bool callbackHelper(HandleValue fun, const InvokeArgs& args,
338
size_t i, TokenPos* pos,
339
MutableHandleValue dst) {
340
// The end of the implementation of callback(). All arguments except
341
// loc have already been stored in range [0, i).
342
if (saveLoc) {
343
if (!newNodeLoc(pos, args[i])) {
344
return false;
345
}
346
}
347
348
return js::Call(cx, fun, userv, args, dst);
349
}
350
351
// Helper function for callback(). Note that all Arguments must be types
352
// that convert to HandleValue, so this isn't as template-y as it seems,
353
// just variadic.
354
template <typename... Arguments>
355
MOZ_MUST_USE bool callbackHelper(HandleValue fun, const InvokeArgs& args,
356
size_t i, HandleValue head,
357
Arguments&&... tail) {
358
// Recursive loop to store the arguments into args. This eventually
359
// bottoms out in a call to the non-template callbackHelper() above.
360
args[i].set(head);
361
return callbackHelper(fun, args, i + 1, std::forward<Arguments>(tail)...);
362
}
363
364
// Invoke a user-defined callback. The actual signature is:
365
//
366
// bool callback(HandleValue fun, HandleValue... args, TokenPos* pos,
367
// MutableHandleValue dst);
368
template <typename... Arguments>
369
MOZ_MUST_USE bool callback(HandleValue fun, Arguments&&... args) {
370
InvokeArgs iargs(cx);
371
if (!iargs.init(cx, sizeof...(args) - 2 + size_t(saveLoc))) {
372
return false;
373
}
374
375
return callbackHelper(fun, iargs, 0, std::forward<Arguments>(args)...);
376
}
377
378
// WARNING: Returning a Handle is non-standard, but it works in this case
379
// because both |v| and |UndefinedHandleValue| are definitely rooted on a
380
// previous stack frame (i.e. we're just choosing between two
381
// already-rooted values).
382
HandleValue opt(HandleValue v) {
383
MOZ_ASSERT_IF(v.isMagic(), v.whyMagic() == JS_SERIALIZE_NO_NODE);
384
return v.isMagic(JS_SERIALIZE_NO_NODE) ? JS::UndefinedHandleValue : v;
385
}
386
387
MOZ_MUST_USE bool atomValue(const char* s, MutableHandleValue dst) {
388
/*
389
* Bug 575416: instead of Atomize, lookup constant atoms in tbl file
390
*/
391
RootedAtom atom(cx, Atomize(cx, s, strlen(s)));
392
if (!atom) {
393
return false;
394
}
395
396
dst.setString(atom);
397
return true;
398
}
399
400
MOZ_MUST_USE bool newObject(MutableHandleObject dst) {
401
RootedPlainObject nobj(cx, NewBuiltinClassInstance<PlainObject>(cx));
402
if (!nobj) {
403
return false;
404
}
405
406
dst.set(nobj);
407
return true;
408
}
409
410
MOZ_MUST_USE bool newArray(NodeVector& elts, MutableHandleValue dst);
411
412
MOZ_MUST_USE bool createNode(ASTType type, TokenPos* pos,
413
MutableHandleObject dst);
414
415
MOZ_MUST_USE bool newNodeHelper(HandleObject obj, MutableHandleValue dst) {
416
// The end of the implementation of newNode().
417
MOZ_ASSERT(obj);
418
dst.setObject(*obj);
419
return true;
420
}
421
422
template <typename... Arguments>
423
MOZ_MUST_USE bool newNodeHelper(HandleObject obj, const char* name,
424
HandleValue value, Arguments&&... rest) {
425
// Recursive loop to define properties. Note that the newNodeHelper()
426
// call below passes two fewer arguments than we received, as we omit
427
// `name` and `value`. This eventually bottoms out in a call to the
428
// non-template newNodeHelper() above.
429
return defineProperty(obj, name, value) &&
430
newNodeHelper(obj, std::forward<Arguments>(rest)...);
431
}
432
433
// Create a node object with "type" and "loc" properties, as well as zero
434
// or more properties passed in as arguments. The signature is really more
435
// like:
436
//
437
// bool newNode(ASTType type, TokenPos* pos,
438
// {const char *name0, HandleValue value0,}...
439
// MutableHandleValue dst);
440
template <typename... Arguments>
441
MOZ_MUST_USE bool newNode(ASTType type, TokenPos* pos, Arguments&&... args) {
442
RootedObject node(cx);
443
return createNode(type, pos, &node) &&
444
newNodeHelper(node, std::forward<Arguments>(args)...);
445
}
446
447
MOZ_MUST_USE bool listNode(ASTType type, const char* propName,
448
NodeVector& elts, TokenPos* pos,
449
MutableHandleValue dst) {
450
RootedValue array(cx);
451
if (!newArray(elts, &array)) {
452
return false;
453
}
454
455
RootedValue cb(cx, callbacks[type]);
456
if (!cb.isNull()) {
457
return callback(cb, array, pos, dst);
458
}
459
460
return newNode(type, pos, propName, array, dst);
461
}
462
463
MOZ_MUST_USE bool defineProperty(HandleObject obj, const char* name,
464
HandleValue val) {
465
MOZ_ASSERT_IF(val.isMagic(), val.whyMagic() == JS_SERIALIZE_NO_NODE);
466
467
/*
468
* Bug 575416: instead of Atomize, lookup constant atoms in tbl file
469
*/
470
RootedAtom atom(cx, Atomize(cx, name, strlen(name)));
471
if (!atom) {
472
return false;
473
}
474
475
// Represent "no node" as null and ensure users are not exposed to magic
476
// values.
477
RootedValue optVal(cx,
478
val.isMagic(JS_SERIALIZE_NO_NODE) ? NullValue() : val);
479
return DefineDataProperty(cx, obj, atom->asPropertyName(), optVal);
480
}
481
482
MOZ_MUST_USE bool newNodeLoc(TokenPos* pos, MutableHandleValue dst);
483
484
MOZ_MUST_USE bool setNodeLoc(HandleObject node, TokenPos* pos);
485
486
public:
487
/*
488
* All of the public builder methods take as their last two
489
* arguments a nullable token position and a non-nullable, rooted
490
* outparam.
491
*
492
* Any Value arguments representing optional subnodes may be a
493
* JS_SERIALIZE_NO_NODE magic value.
494
*/
495
496
/*
497
* misc nodes
498
*/
499
500
MOZ_MUST_USE bool program(NodeVector& elts, TokenPos* pos,
501
MutableHandleValue dst);
502
503
MOZ_MUST_USE bool literal(HandleValue val, TokenPos* pos,
504
MutableHandleValue dst);
505
506
MOZ_MUST_USE bool identifier(HandleValue name, TokenPos* pos,
507
MutableHandleValue dst);
508
509
MOZ_MUST_USE bool function(ASTType type, TokenPos* pos, HandleValue id,
510
NodeVector& args, NodeVector& defaults,
511
HandleValue body, HandleValue rest,
512
GeneratorStyle generatorStyle, bool isAsync,
513
bool isExpression, MutableHandleValue dst);
514
515
MOZ_MUST_USE bool variableDeclarator(HandleValue id, HandleValue init,
516
TokenPos* pos, MutableHandleValue dst);
517
518
MOZ_MUST_USE bool switchCase(HandleValue expr, NodeVector& elts,
519
TokenPos* pos, MutableHandleValue dst);
520
521
MOZ_MUST_USE bool catchClause(HandleValue var, HandleValue body,
522
TokenPos* pos, MutableHandleValue dst);
523
524
MOZ_MUST_USE bool prototypeMutation(HandleValue val, TokenPos* pos,
525
MutableHandleValue dst);
526
MOZ_MUST_USE bool propertyInitializer(HandleValue key, HandleValue val,
527
PropKind kind, bool isShorthand,
528
bool isMethod, TokenPos* pos,
529
MutableHandleValue dst);
530
531
/*
532
* statements
533
*/
534
535
MOZ_MUST_USE bool blockStatement(NodeVector& elts, TokenPos* pos,
536
MutableHandleValue dst);
537
538
MOZ_MUST_USE bool expressionStatement(HandleValue expr, TokenPos* pos,
539
MutableHandleValue dst);
540
541
MOZ_MUST_USE bool emptyStatement(TokenPos* pos, MutableHandleValue dst);
542
543
MOZ_MUST_USE bool ifStatement(HandleValue test, HandleValue cons,
544
HandleValue alt, TokenPos* pos,
545
MutableHandleValue dst);
546
547
MOZ_MUST_USE bool breakStatement(HandleValue label, TokenPos* pos,
548
MutableHandleValue dst);
549
550
MOZ_MUST_USE bool continueStatement(HandleValue label, TokenPos* pos,
551
MutableHandleValue dst);
552
553
MOZ_MUST_USE bool labeledStatement(HandleValue label, HandleValue stmt,
554
TokenPos* pos, MutableHandleValue dst);
555
556
MOZ_MUST_USE bool throwStatement(HandleValue arg, TokenPos* pos,
557
MutableHandleValue dst);
558
559
MOZ_MUST_USE bool returnStatement(HandleValue arg, TokenPos* pos,
560
MutableHandleValue dst);
561
562
MOZ_MUST_USE bool forStatement(HandleValue init, HandleValue test,
563
HandleValue update, HandleValue stmt,
564
TokenPos* pos, MutableHandleValue dst);
565
566
MOZ_MUST_USE bool forInStatement(HandleValue var, HandleValue expr,
567
HandleValue stmt, TokenPos* pos,
568
MutableHandleValue dst);
569
570
MOZ_MUST_USE bool forOfStatement(HandleValue var, HandleValue expr,
571
HandleValue stmt, TokenPos* pos,
572
MutableHandleValue dst);
573
574
MOZ_MUST_USE bool withStatement(HandleValue expr, HandleValue stmt,
575
TokenPos* pos, MutableHandleValue dst);
576
577
MOZ_MUST_USE bool whileStatement(HandleValue test, HandleValue stmt,
578
TokenPos* pos, MutableHandleValue dst);
579
580
MOZ_MUST_USE bool doWhileStatement(HandleValue stmt, HandleValue test,
581
TokenPos* pos, MutableHandleValue dst);
582
583
MOZ_MUST_USE bool switchStatement(HandleValue disc, NodeVector& elts,
584
bool lexical, TokenPos* pos,
585
MutableHandleValue dst);
586
587
MOZ_MUST_USE bool tryStatement(HandleValue body, HandleValue handler,
588
HandleValue finally, TokenPos* pos,
589
MutableHandleValue dst);
590
591
MOZ_MUST_USE bool debuggerStatement(TokenPos* pos, MutableHandleValue dst);
592
593
MOZ_MUST_USE bool importDeclaration(NodeVector& elts, HandleValue moduleSpec,
594
TokenPos* pos, MutableHandleValue dst);
595
596
MOZ_MUST_USE bool importSpecifier(HandleValue importName,
597
HandleValue bindingName, TokenPos* pos,
598
MutableHandleValue dst);
599
600
MOZ_MUST_USE bool exportDeclaration(HandleValue decl, NodeVector& elts,
601
HandleValue moduleSpec,
602
HandleValue isDefault, TokenPos* pos,
603
MutableHandleValue dst);
604
605
MOZ_MUST_USE bool exportSpecifier(HandleValue bindingName,
606
HandleValue exportName, TokenPos* pos,
607
MutableHandleValue dst);
608
609
MOZ_MUST_USE bool exportBatchSpecifier(TokenPos* pos, MutableHandleValue dst);
610
611
MOZ_MUST_USE bool classDefinition(bool expr, HandleValue name,
612
HandleValue heritage, HandleValue block,
613
TokenPos* pos, MutableHandleValue dst);
614
MOZ_MUST_USE bool classMembers(NodeVector& members, MutableHandleValue dst);
615
MOZ_MUST_USE bool classMethod(HandleValue name, HandleValue body,
616
PropKind kind, bool isStatic, TokenPos* pos,
617
MutableHandleValue dst);
618
MOZ_MUST_USE bool classField(HandleValue name, HandleValue initializer,
619
TokenPos* pos, MutableHandleValue dst);
620
621
/*
622
* expressions
623
*/
624
625
MOZ_MUST_USE bool binaryExpression(BinaryOperator op, HandleValue left,
626
HandleValue right, TokenPos* pos,
627
MutableHandleValue dst);
628
629
MOZ_MUST_USE bool unaryExpression(UnaryOperator op, HandleValue expr,
630
TokenPos* pos, MutableHandleValue dst);
631
632
MOZ_MUST_USE bool assignmentExpression(AssignmentOperator op, HandleValue lhs,
633
HandleValue rhs, TokenPos* pos,
634
MutableHandleValue dst);
635
636
MOZ_MUST_USE bool updateExpression(HandleValue expr, bool incr, bool prefix,
637
TokenPos* pos, MutableHandleValue dst);
638
639
MOZ_MUST_USE bool logicalExpression(ParseNodeKind pnk, HandleValue left,
640
HandleValue right, TokenPos* pos,
641
MutableHandleValue dst);
642
643
MOZ_MUST_USE bool conditionalExpression(HandleValue test, HandleValue cons,
644
HandleValue alt, TokenPos* pos,
645
MutableHandleValue dst);
646
647
MOZ_MUST_USE bool sequenceExpression(NodeVector& elts, TokenPos* pos,
648
MutableHandleValue dst);
649
650
MOZ_MUST_USE bool newExpression(HandleValue callee, NodeVector& args,
651
TokenPos* pos, MutableHandleValue dst);
652
653
MOZ_MUST_USE bool callExpression(HandleValue callee, NodeVector& args,
654
TokenPos* pos, MutableHandleValue dst);
655
656
MOZ_MUST_USE bool memberExpression(bool computed, HandleValue expr,
657
HandleValue member, TokenPos* pos,
658
MutableHandleValue dst);
659
660
MOZ_MUST_USE bool arrayExpression(NodeVector& elts, TokenPos* pos,
661
MutableHandleValue dst);
662
663
MOZ_MUST_USE bool templateLiteral(NodeVector& elts, TokenPos* pos,
664
MutableHandleValue dst);
665
666
MOZ_MUST_USE bool taggedTemplate(HandleValue callee, NodeVector& args,
667
TokenPos* pos, MutableHandleValue dst);
668
669
MOZ_MUST_USE bool callSiteObj(NodeVector& raw, NodeVector& cooked,
670
TokenPos* pos, MutableHandleValue dst);
671
672
MOZ_MUST_USE bool spreadExpression(HandleValue expr, TokenPos* pos,
673
MutableHandleValue dst);
674
675
MOZ_MUST_USE bool computedName(HandleValue name, TokenPos* pos,
676
MutableHandleValue dst);
677
678
MOZ_MUST_USE bool objectExpression(NodeVector& elts, TokenPos* pos,
679
MutableHandleValue dst);
680
681
MOZ_MUST_USE bool thisExpression(TokenPos* pos, MutableHandleValue dst);
682
683
MOZ_MUST_USE bool yieldExpression(HandleValue arg, YieldKind kind,
684
TokenPos* pos, MutableHandleValue dst);
685
686
MOZ_MUST_USE bool metaProperty(HandleValue meta, HandleValue property,
687
TokenPos* pos, MutableHandleValue dst);
688
689
MOZ_MUST_USE bool callImportExpression(HandleValue ident, HandleValue arg,
690
TokenPos* pos, MutableHandleValue dst);
691
692
MOZ_MUST_USE bool super(TokenPos* pos, MutableHandleValue dst);
693
694
/*
695
* declarations
696
*/
697
698
MOZ_MUST_USE bool variableDeclaration(NodeVector& elts, VarDeclKind kind,
699
TokenPos* pos, MutableHandleValue dst);
700
701
/*
702
* patterns
703
*/
704
705
MOZ_MUST_USE bool arrayPattern(NodeVector& elts, TokenPos* pos,
706
MutableHandleValue dst);
707
708
MOZ_MUST_USE bool objectPattern(NodeVector& elts, TokenPos* pos,
709
MutableHandleValue dst);
710
711
MOZ_MUST_USE bool propertyPattern(HandleValue key, HandleValue patt,
712
bool isShorthand, TokenPos* pos,
713
MutableHandleValue dst);
714
};
715
716
} /* anonymous namespace */
717
718
bool NodeBuilder::createNode(ASTType type, TokenPos* pos,
719
MutableHandleObject dst) {
720
MOZ_ASSERT(type > AST_ERROR && type < AST_LIMIT);
721
722
RootedValue tv(cx);
723
RootedPlainObject node(cx, NewBuiltinClassInstance<PlainObject>(cx));
724
if (!node || !setNodeLoc(node, pos) || !atomValue(nodeTypeNames[type], &tv) ||
725
!defineProperty(node, "type", tv)) {
726
return false;
727
}
728
729
dst.set(node);
730
return true;
731
}
732
733
bool NodeBuilder::newArray(NodeVector& elts, MutableHandleValue dst) {
734
const size_t len = elts.length();
735
if (len > UINT32_MAX) {
736
ReportAllocationOverflow(cx);
737
return false;
738
}
739
RootedObject array(cx, NewDenseFullyAllocatedArray(cx, uint32_t(len)));
740
if (!array) {
741
return false;
742
}
743
744
for (size_t i = 0; i < len; i++) {
745
RootedValue val(cx, elts[i]);
746
747
MOZ_ASSERT_IF(val.isMagic(), val.whyMagic() == JS_SERIALIZE_NO_NODE);
748
749
/* Represent "no node" as an array hole by not adding the value. */
750
if (val.isMagic(JS_SERIALIZE_NO_NODE)) {
751
continue;
752
}
753
754
if (!DefineDataElement(cx, array, i, val)) {
755
return false;
756
}
757
}
758
759
dst.setObject(*array);
760
return true;
761
}
762
763
bool NodeBuilder::newNodeLoc(TokenPos* pos, MutableHandleValue dst) {
764
if (!pos) {
765
dst.setNull();
766
return true;
767
}
768
769
RootedObject loc(cx);
770
RootedObject to(cx);
771
RootedValue val(cx);
772
773
if (!newObject(&loc)) {
774
return false;
775
}
776
777
dst.setObject(*loc);
778
779
uint32_t startLineNum, startColumnIndex;
780
uint32_t endLineNum, endColumnIndex;
781
parser->tokenStream.computeLineAndColumn(pos->begin, &startLineNum,
782
&startColumnIndex);
783
parser->tokenStream.computeLineAndColumn(pos->end, &endLineNum,
784
&endColumnIndex);
785
786
if (!newObject(&to)) {
787
return false;
788
}
789
val.setObject(*to);
790
if (!defineProperty(loc, "start", val)) {
791
return false;
792
}
793
val.setNumber(startLineNum);
794
if (!defineProperty(to, "line", val)) {
795
return false;
796
}
797
val.setNumber(startColumnIndex);
798
if (!defineProperty(to, "column", val)) {
799
return false;
800
}
801
802
if (!newObject(&to)) {
803
return false;
804
}
805
val.setObject(*to);
806
if (!defineProperty(loc, "end", val)) {
807
return false;
808
}
809
val.setNumber(endLineNum);
810
if (!defineProperty(to, "line", val)) {
811
return false;
812
}
813
val.setNumber(endColumnIndex);
814
if (!defineProperty(to, "column", val)) {
815
return false;
816
}
817
818
if (!defineProperty(loc, "source", srcval)) {
819
return false;
820
}
821
822
return true;
823
}
824
825
bool NodeBuilder::setNodeLoc(HandleObject node, TokenPos* pos) {
826
if (!saveLoc) {
827
return true;
828
}
829
830
RootedValue loc(cx);
831
return newNodeLoc(pos, &loc) && defineProperty(node, "loc", loc);
832
}
833
834
bool NodeBuilder::program(NodeVector& elts, TokenPos* pos,
835
MutableHandleValue dst) {
836
return listNode(AST_PROGRAM, "body", elts, pos, dst);
837
}
838
839
bool NodeBuilder::blockStatement(NodeVector& elts, TokenPos* pos,
840
MutableHandleValue dst) {
841
return listNode(AST_BLOCK_STMT, "body", elts, pos, dst);
842
}
843
844
bool NodeBuilder::expressionStatement(HandleValue expr, TokenPos* pos,
845
MutableHandleValue dst) {
846
RootedValue cb(cx, callbacks[AST_EXPR_STMT]);
847
if (!cb.isNull()) {
848
return callback(cb, expr, pos, dst);
849
}
850
851
return newNode(AST_EXPR_STMT, pos, "expression", expr, dst);
852
}
853
854
bool NodeBuilder::emptyStatement(TokenPos* pos, MutableHandleValue dst) {
855
RootedValue cb(cx, callbacks[AST_EMPTY_STMT]);
856
if (!cb.isNull()) {
857
return callback(cb, pos, dst);
858
}
859
860
return newNode(AST_EMPTY_STMT, pos, dst);
861
}
862
863
bool NodeBuilder::ifStatement(HandleValue test, HandleValue cons,
864
HandleValue alt, TokenPos* pos,
865
MutableHandleValue dst) {
866
RootedValue cb(cx, callbacks[AST_IF_STMT]);
867
if (!cb.isNull()) {
868
return callback(cb, test, cons, opt(alt), pos, dst);
869
}
870
871
return newNode(AST_IF_STMT, pos, "test", test, "consequent", cons,
872
"alternate", alt, dst);
873
}
874
875
bool NodeBuilder::breakStatement(HandleValue label, TokenPos* pos,
876
MutableHandleValue dst) {
877
RootedValue cb(cx, callbacks[AST_BREAK_STMT]);
878
if (!cb.isNull()) {
879
return callback(cb, opt(label), pos, dst);
880
}
881
882
return newNode(AST_BREAK_STMT, pos, "label", label, dst);
883
}
884
885
bool NodeBuilder::continueStatement(HandleValue label, TokenPos* pos,
886
MutableHandleValue dst) {
887
RootedValue cb(cx, callbacks[AST_CONTINUE_STMT]);
888
if (!cb.isNull()) {
889
return callback(cb, opt(label), pos, dst);
890
}
891
892
return newNode(AST_CONTINUE_STMT, pos, "label", label, dst);
893
}
894
895
bool NodeBuilder::labeledStatement(HandleValue label, HandleValue stmt,
896
TokenPos* pos, MutableHandleValue dst) {
897
RootedValue cb(cx, callbacks[AST_LAB_STMT]);
898
if (!cb.isNull()) {
899
return callback(cb, label, stmt, pos, dst);
900
}
901
902
return newNode(AST_LAB_STMT, pos, "label", label, "body", stmt, dst);
903
}
904
905
bool NodeBuilder::throwStatement(HandleValue arg, TokenPos* pos,
906
MutableHandleValue dst) {
907
RootedValue cb(cx, callbacks[AST_THROW_STMT]);
908
if (!cb.isNull()) {
909
return callback(cb, arg, pos, dst);
910
}
911
912
return newNode(AST_THROW_STMT, pos, "argument", arg, dst);
913
}
914
915
bool NodeBuilder::returnStatement(HandleValue arg, TokenPos* pos,
916
MutableHandleValue dst) {
917
RootedValue cb(cx, callbacks[AST_RETURN_STMT]);
918
if (!cb.isNull()) {
919
return callback(cb, opt(arg), pos, dst);
920
}
921
922
return newNode(AST_RETURN_STMT, pos, "argument", arg, dst);
923
}
924
925
bool NodeBuilder::forStatement(HandleValue init, HandleValue test,
926
HandleValue update, HandleValue stmt,
927
TokenPos* pos, MutableHandleValue dst) {
928
RootedValue cb(cx, callbacks[AST_FOR_STMT]);
929
if (!cb.isNull()) {
930
return callback(cb, opt(init), opt(test), opt(update), stmt, pos, dst);
931
}
932
933
return newNode(AST_FOR_STMT, pos, "init", init, "test", test, "update",
934
update, "body", stmt, dst);
935
}
936
937
bool NodeBuilder::forInStatement(HandleValue var, HandleValue expr,
938
HandleValue stmt, TokenPos* pos,
939
MutableHandleValue dst) {
940
RootedValue cb(cx, callbacks[AST_FOR_IN_STMT]);
941
if (!cb.isNull()) {
942
RootedValue isForEach(
943
cx, JS::FalseValue()); // obsolete E4X `for each` statement
944
return callback(cb, var, expr, stmt, isForEach, pos, dst);
945
}
946
947
return newNode(AST_FOR_IN_STMT, pos, "left", var, "right", expr, "body", stmt,
948
dst);
949
}
950
951
bool NodeBuilder::forOfStatement(HandleValue var, HandleValue expr,
952
HandleValue stmt, TokenPos* pos,
953
MutableHandleValue dst) {
954
RootedValue cb(cx, callbacks[AST_FOR_OF_STMT]);
955
if (!cb.isNull()) {
956
return callback(cb, var, expr, stmt, pos, dst);
957
}
958
959
return newNode(AST_FOR_OF_STMT, pos, "left", var, "right", expr, "body", stmt,
960
dst);
961
}
962
963
bool NodeBuilder::withStatement(HandleValue expr, HandleValue stmt,
964
TokenPos* pos, MutableHandleValue dst) {
965
RootedValue cb(cx, callbacks[AST_WITH_STMT]);
966
if (!cb.isNull()) {
967
return callback(cb, expr, stmt, pos, dst);
968
}
969
970
return newNode(AST_WITH_STMT, pos, "object", expr, "body", stmt, dst);
971
}
972
973
bool NodeBuilder::whileStatement(HandleValue test, HandleValue stmt,
974
TokenPos* pos, MutableHandleValue dst) {
975
RootedValue cb(cx, callbacks[AST_WHILE_STMT]);
976
if (!cb.isNull()) {
977
return callback(cb, test, stmt, pos, dst);
978
}
979
980
return newNode(AST_WHILE_STMT, pos, "test", test, "body", stmt, dst);
981
}
982
983
bool NodeBuilder::doWhileStatement(HandleValue stmt, HandleValue test,
984
TokenPos* pos, MutableHandleValue dst) {
985
RootedValue cb(cx, callbacks[AST_DO_STMT]);
986
if (!cb.isNull()) {
987
return callback(cb, stmt, test, pos, dst);
988
}
989
990
return newNode(AST_DO_STMT, pos, "body", stmt, "test", test, dst);
991
}
992
993
bool NodeBuilder::switchStatement(HandleValue disc, NodeVector& elts,
994
bool lexical, TokenPos* pos,
995
MutableHandleValue dst) {
996
RootedValue array(cx);
997
if (!newArray(elts, &array)) {
998
return false;
999
}
1000
1001
RootedValue lexicalVal(cx, BooleanValue(lexical));
1002
1003
RootedValue cb(cx, callbacks[AST_SWITCH_STMT]);
1004
if (!cb.isNull()) {
1005
return callback(cb, disc, array, lexicalVal, pos, dst);
1006
}
1007
1008
return newNode(AST_SWITCH_STMT, pos, "discriminant", disc, "cases", array,
1009
"lexical", lexicalVal, dst);
1010
}
1011
1012
bool NodeBuilder::tryStatement(HandleValue body, HandleValue handler,
1013
HandleValue finally, TokenPos* pos,
1014
MutableHandleValue dst) {
1015
RootedValue cb(cx, callbacks[AST_TRY_STMT]);
1016
if (!cb.isNull()) {
1017
return callback(cb, body, handler, opt(finally), pos, dst);
1018
}
1019
1020
return newNode(AST_TRY_STMT, pos, "block", body, "handler", handler,
1021
"finalizer", finally, dst);
1022
}
1023
1024
bool NodeBuilder::debuggerStatement(TokenPos* pos, MutableHandleValue dst) {
1025
RootedValue cb(cx, callbacks[AST_DEBUGGER_STMT]);
1026
if (!cb.isNull()) {
1027
return callback(cb, pos, dst);
1028
}
1029
1030
return newNode(AST_DEBUGGER_STMT, pos, dst);
1031
}
1032
1033
bool NodeBuilder::binaryExpression(BinaryOperator op, HandleValue left,
1034
HandleValue right, TokenPos* pos,
1035
MutableHandleValue dst) {
1036
MOZ_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
1037
1038
RootedValue opName(cx);
1039
if (!atomValue(binopNames[op], &opName)) {
1040
return false;
1041
}
1042
1043
RootedValue cb(cx, callbacks[AST_BINARY_EXPR]);
1044
if (!cb.isNull()) {
1045
return callback(cb, opName, left, right, pos, dst);
1046
}
1047
1048
return newNode(AST_BINARY_EXPR, pos, "operator", opName, "left", left,
1049
"right", right, dst);
1050
}
1051
1052
bool NodeBuilder::unaryExpression(UnaryOperator unop, HandleValue expr,
1053
TokenPos* pos, MutableHandleValue dst) {
1054
MOZ_ASSERT(unop > UNOP_ERR && unop < UNOP_LIMIT);
1055
1056
RootedValue opName(cx);
1057
if (!atomValue(unopNames[unop], &opName)) {
1058
return false;
1059
}
1060
1061
RootedValue cb(cx, callbacks[AST_UNARY_EXPR]);
1062
if (!cb.isNull()) {
1063
return callback(cb, opName, expr, pos, dst);
1064
}
1065
1066
RootedValue trueVal(cx, BooleanValue(true));
1067
return newNode(AST_UNARY_EXPR, pos, "operator", opName, "argument", expr,
1068
"prefix", trueVal, dst);
1069
}
1070
1071
bool NodeBuilder::assignmentExpression(AssignmentOperator aop, HandleValue lhs,
1072
HandleValue rhs, TokenPos* pos,
1073
MutableHandleValue dst) {
1074
MOZ_ASSERT(aop > AOP_ERR && aop < AOP_LIMIT);
1075
1076
RootedValue opName(cx);
1077
if (!atomValue(aopNames[aop], &opName)) {
1078
return false;
1079
}
1080
1081
RootedValue cb(cx, callbacks[AST_ASSIGN_EXPR]);
1082
if (!cb.isNull()) {
1083
return callback(cb, opName, lhs, rhs, pos, dst);
1084
}
1085
1086
return newNode(AST_ASSIGN_EXPR, pos, "operator", opName, "left", lhs, "right",
1087
rhs, dst);
1088
}
1089
1090
bool NodeBuilder::updateExpression(HandleValue expr, bool incr, bool prefix,
1091
TokenPos* pos, MutableHandleValue dst) {
1092
RootedValue opName(cx);
1093
if (!atomValue(incr ? "++" : "--", &opName)) {
1094
return false;
1095
}
1096
1097
RootedValue prefixVal(cx, BooleanValue(prefix));
1098
1099
RootedValue cb(cx, callbacks[AST_UPDATE_EXPR]);
1100
if (!cb.isNull()) {
1101
return callback(cb, expr, opName, prefixVal, pos, dst);
1102
}
1103
1104
return newNode(AST_UPDATE_EXPR, pos, "operator", opName, "argument", expr,
1105
"prefix", prefixVal, dst);
1106
}
1107
1108
bool NodeBuilder::logicalExpression(ParseNodeKind pnk, HandleValue left,
1109
HandleValue right, TokenPos* pos,
1110
MutableHandleValue dst) {
1111
RootedValue opName(cx);
1112
switch (pnk) {
1113
case ParseNodeKind::OrExpr:
1114
if (!atomValue("||", &opName)) {
1115
return false;
1116
}
1117
break;
1118
case ParseNodeKind::CoalesceExpr:
1119
if (!atomValue("??", &opName)) {
1120
return false;
1121
}
1122
break;
1123
case ParseNodeKind::AndExpr:
1124
if (!atomValue("&&", &opName)) {
1125
return false;
1126
}
1127
break;
1128
default:
1129
MOZ_CRASH("Unexpected ParseNodeKind: Must be `Or`, `And`, or `Coalesce`");
1130
}
1131
1132
RootedValue cb(cx, callbacks[AST_LOGICAL_EXPR]);
1133
if (!cb.isNull()) {
1134
return callback(cb, opName, left, right, pos, dst);
1135
}
1136
1137
return newNode(AST_LOGICAL_EXPR, pos, "operator", opName, "left", left,
1138
"right", right, dst);
1139
}
1140
1141
bool NodeBuilder::conditionalExpression(HandleValue test, HandleValue cons,
1142
HandleValue alt, TokenPos* pos,
1143
MutableHandleValue dst) {
1144
RootedValue cb(cx, callbacks[AST_COND_EXPR]);
1145
if (!cb.isNull()) {
1146
return callback(cb, test, cons, alt, pos, dst);
1147
}
1148
1149
return newNode(AST_COND_EXPR, pos, "test", test, "consequent", cons,
1150
"alternate", alt, dst);
1151
}
1152
1153
bool NodeBuilder::sequenceExpression(NodeVector& elts, TokenPos* pos,
1154
MutableHandleValue dst) {
1155
return listNode(AST_LIST_EXPR, "expressions", elts, pos, dst);
1156
}
1157
1158
bool NodeBuilder::callExpression(HandleValue callee, NodeVector& args,
1159
TokenPos* pos, MutableHandleValue dst) {
1160
RootedValue array(cx);
1161
if (!newArray(args, &array)) {
1162
return false;
1163
}
1164
1165
RootedValue cb(cx, callbacks[AST_CALL_EXPR]);
1166
if (!cb.isNull()) {
1167
return callback(cb, callee, array, pos, dst);
1168
}
1169
1170
return newNode(AST_CALL_EXPR, pos, "callee", callee, "arguments", array, dst);
1171
}
1172
1173
bool NodeBuilder::newExpression(HandleValue callee, NodeVector& args,
1174
TokenPos* pos, MutableHandleValue dst) {
1175
RootedValue array(cx);
1176
if (!newArray(args, &array)) {
1177
return false;
1178
}
1179
1180
RootedValue cb(cx, callbacks[AST_NEW_EXPR]);
1181
if (!cb.isNull()) {
1182
return callback(cb, callee, array, pos, dst);
1183
}
1184
1185
return newNode(AST_NEW_EXPR, pos, "callee", callee, "arguments", array, dst);
1186
}
1187
1188
bool NodeBuilder::memberExpression(bool computed, HandleValue expr,
1189
HandleValue member, TokenPos* pos,
1190
MutableHandleValue dst) {
1191
RootedValue computedVal(cx, BooleanValue(computed));
1192
1193
RootedValue cb(cx, callbacks[AST_MEMBER_EXPR]);
1194
if (!cb.isNull()) {
1195
return callback(cb, computedVal, expr, member, pos, dst);
1196
}
1197
1198
return newNode(AST_MEMBER_EXPR, pos, "object", expr, "property", member,
1199
"computed", computedVal, dst);
1200
}
1201
1202
bool NodeBuilder::arrayExpression(NodeVector& elts, TokenPos* pos,
1203
MutableHandleValue dst) {
1204
return listNode(AST_ARRAY_EXPR, "elements", elts, pos, dst);
1205
}
1206
1207
bool NodeBuilder::callSiteObj(NodeVector& raw, NodeVector& cooked,
1208
TokenPos* pos, MutableHandleValue dst) {
1209
RootedValue rawVal(cx);
1210
if (!newArray(raw, &rawVal)) {
1211
return false;
1212
}
1213
1214
RootedValue cookedVal(cx);
1215
if (!newArray(cooked, &cookedVal)) {
1216
return false;
1217
}
1218
1219
return newNode(AST_CALL_SITE_OBJ, pos, "raw", rawVal, "cooked", cookedVal,
1220
dst);
1221
}
1222
1223
bool NodeBuilder::taggedTemplate(HandleValue callee, NodeVector& args,
1224
TokenPos* pos, MutableHandleValue dst) {
1225
RootedValue array(cx);
1226
if (!newArray(args, &array)) {
1227
return false;
1228
}
1229
1230
return newNode(AST_TAGGED_TEMPLATE, pos, "callee", callee, "arguments", array,
1231
dst);
1232
}
1233
1234
bool NodeBuilder::templateLiteral(NodeVector& elts, TokenPos* pos,
1235
MutableHandleValue dst) {
1236
return listNode(AST_TEMPLATE_LITERAL, "elements", elts, pos, dst);
1237
}
1238
1239
bool NodeBuilder::computedName(HandleValue name, TokenPos* pos,
1240
MutableHandleValue dst) {
1241
return newNode(AST_COMPUTED_NAME, pos, "name", name, dst);
1242
}
1243
1244
bool NodeBuilder::spreadExpression(HandleValue expr, TokenPos* pos,
1245
MutableHandleValue dst) {
1246
return newNode(AST_SPREAD_EXPR, pos, "expression", expr, dst);
1247
}
1248
1249
bool NodeBuilder::propertyPattern(HandleValue key, HandleValue patt,
1250
bool isShorthand, TokenPos* pos,
1251
MutableHandleValue dst) {
1252
RootedValue kindName(cx);
1253
if (!atomValue("init", &kindName)) {
1254
return false;
1255
}
1256
1257
RootedValue isShorthandVal(cx, BooleanValue(isShorthand));
1258
1259
RootedValue cb(cx, callbacks[AST_PROP_PATT]);
1260
if (!cb.isNull()) {
1261
return callback(cb, key, patt, pos, dst);
1262
}
1263
1264
return newNode(AST_PROP_PATT, pos, "key", key, "value", patt, "kind",
1265
kindName, "shorthand", isShorthandVal, dst);
1266
}
1267
1268
bool NodeBuilder::prototypeMutation(HandleValue val, TokenPos* pos,
1269
MutableHandleValue dst) {
1270
RootedValue cb(cx, callbacks[AST_PROTOTYPEMUTATION]);
1271
if (!cb.isNull()) {
1272
return callback(cb, val, pos, dst);
1273
}
1274
1275
return newNode(AST_PROTOTYPEMUTATION, pos, "value", val, dst);
1276
}
1277
1278
bool NodeBuilder::propertyInitializer(HandleValue key, HandleValue val,
1279
PropKind kind, bool isShorthand,
1280
bool isMethod, TokenPos* pos,
1281
MutableHandleValue dst) {
1282
RootedValue kindName(cx);
1283
if (!atomValue(
1284
kind == PROP_INIT ? "init" : kind == PROP_GETTER ? "get" : "set",
1285
&kindName)) {
1286
return false;
1287
}
1288
1289
RootedValue isShorthandVal(cx, BooleanValue(isShorthand));
1290
RootedValue isMethodVal(cx, BooleanValue(isMethod));
1291
1292
RootedValue cb(cx, callbacks[AST_PROPERTY]);
1293
if (!cb.isNull()) {
1294
return callback(cb, kindName, key, val, pos, dst);
1295
}
1296
1297
return newNode(AST_PROPERTY, pos, "key", key, "value", val, "kind", kindName,
1298
"method", isMethodVal, "shorthand", isShorthandVal, dst);
1299
}
1300
1301
bool NodeBuilder::objectExpression(NodeVector& elts, TokenPos* pos,
1302
MutableHandleValue dst) {
1303
return listNode(AST_OBJECT_EXPR, "properties", elts, pos, dst);
1304
}
1305
1306
bool NodeBuilder::thisExpression(TokenPos* pos, MutableHandleValue dst) {
1307
RootedValue cb(cx, callbacks[AST_THIS_EXPR]);
1308
if (!cb.isNull()) {
1309
return callback(cb, pos, dst);
1310
}
1311
1312
return newNode(AST_THIS_EXPR, pos, dst);
1313
}
1314
1315
bool NodeBuilder::yieldExpression(HandleValue arg, YieldKind kind,
1316
TokenPos* pos, MutableHandleValue dst) {
1317
RootedValue cb(cx, callbacks[AST_YIELD_EXPR]);
1318
RootedValue delegateVal(cx);
1319
1320
switch (kind) {
1321
case Delegating:
1322
delegateVal = BooleanValue(true);
1323
break;
1324
case NotDelegating:
1325
delegateVal = BooleanValue(false);
1326
break;
1327
}
1328
1329
if (!cb.isNull()) {
1330
return callback(cb, opt(arg), delegateVal, pos, dst);
1331
}
1332
return newNode(AST_YIELD_EXPR, pos, "argument", arg, "delegate", delegateVal,
1333
dst);
1334
}
1335
1336
bool NodeBuilder::importDeclaration(NodeVector& elts, HandleValue moduleSpec,
1337
TokenPos* pos, MutableHandleValue dst) {
1338
RootedValue array(cx);
1339
if (!newArray(elts, &array)) {
1340
return false;
1341
}
1342
1343
RootedValue cb(cx, callbacks[AST_IMPORT_DECL]);
1344
if (!cb.isNull()) {
1345
return callback(cb, array, moduleSpec, pos, dst);
1346
}
1347
1348
return newNode(AST_IMPORT_DECL, pos, "specifiers", array, "source",
1349
moduleSpec, dst);
1350
}
1351
1352
bool NodeBuilder::importSpecifier(HandleValue importName,
1353
HandleValue bindingName, TokenPos* pos,
1354
MutableHandleValue dst) {
1355
RootedValue cb(cx, callbacks[AST_IMPORT_SPEC]);
1356
if (!cb.isNull()) {
1357
return callback(cb, importName, bindingName, pos, dst);
1358
}
1359
1360
return newNode(AST_IMPORT_SPEC, pos, "id", importName, "name", bindingName,
1361
dst);
1362
}
1363
1364
bool NodeBuilder::exportDeclaration(HandleValue decl, NodeVector& elts,
1365
HandleValue moduleSpec,
1366
HandleValue isDefault, TokenPos* pos,
1367
MutableHandleValue dst) {
1368
RootedValue array(cx, NullValue());
1369
if (decl.isNull() && !newArray(elts, &array)) {
1370
return false;
1371
}
1372
1373
RootedValue cb(cx, callbacks[AST_EXPORT_DECL]);
1374
1375
if (!cb.isNull()) {
1376
return callback(cb, decl, array, moduleSpec, pos, dst);
1377
}
1378
1379
return newNode(AST_EXPORT_DECL, pos, "declaration", decl, "specifiers", array,
1380
"source", moduleSpec, "isDefault", isDefault, dst);
1381
}
1382
1383
bool NodeBuilder::exportSpecifier(HandleValue bindingName,
1384
HandleValue exportName, TokenPos* pos,
1385
MutableHandleValue dst) {
1386
RootedValue cb(cx, callbacks[AST_EXPORT_SPEC]);
1387
if (!cb.isNull()) {
1388
return callback(cb, bindingName, exportName, pos, dst);
1389
}
1390
1391
return newNode(AST_EXPORT_SPEC, pos, "id", bindingName, "name", exportName,
1392
dst);
1393
}
1394
1395
bool NodeBuilder::exportBatchSpecifier(TokenPos* pos, MutableHandleValue dst) {
1396
RootedValue cb(cx, callbacks[AST_EXPORT_BATCH_SPEC]);
1397
if (!cb.isNull()) {
1398
return callback(cb, pos, dst);
1399
}
1400
1401
return newNode(AST_EXPORT_BATCH_SPEC, pos, dst);
1402
}
1403
1404
bool NodeBuilder::variableDeclaration(NodeVector& elts, VarDeclKind kind,
1405
TokenPos* pos, MutableHandleValue dst) {
1406
MOZ_ASSERT(kind > VARDECL_ERR && kind < VARDECL_LIMIT);
1407
1408
RootedValue array(cx), kindName(cx);
1409
if (!newArray(elts, &array) ||
1410
!atomValue(
1411
kind == VARDECL_CONST ? "const" : kind == VARDECL_LET ? "let" : "var",
1412
&kindName)) {
1413
return false;
1414
}
1415
1416
RootedValue cb(cx, callbacks[AST_VAR_DECL]);
1417
if (!cb.isNull()) {
1418
return callback(cb, kindName, array, pos, dst);
1419
}
1420
1421
return newNode(AST_VAR_DECL, pos, "kind", kindName, "declarations", array,
1422
dst);
1423
}
1424
1425
bool NodeBuilder::variableDeclarator(HandleValue id, HandleValue init,
1426
TokenPos* pos, MutableHandleValue dst) {
1427
RootedValue cb(cx, callbacks[AST_VAR_DTOR]);
1428
if (!cb.isNull()) {
1429
return callback(cb, id, opt(init), pos, dst);
1430
}
1431
1432
return newNode(AST_VAR_DTOR, pos, "id", id, "init", init, dst);
1433
}
1434
1435
bool NodeBuilder::switchCase(HandleValue expr, NodeVector& elts, TokenPos* pos,
1436
MutableHandleValue dst) {
1437
RootedValue array(cx);
1438
if (!newArray(elts, &array)) {
1439
return false;
1440
}
1441
1442
RootedValue cb(cx, callbacks[AST_CASE]);
1443
if (!cb.isNull()) {
1444
return callback(cb, opt(expr), array, pos, dst);
1445
}
1446
1447
return newNode(AST_CASE, pos, "test", expr, "consequent", array, dst);
1448
}
1449
1450
bool NodeBuilder::catchClause(HandleValue var, HandleValue body, TokenPos* pos,
1451
MutableHandleValue dst) {
1452
RootedValue cb(cx, callbacks[AST_CATCH]);
1453
if (!cb.isNull()) {
1454
return callback(cb, opt(var), body, pos, dst);
1455
}
1456
1457
return newNode(AST_CATCH, pos, "param", var, "body", body, dst);
1458
}
1459
1460
bool NodeBuilder::literal(HandleValue val, TokenPos* pos,
1461
MutableHandleValue dst) {
1462
RootedValue cb(cx, callbacks[AST_LITERAL]);
1463
if (!cb.isNull()) {
1464
return callback(cb, val, pos, dst);
1465
}
1466
1467
return newNode(AST_LITERAL, pos, "value", val, dst);
1468
}
1469
1470
bool NodeBuilder::identifier(HandleValue name, TokenPos* pos,
1471
MutableHandleValue dst) {
1472
RootedValue cb(cx, callbacks[AST_IDENTIFIER]);
1473
if (!cb.isNull()) {
1474
return callback(cb, name, pos, dst);
1475
}
1476
1477
return newNode(AST_IDENTIFIER, pos, "name", name, dst);
1478
}
1479
1480
bool NodeBuilder::objectPattern(NodeVector& elts, TokenPos* pos,
1481
MutableHandleValue dst) {
1482
return listNode(AST_OBJECT_PATT, "properties", elts, pos, dst);
1483
}
1484
1485
bool NodeBuilder::arrayPattern(NodeVector& elts, TokenPos* pos,
1486
MutableHandleValue dst) {
1487
return listNode(AST_ARRAY_PATT, "elements", elts, pos, dst);
1488
}
1489
1490
bool NodeBuilder::function(ASTType type, TokenPos* pos, HandleValue id,
1491
NodeVector& args, NodeVector& defaults,
1492
HandleValue body, HandleValue rest,
1493
GeneratorStyle generatorStyle, bool isAsync,
1494
bool isExpression, MutableHandleValue dst) {
1495
RootedValue array(cx), defarray(cx);
1496
if (!newArray(args, &array)) {
1497
return false;
1498
}
1499
if (!newArray(defaults, &defarray)) {
1500
return false;
1501
}
1502
1503
bool isGenerator = generatorStyle != GeneratorStyle::None;
1504
RootedValue isGeneratorVal(cx, BooleanValue(isGenerator));
1505
RootedValue isAsyncVal(cx, BooleanValue(isAsync));
1506
RootedValue isExpressionVal(cx, BooleanValue(isExpression));
1507
1508
RootedValue cb(cx, callbacks[type]);
1509
if (!cb.isNull()) {
1510
return callback(cb, opt(id), array, body, isGeneratorVal, isExpressionVal,
1511
pos, dst);
1512
}
1513
1514
if (isGenerator) {
1515
MOZ_ASSERT(generatorStyle == GeneratorStyle::ES6);
1516
JSAtom* styleStr = Atomize(cx, "es6", 3);
1517
if (!styleStr) {
1518
return false;
1519
}
1520
RootedValue styleVal(cx, StringValue(styleStr));
1521
return newNode(type, pos, "id", id, "params", array, "defaults", defarray,
1522
"body", body, "rest", rest, "generator", isGeneratorVal,
1523
"async", isAsyncVal, "style", styleVal, "expression",
1524
isExpressionVal, dst);
1525
}
1526
1527
return newNode(type, pos, "id", id, "params", array, "defaults", defarray,
1528
"body", body, "rest", rest, "generator", isGeneratorVal,
1529
"async", isAsyncVal, "expression", isExpressionVal, dst);
1530
}
1531
1532
bool NodeBuilder::classMethod(HandleValue name, HandleValue body, PropKind kind,
1533
bool isStatic, TokenPos* pos,
1534
MutableHandleValue dst) {
1535
RootedValue kindName(cx);
1536
if (!atomValue(
1537
kind == PROP_INIT ? "method" : kind == PROP_GETTER ? "get" : "set",
1538
&kindName)) {
1539
return false;
1540
}
1541
1542
RootedValue isStaticVal(cx, BooleanValue(isStatic));
1543
RootedValue cb(cx, callbacks[AST_CLASS_METHOD]);
1544
if (!cb.isNull()) {
1545
return callback(cb, kindName, name, body, isStaticVal, pos, dst);
1546
}
1547
1548
return newNode(AST_CLASS_METHOD, pos, "name", name, "body", body, "kind",
1549
kindName, "static", isStaticVal, dst);
1550
}
1551
1552
bool NodeBuilder::classField(HandleValue name, HandleValue initializer,
1553
TokenPos* pos, MutableHandleValue dst) {
1554
RootedValue cb(cx, callbacks[AST_CLASS_FIELD]);
1555
if (!cb.isNull()) {
1556
return callback(cb, name, initializer, pos, dst);
1557
}
1558
1559
return newNode(AST_CLASS_FIELD, pos, "name", name, "init", initializer, dst);
1560
}
1561
1562
bool NodeBuilder::classMembers(NodeVector& members, MutableHandleValue dst) {
1563
return newArray(members, dst);
1564
}
1565
1566
bool NodeBuilder::classDefinition(bool expr, HandleValue name,
1567
HandleValue heritage, HandleValue block,
1568
TokenPos* pos, MutableHandleValue dst) {
1569
ASTType type = expr ? AST_CLASS_EXPR : AST_CLASS_STMT;
1570
RootedValue cb(cx, callbacks[type]);
1571
if (!cb.isNull()) {
1572
return callback(cb, name, heritage, block, pos, dst);
1573
}
1574
1575
return newNode(type, pos, "id", name, "superClass", heritage, "body", block,
1576
dst);
1577
}
1578
1579
bool NodeBuilder::metaProperty(HandleValue meta, HandleValue property,
1580
TokenPos* pos, MutableHandleValue dst) {
1581
RootedValue cb(cx, callbacks[AST_METAPROPERTY]);