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
/*
8
* JS parser.
9
*
10
* This is a recursive-descent parser for the JavaScript language specified by
11
* "The ECMAScript Language Specification" (Standard ECMA-262). It uses
12
* lexical and semantic feedback to disambiguate non-LL(1) structures. It
13
* generates trees of nodes induced by the recursive parsing (not precise
14
* syntax trees, see Parser.h). After tree construction, it rewrites trees to
15
* fold constants and evaluate compile-time expressions.
16
*
17
* This parser attempts no error recovery.
18
*/
19
20
#include "frontend/Parser.h"
21
22
#include "mozilla/ArrayUtils.h"
23
#include "mozilla/Casting.h"
24
#include "mozilla/Range.h"
25
#include "mozilla/Sprintf.h"
26
#include "mozilla/TypeTraits.h"
27
#include "mozilla/Unused.h"
28
#include "mozilla/Utf8.h"
29
#include "mozilla/Variant.h"
30
31
#include <memory>
32
#include <new>
33
34
#include "jsnum.h"
35
#include "jstypes.h"
36
37
#include "builtin/ModuleObject.h"
38
#include "builtin/SelfHostingDefines.h"
39
#include "frontend/BytecodeCompiler.h"
40
#include "frontend/FoldConstants.h"
41
#include "frontend/ModuleSharedContext.h"
42
#include "frontend/ParseNode.h"
43
#include "frontend/ParseNodeVerify.h"
44
#include "frontend/TokenStream.h"
45
#include "irregexp/RegExpParser.h"
46
#include "js/RegExpFlags.h" // JS::RegExpFlags
47
#include "vm/BytecodeUtil.h"
48
#include "vm/JSAtom.h"
49
#include "vm/JSContext.h"
50
#include "vm/JSFunction.h"
51
#include "vm/JSScript.h"
52
#include "vm/ModuleBuilder.h" // js::ModuleBuilder
53
#include "vm/RegExpObject.h"
54
#include "vm/SelfHosting.h"
55
#include "vm/StringType.h"
56
#include "wasm/AsmJS.h"
57
58
#include "frontend/ParseContext-inl.h"
59
#include "frontend/SharedContext-inl.h"
60
#include "vm/EnvironmentObject-inl.h"
61
62
using namespace js;
63
64
using mozilla::AssertedCast;
65
using mozilla::AsVariant;
66
using mozilla::Maybe;
67
using mozilla::Nothing;
68
using mozilla::PodCopy;
69
using mozilla::PodZero;
70
using mozilla::PointerRangeSize;
71
using mozilla::Some;
72
using mozilla::Unused;
73
using mozilla::Utf8Unit;
74
75
using JS::AutoGCRooter;
76
using JS::ReadOnlyCompileOptions;
77
using JS::RegExpFlags;
78
79
namespace js {
80
namespace frontend {
81
82
using DeclaredNamePtr = ParseContext::Scope::DeclaredNamePtr;
83
using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr;
84
using BindingIter = ParseContext::Scope::BindingIter;
85
using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
86
87
using BindingNameVector = Vector<BindingName, 6>;
88
89
template <class T, class U>
90
static inline void PropagateTransitiveParseFlags(const T* inner, U* outer) {
91
if (inner->bindingsAccessedDynamically()) {
92
outer->setBindingsAccessedDynamically();
93
}
94
if (inner->hasDirectEval()) {
95
outer->setHasDirectEval();
96
}
97
}
98
99
static bool StatementKindIsBraced(StatementKind kind) {
100
return kind == StatementKind::Block || kind == StatementKind::Switch ||
101
kind == StatementKind::Try || kind == StatementKind::Catch ||
102
kind == StatementKind::Finally || kind == StatementKind::Class;
103
}
104
105
template <class ParseHandler, typename Unit>
106
inline typename GeneralParser<ParseHandler, Unit>::FinalParser*
107
GeneralParser<ParseHandler, Unit>::asFinalParser() {
108
static_assert(
109
mozilla::IsBaseOf<GeneralParser<ParseHandler, Unit>, FinalParser>::value,
110
"inheritance relationship required by the static_cast<> below");
111
112
return static_cast<FinalParser*>(this);
113
}
114
115
template <class ParseHandler, typename Unit>
116
inline const typename GeneralParser<ParseHandler, Unit>::FinalParser*
117
GeneralParser<ParseHandler, Unit>::asFinalParser() const {
118
static_assert(
119
mozilla::IsBaseOf<GeneralParser<ParseHandler, Unit>, FinalParser>::value,
120
"inheritance relationship required by the static_cast<> below");
121
122
return static_cast<const FinalParser*>(this);
123
}
124
125
template <class ParseHandler, typename Unit>
126
template <typename ConditionT, typename ErrorReportT>
127
bool GeneralParser<ParseHandler, Unit>::mustMatchTokenInternal(
128
ConditionT condition, ErrorReportT errorReport) {
129
MOZ_ASSERT(condition(TokenKind::Div) == false);
130
MOZ_ASSERT(condition(TokenKind::DivAssign) == false);
131
MOZ_ASSERT(condition(TokenKind::RegExp) == false);
132
133
TokenKind actual;
134
if (!tokenStream.getToken(&actual, TokenStream::SlashIsInvalid)) {
135
return false;
136
}
137
if (!condition(actual)) {
138
errorReport(actual);
139
return false;
140
}
141
return true;
142
}
143
144
ParserSharedBase::ParserSharedBase(JSContext* cx, LifoAlloc& alloc,
145
UsedNameTracker& usedNames,
146
ScriptSourceObject* sourceObject, Kind kind)
147
: JS::AutoGCRooter(
148
cx,
149
#ifdef JS_BUILD_BINAST
150
kind == Kind::Parser ? JS::AutoGCRooter::Tag::Parser
151
: JS::AutoGCRooter::Tag::BinASTParser
152
#else
153
JS::AutoGCRooter::Tag::Parser
154
#endif
155
),
156
cx_(cx),
157
alloc_(alloc),
158
traceListHead_(nullptr),
159
pc_(nullptr),
160
usedNames_(usedNames),
161
sourceObject_(cx, sourceObject),
162
keepAtoms_(cx) {
163
cx->frontendCollectionPool().addActiveCompilation();
164
tempPoolMark_ = alloc_.mark();
165
}
166
167
ParserSharedBase::~ParserSharedBase() {
168
alloc_.release(tempPoolMark_);
169
170
/*
171
* The parser can allocate enormous amounts of memory for large functions.
172
* Eagerly free the memory now (which otherwise won't be freed until the
173
* next GC) to avoid unnecessary OOMs.
174
*/
175
alloc_.freeAllIfHugeAndUnused();
176
177
cx_->frontendCollectionPool().removeActiveCompilation();
178
}
179
180
ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
181
const ReadOnlyCompileOptions& options,
182
bool foldConstants, UsedNameTracker& usedNames,
183
ScriptSourceObject* sourceObject, ParseGoal parseGoal)
184
: ParserSharedBase(cx, alloc, usedNames, sourceObject,
185
ParserSharedBase::Kind::Parser),
186
anyChars(cx, options, this),
187
ss(nullptr),
188
foldConstants_(foldConstants),
189
#ifdef DEBUG
190
checkOptionsCalled_(false),
191
#endif
192
isUnexpectedEOF_(false),
193
awaitHandling_(AwaitIsName),
194
inParametersOfAsyncFunction_(false),
195
parseGoal_(uint8_t(parseGoal)) {
196
}
197
198
bool ParserBase::checkOptions() {
199
#ifdef DEBUG
200
checkOptionsCalled_ = true;
201
#endif
202
203
return anyChars.checkOptions();
204
}
205
206
ParserBase::~ParserBase() { MOZ_ASSERT(checkOptionsCalled_); }
207
208
template <class ParseHandler>
209
PerHandlerParser<ParseHandler>::PerHandlerParser(
210
JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
211
bool foldConstants, UsedNameTracker& usedNames,
212
LazyScript* lazyOuterFunction, ScriptSourceObject* sourceObject,
213
ParseGoal parseGoal, void* internalSyntaxParser)
214
: ParserBase(cx, alloc, options, foldConstants, usedNames, sourceObject,
215
parseGoal),
216
handler_(cx, alloc, lazyOuterFunction),
217
internalSyntaxParser_(internalSyntaxParser) {}
218
219
template <class ParseHandler, typename Unit>
220
GeneralParser<ParseHandler, Unit>::GeneralParser(
221
JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
222
const Unit* units, size_t length, bool foldConstants,
223
UsedNameTracker& usedNames, SyntaxParser* syntaxParser,
224
LazyScript* lazyOuterFunction, ScriptSourceObject* sourceObject,
225
ParseGoal parseGoal)
226
: Base(cx, alloc, options, foldConstants, usedNames, syntaxParser,
227
lazyOuterFunction, sourceObject, parseGoal),
228
tokenStream(cx, options, units, length) {}
229
230
template <typename Unit>
231
void Parser<SyntaxParseHandler, Unit>::setAwaitHandling(
232
AwaitHandling awaitHandling) {
233
this->awaitHandling_ = awaitHandling;
234
}
235
236
template <typename Unit>
237
void Parser<FullParseHandler, Unit>::setAwaitHandling(
238
AwaitHandling awaitHandling) {
239
this->awaitHandling_ = awaitHandling;
240
if (SyntaxParser* syntaxParser = getSyntaxParser()) {
241
syntaxParser->setAwaitHandling(awaitHandling);
242
}
243
}
244
245
template <class ParseHandler, typename Unit>
246
inline void GeneralParser<ParseHandler, Unit>::setAwaitHandling(
247
AwaitHandling awaitHandling) {
248
asFinalParser()->setAwaitHandling(awaitHandling);
249
}
250
251
template <typename Unit>
252
void Parser<SyntaxParseHandler, Unit>::setInParametersOfAsyncFunction(
253
bool inParameters) {
254
this->inParametersOfAsyncFunction_ = inParameters;
255
}
256
257
template <typename Unit>
258
void Parser<FullParseHandler, Unit>::setInParametersOfAsyncFunction(
259
bool inParameters) {
260
this->inParametersOfAsyncFunction_ = inParameters;
261
if (SyntaxParser* syntaxParser = getSyntaxParser()) {
262
syntaxParser->setInParametersOfAsyncFunction(inParameters);
263
}
264
}
265
266
template <class ParseHandler, typename Unit>
267
inline void GeneralParser<ParseHandler, Unit>::setInParametersOfAsyncFunction(
268
bool inParameters) {
269
asFinalParser()->setInParametersOfAsyncFunction(inParameters);
270
}
271
272
template <typename BoxT, typename ArgT>
273
BoxT* ParserSharedBase::newTraceListNode(ArgT* arg) {
274
MOZ_ASSERT(arg);
275
276
/*
277
* We use JSContext.tempLifoAlloc to allocate parsed objects and place them
278
* on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
279
* arenas containing the entries must be alive until we are done with
280
* scanning, parsing and code generation for the whole script or top-level
281
* function.
282
*/
283
284
BoxT* box = alloc_.template new_<BoxT>(arg, traceListHead_);
285
if (!box) {
286
ReportOutOfMemory(cx_);
287
return nullptr;
288
}
289
290
traceListHead_ = box;
291
292
return box;
293
}
294
295
ObjectBox* ParserSharedBase::newObjectBox(JSObject* obj) {
296
return newTraceListNode<ObjectBox, JSObject>(obj);
297
}
298
299
BigIntBox* ParserSharedBase::newBigIntBox(BigInt* val) {
300
return newTraceListNode<BigIntBox, BigInt>(val);
301
}
302
303
template <class ParseHandler>
304
FunctionBox* PerHandlerParser<ParseHandler>::newFunctionBox(
305
FunctionNodeType funNode, JSFunction* fun, uint32_t toStringStart,
306
Directives inheritedDirectives, GeneratorKind generatorKind,
307
FunctionAsyncKind asyncKind) {
308
MOZ_ASSERT(fun);
309
310
/*
311
* We use JSContext.tempLifoAlloc to allocate parsed objects and place them
312
* on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
313
* arenas containing the entries must be alive until we are done with
314
* scanning, parsing and code generation for the whole script or top-level
315
* function.
316
*/
317
FunctionBox* funbox = alloc_.new_<FunctionBox>(
318
cx_, traceListHead_, fun, toStringStart, inheritedDirectives,
319
options().extraWarningsOption, generatorKind, asyncKind);
320
if (!funbox) {
321
ReportOutOfMemory(cx_);
322
return nullptr;
323
}
324
325
traceListHead_ = funbox;
326
if (funNode) {
327
handler_.setFunctionBox(funNode, funbox);
328
}
329
330
return funbox;
331
}
332
333
void ParserBase::trace(JSTracer* trc) {
334
TraceListNode::TraceList(trc, traceListHead_);
335
}
336
337
void TraceParser(JSTracer* trc, AutoGCRooter* parser) {
338
static_cast<ParserBase*>(parser)->trace(trc);
339
}
340
341
bool ParserBase::setSourceMapInfo() {
342
// Not all clients initialize ss. Can't update info to an object that isn't
343
// there.
344
if (!ss) {
345
return true;
346
}
347
348
if (anyChars.hasDisplayURL()) {
349
if (!ss->setDisplayURL(cx_, anyChars.displayURL())) {
350
return false;
351
}
352
}
353
354
if (anyChars.hasSourceMapURL()) {
355
MOZ_ASSERT(!ss->hasSourceMapURL());
356
if (!ss->setSourceMapURL(cx_, anyChars.sourceMapURL())) {
357
return false;
358
}
359
}
360
361
/*
362
* Source map URLs passed as a compile option (usually via a HTTP source map
363
* header) override any source map urls passed as comment pragmas.
364
*/
365
if (options().sourceMapURL()) {
366
// Warn about the replacement, but use the new one.
367
if (ss->hasSourceMapURL()) {
368
if (!warningNoOffset(JSMSG_ALREADY_HAS_PRAGMA, ss->filename(),
369
"//# sourceMappingURL")) {
370
return false;
371
}
372
}
373
374
if (!ss->setSourceMapURL(cx_, options().sourceMapURL())) {
375
return false;
376
}
377
}
378
379
return true;
380
}
381
382
/*
383
* Parse a top-level JS script.
384
*/
385
template <class ParseHandler, typename Unit>
386
typename ParseHandler::ListNodeType GeneralParser<ParseHandler, Unit>::parse() {
387
MOZ_ASSERT(checkOptionsCalled_);
388
389
Directives directives(options().strictOption);
390
GlobalSharedContext globalsc(cx_, ScopeKind::Global, directives,
391
options().extraWarningsOption);
392
SourceParseContext globalpc(this, &globalsc, /* newDirectives = */ nullptr);
393
if (!globalpc.init()) {
394
return null();
395
}
396
397
ParseContext::VarScope varScope(this);
398
if (!varScope.init(pc_)) {
399
return null();
400
}
401
402
ListNodeType stmtList = statementList(YieldIsName);
403
if (!stmtList) {
404
return null();
405
}
406
407
TokenKind tt;
408
if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
409
return null();
410
}
411
if (tt != TokenKind::Eof) {
412
error(JSMSG_GARBAGE_AFTER_INPUT, "script", TokenKindToDesc(tt));
413
return null();
414
}
415
416
if (!CheckParseTree(cx_, alloc_, stmtList)) {
417
return null();
418
}
419
420
if (foldConstants_) {
421
Node node = stmtList;
422
// Don't constant-fold inside "use asm" code, as this could create a parse
423
// tree that doesn't type-check as asm.js.
424
if (!pc_->useAsmOrInsideUseAsm()) {
425
if (!FoldConstants(cx_, &node, &handler_)) {
426
return null();
427
}
428
}
429
stmtList = handler_.asList(node);
430
}
431
432
return stmtList;
433
}
434
435
/*
436
* Strict mode forbids introducing new definitions for 'eval', 'arguments',
437
* 'let', 'static', 'yield', or for any strict mode reserved word.
438
*/
439
bool ParserBase::isValidStrictBinding(PropertyName* name) {
440
TokenKind tt = ReservedWordTokenKind(name);
441
if (tt == TokenKind::Name) {
442
return name != cx_->names().eval && name != cx_->names().arguments;
443
}
444
return tt != TokenKind::Let && tt != TokenKind::Static &&
445
tt != TokenKind::Yield && !TokenKindIsStrictReservedWord(tt);
446
}
447
448
/*
449
* Returns true if all parameter names are valid strict mode binding names and
450
* no duplicate parameter names are present.
451
*/
452
bool ParserBase::hasValidSimpleStrictParameterNames() {
453
MOZ_ASSERT(pc_->isFunctionBox() &&
454
pc_->functionBox()->hasSimpleParameterList());
455
456
if (pc_->functionBox()->hasDuplicateParameters) {
457
return false;
458
}
459
460
for (auto* name : pc_->positionalFormalParameterNames()) {
461
MOZ_ASSERT(name);
462
if (!isValidStrictBinding(name->asPropertyName())) {
463
return false;
464
}
465
}
466
return true;
467
}
468
469
template <class ParseHandler, typename Unit>
470
void GeneralParser<ParseHandler, Unit>::reportMissingClosing(
471
unsigned errorNumber, unsigned noteNumber, uint32_t openedPos) {
472
auto notes = MakeUnique<JSErrorNotes>();
473
if (!notes) {
474
ReportOutOfMemory(pc_->sc()->cx_);
475
return;
476
}
477
478
uint32_t line, column;
479
tokenStream.computeLineAndColumn(openedPos, &line, &column);
480
481
const size_t MaxWidth = sizeof("4294967295");
482
char columnNumber[MaxWidth];
483
SprintfLiteral(columnNumber, "%" PRIu32, column);
484
char lineNumber[MaxWidth];
485
SprintfLiteral(lineNumber, "%" PRIu32, line);
486
487
if (!notes->addNoteASCII(pc_->sc()->cx_, getFilename(), 0, line, column,
488
GetErrorMessage, nullptr, noteNumber, lineNumber,
489
columnNumber)) {
490
return;
491
}
492
493
errorWithNotes(std::move(notes), errorNumber);
494
}
495
496
template <class ParseHandler, typename Unit>
497
void GeneralParser<ParseHandler, Unit>::reportRedeclaration(
498
HandlePropertyName name, DeclarationKind prevKind, TokenPos pos,
499
uint32_t prevPos) {
500
UniqueChars bytes = AtomToPrintableString(cx_, name);
501
if (!bytes) {
502
return;
503
}
504
505
if (prevPos == DeclaredNameInfo::npos) {
506
errorAt(pos.begin, JSMSG_REDECLARED_VAR, DeclarationKindString(prevKind),
507
bytes.get());
508
return;
509
}
510
511
auto notes = MakeUnique<JSErrorNotes>();
512
if (!notes) {
513
ReportOutOfMemory(pc_->sc()->cx_);
514
return;
515
}
516
517
uint32_t line, column;
518
tokenStream.computeLineAndColumn(prevPos, &line, &column);
519
520
const size_t MaxWidth = sizeof("4294967295");
521
char columnNumber[MaxWidth];
522
SprintfLiteral(columnNumber, "%" PRIu32, column);
523
char lineNumber[MaxWidth];
524
SprintfLiteral(lineNumber, "%" PRIu32, line);
525
526
if (!notes->addNoteASCII(pc_->sc()->cx_, getFilename(), 0, line, column,
527
GetErrorMessage, nullptr, JSMSG_REDECLARED_PREV,
528
lineNumber, columnNumber)) {
529
return;
530
}
531
532
errorWithNotesAt(std::move(notes), pos.begin, JSMSG_REDECLARED_VAR,
533
DeclarationKindString(prevKind), bytes.get());
534
}
535
536
// notePositionalFormalParameter is called for both the arguments of a regular
537
// function definition and the arguments specified by the Function
538
// constructor.
539
//
540
// The 'disallowDuplicateParams' bool indicates whether the use of another
541
// feature (destructuring or default arguments) disables duplicate arguments.
542
// (ECMA-262 requires us to support duplicate parameter names, but, for newer
543
// features, we consider the code to have "opted in" to higher standards and
544
// forbid duplicates.)
545
template <class ParseHandler, typename Unit>
546
bool GeneralParser<ParseHandler, Unit>::notePositionalFormalParameter(
547
FunctionNodeType funNode, HandlePropertyName name, uint32_t beginPos,
548
bool disallowDuplicateParams, bool* duplicatedParam) {
549
if (AddDeclaredNamePtr p =
550
pc_->functionScope().lookupDeclaredNameForAdd(name)) {
551
if (disallowDuplicateParams) {
552
error(JSMSG_BAD_DUP_ARGS);
553
return false;
554
}
555
556
// Strict-mode disallows duplicate args. We may not know whether we are
557
// in strict mode or not (since the function body hasn't been parsed).
558
// In such cases, report will queue up the potential error and return
559
// 'true'.
560
if (pc_->sc()->needStrictChecks()) {
561
UniqueChars bytes = AtomToPrintableString(cx_, name);
562
if (!bytes) {
563
return false;
564
}
565
if (!strictModeError(JSMSG_DUPLICATE_FORMAL, bytes.get())) {
566
return false;
567
}
568
}
569
570
*duplicatedParam = true;
571
} else {
572
DeclarationKind kind = DeclarationKind::PositionalFormalParameter;
573
if (!pc_->functionScope().addDeclaredName(pc_, p, name, kind, beginPos)) {
574
return false;
575
}
576
}
577
578
if (!pc_->positionalFormalParameterNames().append(name)) {
579
ReportOutOfMemory(cx_);
580
return false;
581
}
582
583
NameNodeType paramNode = newName(name);
584
if (!paramNode) {
585
return false;
586
}
587
588
handler_.addFunctionFormalParameter(funNode, paramNode);
589
return true;
590
}
591
592
template <class ParseHandler>
593
bool PerHandlerParser<ParseHandler>::noteDestructuredPositionalFormalParameter(
594
FunctionNodeType funNode, Node destruct) {
595
// Append an empty name to the positional formals vector to keep track of
596
// argument slots when making FunctionScope::Data.
597
if (!pc_->positionalFormalParameterNames().append(nullptr)) {
598
ReportOutOfMemory(cx_);
599
return false;
600
}
601
602
handler_.addFunctionFormalParameter(funNode, destruct);
603
return true;
604
}
605
606
template <class ParseHandler, typename Unit>
607
bool GeneralParser<ParseHandler, Unit>::
608
checkLexicalDeclarationDirectlyWithinBlock(ParseContext::Statement& stmt,
609
DeclarationKind kind,
610
TokenPos pos) {
611
MOZ_ASSERT(DeclarationKindIsLexical(kind));
612
613
// It is an early error to declare a lexical binding not directly
614
// within a block.
615
if (!StatementKindIsBraced(stmt.kind()) &&
616
stmt.kind() != StatementKind::ForLoopLexicalHead) {
617
errorAt(pos.begin,
618
stmt.kind() == StatementKind::Label
619
? JSMSG_LEXICAL_DECL_LABEL
620
: JSMSG_LEXICAL_DECL_NOT_IN_BLOCK,
621
DeclarationKindString(kind));
622
return false;
623
}
624
625
return true;
626
}
627
628
template <class ParseHandler, typename Unit>
629
bool GeneralParser<ParseHandler, Unit>::noteDeclaredName(
630
HandlePropertyName name, DeclarationKind kind, TokenPos pos) {
631
// The asm.js validator does all its own symbol-table management so, as an
632
// optimization, avoid doing any work here.
633
if (pc_->useAsmOrInsideUseAsm()) {
634
return true;
635
}
636
637
switch (kind) {
638
case DeclarationKind::Var:
639
case DeclarationKind::BodyLevelFunction: {
640
Maybe<DeclarationKind> redeclaredKind;
641
uint32_t prevPos;
642
if (!pc_->tryDeclareVar(name, kind, pos.begin, &redeclaredKind,
643
&prevPos)) {
644
return false;
645
}
646
647
if (redeclaredKind) {
648
reportRedeclaration(name, *redeclaredKind, pos, prevPos);
649
return false;
650
}
651
652
break;
653
}
654
655
case DeclarationKind::ModuleBodyLevelFunction: {
656
MOZ_ASSERT(pc_->atModuleLevel());
657
658
AddDeclaredNamePtr p = pc_->varScope().lookupDeclaredNameForAdd(name);
659
if (p) {
660
reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
661
return false;
662
}
663
664
if (!pc_->varScope().addDeclaredName(pc_, p, name, kind, pos.begin)) {
665
return false;
666
}
667
668
// Body-level functions in modules are always closed over.
669
pc_->varScope().lookupDeclaredName(name)->value()->setClosedOver();
670
671
break;
672
}
673
674
case DeclarationKind::FormalParameter: {
675
// It is an early error if any non-positional formal parameter name
676
// (e.g., destructuring formal parameter) is duplicated.
677
678
AddDeclaredNamePtr p =
679
pc_->functionScope().lookupDeclaredNameForAdd(name);
680
if (p) {
681
error(JSMSG_BAD_DUP_ARGS);
682
return false;
683
}
684
685
if (!pc_->functionScope().addDeclaredName(pc_, p, name, kind,
686
pos.begin)) {
687
return false;
688
}
689
690
break;
691
}
692
693
case DeclarationKind::LexicalFunction: {
694
ParseContext::Scope* scope = pc_->innermostScope();
695
AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name);
696
if (p) {
697
reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
698
return false;
699
}
700
701
if (!scope->addDeclaredName(pc_, p, name, kind, pos.begin)) {
702
return false;
703
}
704
705
break;
706
}
707
708
case DeclarationKind::SloppyLexicalFunction: {
709
// Functions in block have complex allowances in sloppy mode for being
710
// labelled that other lexical declarations do not have. Those checks
711
// are more complex than calling checkLexicalDeclarationDirectlyWithin-
712
// Block and are done in checkFunctionDefinition.
713
714
ParseContext::Scope* scope = pc_->innermostScope();
715
if (AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name)) {
716
// It is usually an early error if there is another declaration
717
// with the same name in the same scope.
718
//
719
// Sloppy lexical functions may redeclare other sloppy lexical
720
// functions for web compatibility reasons.
721
if (p->value()->kind() != DeclarationKind::SloppyLexicalFunction) {
722
reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
723
return false;
724
}
725
} else {
726
if (!scope->addDeclaredName(pc_, p, name, kind, pos.begin)) {
727
return false;
728
}
729
}
730
731
break;
732
}
733
734
case DeclarationKind::Let:
735
case DeclarationKind::Const:
736
case DeclarationKind::Class:
737
// The BoundNames of LexicalDeclaration and ForDeclaration must not
738
// contain 'let'. (CatchParameter is the only lexical binding form
739
// without this restriction.)
740
if (name == cx_->names().let) {
741
errorAt(pos.begin, JSMSG_LEXICAL_DECL_DEFINES_LET);
742
return false;
743
}
744
745
MOZ_FALLTHROUGH;
746
747
case DeclarationKind::Import:
748
// Module code is always strict, so 'let' is always a keyword and never a
749
// name.
750
MOZ_ASSERT(name != cx_->names().let);
751
MOZ_FALLTHROUGH;
752
753
case DeclarationKind::SimpleCatchParameter:
754
case DeclarationKind::CatchParameter: {
755
if (ParseContext::Statement* stmt = pc_->innermostStatement()) {
756
if (!checkLexicalDeclarationDirectlyWithinBlock(*stmt, kind, pos)) {
757
return false;
758
}
759
}
760
761
ParseContext::Scope* scope = pc_->innermostScope();
762
763
// For body-level lexically declared names in a function, it is an
764
// early error if there is a formal parameter of the same name. This
765
// needs a special check if there is an extra var scope due to
766
// parameter expressions.
767
if (pc_->isFunctionExtraBodyVarScopeInnermost()) {
768
DeclaredNamePtr p = pc_->functionScope().lookupDeclaredName(name);
769
if (p && DeclarationKindIsParameter(p->value()->kind())) {
770
reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
771
return false;
772
}
773
}
774
775
// It is an early error if there is another declaration with the same
776
// name in the same scope.
777
AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name);
778
if (p) {
779
reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
780
return false;
781
}
782
783
if (!scope->addDeclaredName(pc_, p, name, kind, pos.begin)) {
784
return false;
785
}
786
787
break;
788
}
789
790
case DeclarationKind::CoverArrowParameter:
791
// CoverArrowParameter is only used as a placeholder declaration kind.
792
break;
793
794
case DeclarationKind::PositionalFormalParameter:
795
MOZ_CRASH(
796
"Positional formal parameter names should use "
797
"notePositionalFormalParameter");
798
break;
799
800
case DeclarationKind::VarForAnnexBLexicalFunction:
801
MOZ_CRASH(
802
"Synthesized Annex B vars should go through "
803
"tryDeclareVarForAnnexBLexicalFunction");
804
break;
805
}
806
807
return true;
808
}
809
810
bool ParserBase::noteUsedNameInternal(HandlePropertyName name) {
811
// The asm.js validator does all its own symbol-table management so, as an
812
// optimization, avoid doing any work here.
813
if (pc_->useAsmOrInsideUseAsm()) {
814
return true;
815
}
816
817
// Global bindings are properties and not actual bindings; we don't need
818
// to know if they are closed over. So no need to track used name at the
819
// global scope. It is not incorrect to track them, this is an
820
// optimization.
821
ParseContext::Scope* scope = pc_->innermostScope();
822
if (pc_->sc()->isGlobalContext() && scope == &pc_->varScope()) {
823
return true;
824
}
825
826
return usedNames_.noteUse(cx_, name, pc_->scriptId(), scope->id());
827
}
828
829
template <class ParseHandler>
830
bool PerHandlerParser<ParseHandler>::
831
propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope) {
832
// Now that we have all the declared names in the scope, check which
833
// functions should exhibit Annex B semantics.
834
if (!scope.propagateAndMarkAnnexBFunctionBoxes(pc_)) {
835
return false;
836
}
837
838
if (handler_.canSkipLazyClosedOverBindings()) {
839
// Scopes are nullptr-delimited in the LazyScript closed over bindings
840
// array.
841
while (JSAtom* name = handler_.nextLazyClosedOverBinding()) {
842
scope.lookupDeclaredName(name)->value()->setClosedOver();
843
}
844
return true;
845
}
846
847
bool isSyntaxParser =
848
mozilla::IsSame<ParseHandler, SyntaxParseHandler>::value;
849
uint32_t scriptId = pc_->scriptId();
850
uint32_t scopeId = scope.id();
851
for (BindingIter bi = scope.bindings(pc_); bi; bi++) {
852
if (UsedNamePtr p = usedNames_.lookup(bi.name())) {
853
bool closedOver;
854
p->value().noteBoundInScope(scriptId, scopeId, &closedOver);
855
if (closedOver) {
856
bi.setClosedOver();
857
858
if (isSyntaxParser &&
859
!pc_->closedOverBindingsForLazy().append(bi.name())) {
860
ReportOutOfMemory(cx_);
861
return false;
862
}
863
}
864
}
865
}
866
867
// Append a nullptr to denote end-of-scope.
868
if (isSyntaxParser && !pc_->closedOverBindingsForLazy().append(nullptr)) {
869
ReportOutOfMemory(cx_);
870
return false;
871
}
872
873
return true;
874
}
875
876
template <typename Unit>
877
bool Parser<FullParseHandler, Unit>::checkStatementsEOF() {
878
// This is designed to be paired with parsing a statement list at the top
879
// level.
880
//
881
// The statementList() call breaks on TokenKind::RightCurly, so make sure
882
// we've reached EOF here.
883
TokenKind tt;
884
if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
885
return false;
886
}
887
if (tt != TokenKind::Eof) {
888
error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt));
889
return false;
890
}
891
return true;
892
}
893
894
template <typename Scope>
895
typename Scope::Data* NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc,
896
uint32_t numBindings) {
897
using Data = typename Scope::Data;
898
size_t allocSize = SizeOfData<typename Scope::Data>(numBindings);
899
auto* bindings = alloc.newWithSize<Data>(allocSize, numBindings);
900
if (!bindings) {
901
ReportOutOfMemory(cx);
902
}
903
return bindings;
904
}
905
906
namespace detail {
907
908
template <class Data>
909
static MOZ_ALWAYS_INLINE BindingName* InitializeIndexedBindings(
910
Data* data, BindingName* start, BindingName* cursor) {
911
return cursor;
912
}
913
914
template <class Data, typename UnsignedInteger, typename... Step>
915
static MOZ_ALWAYS_INLINE BindingName* InitializeIndexedBindings(
916
Data* data, BindingName* start, BindingName* cursor,
917
UnsignedInteger Data::*field, const BindingNameVector& bindings,
918
Step&&... step) {
919
data->*field = AssertedCast<UnsignedInteger>(PointerRangeSize(start, cursor));
920
921
BindingName* newCursor =
922
std::uninitialized_copy(bindings.begin(), bindings.end(), cursor);
923
924
return InitializeIndexedBindings(data, start, newCursor,
925
std::forward<Step>(step)...);
926
}
927
928
} // namespace detail
929
930
// Initialize |data->trailingNames| bindings, then set |data->length| to the
931
// count of bindings added (which must equal |count|).
932
//
933
// First, |firstBindings| are added to |data->trailingNames|. Then any "steps"
934
// present are performed first to last. Each step is 1) a pointer to a member
935
// of |data| to be set to the current number of bindings added, and 2) a vector
936
// of |BindingName|s to then copy into |data->trailingNames|. (Thus each
937
// |data| member field indicates where the corresponding vector's names start.)
938
template <class Data, typename... Step>
939
static MOZ_ALWAYS_INLINE void InitializeBindingData(
940
Data* data, uint32_t count, const BindingNameVector& firstBindings,
941
Step&&... step) {
942
MOZ_ASSERT(data->length == 0, "data shouldn't be filled yet");
943
944
BindingName* start = data->trailingNames.start();
945
BindingName* cursor = std::uninitialized_copy(firstBindings.begin(),
946
firstBindings.end(), start);
947
948
#ifdef DEBUG
949
BindingName* end =
950
#endif
951
detail::InitializeIndexedBindings(data, start, cursor,
952
std::forward<Step>(step)...);
953
954
MOZ_ASSERT(PointerRangeSize(start, end) == count);
955
data->length = count;
956
}
957
958
Maybe<GlobalScope::Data*> NewGlobalScopeData(JSContext* cx,
959
ParseContext::Scope& scope,
960
LifoAlloc& alloc,
961
ParseContext* pc) {
962
BindingNameVector vars(cx);
963
BindingNameVector lets(cx);
964
BindingNameVector consts(cx);
965
966
bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
967
for (BindingIter bi = scope.bindings(pc); bi; bi++) {
968
bool closedOver = allBindingsClosedOver || bi.closedOver();
969
970
switch (bi.kind()) {
971
case BindingKind::Var: {
972
bool isTopLevelFunction =
973
bi.declarationKind() == DeclarationKind::BodyLevelFunction;
974
BindingName binding(bi.name(), closedOver, isTopLevelFunction);
975
if (!vars.append(binding)) {
976
return Nothing();
977
}
978
break;
979
}
980
case BindingKind::Let: {
981
BindingName binding(bi.name(), closedOver);
982
if (!lets.append(binding)) {
983
return Nothing();
984
}
985
break;
986
}
987
case BindingKind::Const: {
988
BindingName binding(bi.name(), closedOver);
989
if (!consts.append(binding)) {
990
return Nothing();
991
}
992
break;
993
}
994
default:
995
MOZ_CRASH("Bad global scope BindingKind");
996
}
997
}
998
999
GlobalScope::Data* bindings = nullptr;
1000
uint32_t numBindings = vars.length() + lets.length() + consts.length();
1001
1002
if (numBindings > 0) {
1003
bindings = NewEmptyBindingData<GlobalScope>(cx, alloc, numBindings);
1004
if (!bindings) {
1005
return Nothing();
1006
}
1007
1008
// The ordering here is important. See comments in GlobalScope.
1009
InitializeBindingData(bindings, numBindings, vars,
1010
&GlobalScope::Data::letStart, lets,
1011
&GlobalScope::Data::constStart, consts);
1012
}
1013
1014
return Some(bindings);
1015
}
1016
1017
Maybe<GlobalScope::Data*> ParserBase::newGlobalScopeData(
1018
ParseContext::Scope& scope) {
1019
return NewGlobalScopeData(cx_, scope, alloc_, pc_);
1020
}
1021
1022
Maybe<ModuleScope::Data*> NewModuleScopeData(JSContext* cx,
1023
ParseContext::Scope& scope,
1024
LifoAlloc& alloc,
1025
ParseContext* pc) {
1026
BindingNameVector imports(cx);
1027
BindingNameVector vars(cx);
1028
BindingNameVector lets(cx);
1029
BindingNameVector consts(cx);
1030
1031
bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
1032
for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1033
// Imports are indirect bindings and must not be given known slots.
1034
BindingName binding(bi.name(), (allBindingsClosedOver || bi.closedOver()) &&
1035
bi.kind() != BindingKind::Import);
1036
switch (bi.kind()) {
1037
case BindingKind::Import:
1038
if (!imports.append(binding)) {
1039
return Nothing();
1040
}
1041
break;
1042
case BindingKind::Var:
1043
if (!vars.append(binding)) {
1044
return Nothing();
1045
}
1046
break;
1047
case BindingKind::Let:
1048
if (!lets.append(binding)) {
1049
return Nothing();
1050
}
1051
break;
1052
case BindingKind::Const:
1053
if (!consts.append(binding)) {
1054
return Nothing();
1055
}
1056
break;
1057
default:
1058
MOZ_CRASH("Bad module scope BindingKind");
1059
}
1060
}
1061
1062
ModuleScope::Data* bindings = nullptr;
1063
uint32_t numBindings =
1064
imports.length() + vars.length() + lets.length() + consts.length();
1065
1066
if (numBindings > 0) {
1067
bindings = NewEmptyBindingData<ModuleScope>(cx, alloc, numBindings);
1068
if (!bindings) {
1069
return Nothing();
1070
}
1071
1072
// The ordering here is important. See comments in ModuleScope.
1073
InitializeBindingData(bindings, numBindings, imports,
1074
&ModuleScope::Data::varStart, vars,
1075
&ModuleScope::Data::letStart, lets,
1076
&ModuleScope::Data::constStart, consts);
1077
}
1078
1079
return Some(bindings);
1080
}
1081
1082
Maybe<ModuleScope::Data*> ParserBase::newModuleScopeData(
1083
ParseContext::Scope& scope) {
1084
return NewModuleScopeData(cx_, scope, alloc_, pc_);
1085
}
1086
1087
Maybe<EvalScope::Data*> NewEvalScopeData(JSContext* cx,
1088
ParseContext::Scope& scope,
1089
LifoAlloc& alloc, ParseContext* pc) {
1090
BindingNameVector vars(cx);
1091
1092
for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1093
// Eval scopes only contain 'var' bindings. Make all bindings aliased
1094
// for now.
1095
MOZ_ASSERT(bi.kind() == BindingKind::Var);
1096
bool isTopLevelFunction =
1097
bi.declarationKind() == DeclarationKind::BodyLevelFunction;
1098
BindingName binding(bi.name(), true, isTopLevelFunction);
1099
if (!vars.append(binding)) {
1100
return Nothing();
1101
}
1102
}
1103
1104
EvalScope::Data* bindings = nullptr;
1105
uint32_t numBindings = vars.length();
1106
1107
if (numBindings > 0) {
1108
bindings = NewEmptyBindingData<EvalScope>(cx, alloc, numBindings);
1109
if (!bindings) {
1110
return Nothing();
1111
}
1112
1113
InitializeBindingData(bindings, numBindings, vars);
1114
}
1115
1116
return Some(bindings);
1117
}
1118
1119
Maybe<EvalScope::Data*> ParserBase::newEvalScopeData(
1120
ParseContext::Scope& scope) {
1121
return NewEvalScopeData(cx_, scope, alloc_, pc_);
1122
}
1123
1124
Maybe<FunctionScope::Data*> NewFunctionScopeData(
1125
JSContext* cx, ParseContext::Scope& scope, bool hasParameterExprs,
1126
IsFieldInitializer isFieldInitializer, LifoAlloc& alloc, ParseContext* pc) {
1127
BindingNameVector positionalFormals(cx);
1128
BindingNameVector formals(cx);
1129
BindingNameVector vars(cx);
1130
1131
bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
1132
bool hasDuplicateParams = pc->functionBox()->hasDuplicateParameters;
1133
1134
// Positional parameter names must be added in order of appearance as they are
1135
// referenced using argument slots.
1136
for (size_t i = 0; i < pc->positionalFormalParameterNames().length(); i++) {
1137
JSAtom* name = pc->positionalFormalParameterNames()[i];
1138
1139
BindingName bindName;
1140
if (name) {
1141
DeclaredNamePtr p = scope.lookupDeclaredName(name);
1142
1143
// Do not consider any positional formal parameters closed over if
1144
// there are parameter defaults. It is the binding in the defaults
1145
// scope that is closed over instead.
1146
bool closedOver =
1147
allBindingsClosedOver || (p && p->value()->closedOver());
1148
1149
// If the parameter name has duplicates, only the final parameter
1150
// name should be on the environment, as otherwise the environment
1151
// object would have multiple, same-named properties.
1152
if (hasDuplicateParams) {
1153
for (size_t j = pc->positionalFormalParameterNames().length() - 1;
1154
j > i; j--) {
1155
if (pc->positionalFormalParameterNames()[j] == name) {
1156
closedOver = false;
1157
break;
1158
}
1159
}
1160
}
1161
1162
bindName = BindingName(name, closedOver);
1163
}
1164
1165
if (!positionalFormals.append(bindName)) {
1166
return Nothing();
1167
}
1168
}
1169
1170
for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1171
BindingName binding(bi.name(), allBindingsClosedOver || bi.closedOver());
1172
switch (bi.kind()) {
1173
case BindingKind::FormalParameter:
1174
// Positional parameter names are already handled above.
1175
if (bi.declarationKind() == DeclarationKind::FormalParameter) {
1176
if (!formals.append(binding)) {
1177
return Nothing();
1178
}
1179
}
1180
break;
1181
case BindingKind::Var:
1182
// The only vars in the function scope when there are parameter
1183
// exprs, which induces a separate var environment, should be the
1184
// special bindings.
1185
MOZ_ASSERT_IF(hasParameterExprs,
1186
FunctionScope::isSpecialName(cx, bi.name()));
1187
if (!vars.append(binding)) {
1188
return Nothing();
1189
}
1190
break;
1191
default:
1192
break;
1193
}
1194
}
1195
1196
FunctionScope::Data* bindings = nullptr;
1197
uint32_t numBindings =
1198
positionalFormals.length() + formals.length() + vars.length();
1199
1200
if (numBindings > 0) {
1201
bindings = NewEmptyBindingData<FunctionScope>(cx, alloc, numBindings);
1202
if (!bindings) {
1203
return Nothing();
1204
}
1205
1206
bindings->isFieldInitializer = isFieldInitializer;
1207
1208
// The ordering here is important. See comments in FunctionScope.
1209
InitializeBindingData(bindings, numBindings, positionalFormals,
1210
&FunctionScope::Data::nonPositionalFormalStart,
1211
formals, &FunctionScope::Data::varStart, vars);
1212
}
1213
1214
return Some(bindings);
1215
}
1216
1217
Maybe<FunctionScope::Data*> ParserBase::newFunctionScopeData(
1218
ParseContext::Scope& scope, bool hasParameterExprs,
1219
IsFieldInitializer isFieldInitializer) {
1220
return NewFunctionScopeData(cx_, scope, hasParameterExprs, isFieldInitializer,
1221
alloc_, pc_);
1222
}
1223
1224
Maybe<VarScope::Data*> NewVarScopeData(JSContext* cx,
1225
ParseContext::Scope& scope,
1226
LifoAlloc& alloc, ParseContext* pc) {
1227
BindingNameVector vars(cx);
1228
1229
bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
1230
1231
for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1232
if (bi.kind() == BindingKind::Var) {
1233
BindingName binding(bi.name(), allBindingsClosedOver || bi.closedOver());
1234
if (!vars.append(binding)) {
1235
return Nothing();
1236
}
1237
}
1238
}
1239
1240
VarScope::Data* bindings = nullptr;
1241
uint32_t numBindings = vars.length();
1242
1243
if (numBindings > 0) {
1244
bindings = NewEmptyBindingData<VarScope>(cx, alloc, numBindings);
1245
if (!bindings) {
1246
return Nothing();
1247
}
1248
1249
InitializeBindingData(bindings, numBindings, vars);
1250
}
1251
1252
return Some(bindings);
1253
}
1254
1255
Maybe<VarScope::Data*> ParserBase::newVarScopeData(ParseContext::Scope& scope) {
1256
return NewVarScopeData(cx_, scope, alloc_, pc_);
1257
}
1258
1259
Maybe<LexicalScope::Data*> NewLexicalScopeData(JSContext* cx,
1260
ParseContext::Scope& scope,
1261
LifoAlloc& alloc,
1262
ParseContext* pc) {
1263
BindingNameVector lets(cx);
1264
BindingNameVector consts(cx);
1265
1266
// Unlike other scopes with bindings which are body-level, it is unknown
1267
// if pc->sc()->allBindingsClosedOver() is correct at the time of
1268
// finishing parsing a lexical scope.
1269
//
1270
// Instead, pc->sc()->allBindingsClosedOver() is checked in
1271
// EmitterScope::enterLexical. Also see comment there.
1272
for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1273
BindingName binding(bi.name(), bi.closedOver());
1274
switch (bi.kind()) {
1275
case BindingKind::Let:
1276
if (!lets.append(binding)) {
1277
return Nothing();
1278
}
1279
break;
1280
case BindingKind::Const:
1281
if (!consts.append(binding)) {
1282
return Nothing();
1283
}
1284
break;
1285
default:
1286
break;
1287
}
1288
}
1289
1290
LexicalScope::Data* bindings = nullptr;
1291
uint32_t numBindings = lets.length() + consts.length();
1292
1293
if (numBindings > 0) {
1294
bindings = NewEmptyBindingData<LexicalScope>(cx, alloc, numBindings);
1295
if (!bindings) {
1296
return Nothing();
1297
}
1298
1299
// The ordering here is important. See comments in LexicalScope.
1300
InitializeBindingData(bindings, numBindings, lets,
1301
&LexicalScope::Data::constStart, consts);
1302
}
1303
1304
return Some(bindings);
1305
}
1306
1307
Maybe<LexicalScope::Data*> ParserBase::newLexicalScopeData(
1308
ParseContext::Scope& scope) {
1309
return NewLexicalScopeData(cx_, scope, alloc_, pc_);
1310
}
1311
1312
template <>
1313
SyntaxParseHandler::LexicalScopeNodeType
1314
PerHandlerParser<SyntaxParseHandler>::finishLexicalScope(
1315
ParseContext::Scope& scope, Node body, ScopeKind kind) {
1316
if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) {
1317
return null();
1318
}
1319
1320
return handler_.newLexicalScope(body);
1321
}
1322
1323
template <>
1324
LexicalScopeNode* PerHandlerParser<FullParseHandler>::finishLexicalScope(
1325
ParseContext::Scope& scope, ParseNode* body, ScopeKind kind) {
1326
if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) {
1327
return nullptr;
1328
}
1329
1330
Maybe<LexicalScope::Data*> bindings = newLexicalScopeData(scope);
1331
if (!bindings) {
1332
return nullptr;
1333
}
1334
1335
return handler_.newLexicalScope(*bindings, body, kind);
1336
}
1337
1338
template <typename Unit>
1339
LexicalScopeNode* Parser<FullParseHandler, Unit>::evalBody(
1340
EvalSharedContext* evalsc) {
1341
SourceParseContext evalpc(this, evalsc, /* newDirectives = */ nullptr);
1342
if (!evalpc.init()) {
1343
return nullptr;
1344
}
1345
1346
ParseContext::VarScope varScope(this);
1347
if (!varScope.init(pc_)) {
1348
return nullptr;
1349
}
1350
1351
LexicalScopeNode* body;
1352
{
1353
// All evals have an implicit non-extensible lexical scope.
1354
ParseContext::Scope lexicalScope(this);
1355
if (!lexicalScope.init(pc_)) {
1356
return nullptr;
1357
}
1358
1359
ListNode* list = statementList(YieldIsName);
1360
if (!list) {
1361
return nullptr;
1362
}
1363
1364
if (!checkStatementsEOF()) {
1365
return nullptr;
1366
}
1367
1368
body = finishLexicalScope(lexicalScope, list);
1369
if (!body) {
1370
return nullptr;
1371
}
1372
}
1373
1374
#ifdef DEBUG
1375
if (evalpc.superScopeNeedsHomeObject() &&
1376
evalsc->compilationEnclosingScope()) {
1377
// If superScopeNeedsHomeObject_ is set and we are an entry-point
1378
// ParseContext, then we must be emitting an eval script, and the
1379
// outer function must already be marked as needing a home object
1380
// since it contains an eval.
1381
ScopeIter si(evalsc->compilationEnclosingScope());
1382
for (; si; si++) {
1383
if (si.kind() == ScopeKind::Function) {
1384
JSFunction* fun = si.scope()->as<FunctionScope>().canonicalFunction();
1385
if (fun->isArrow()) {
1386
continue;
1387
}
1388
MOZ_ASSERT(fun->allowSuperProperty());
1389
MOZ_ASSERT(fun->nonLazyScript()->needsHomeObject());
1390
break;
1391
}
1392
}
1393
MOZ_ASSERT(!si.done(),
1394
"Eval must have found an enclosing function box scope that "
1395
"allows super.property");
1396
}
1397
#endif
1398
1399
if (!CheckParseTree(cx_, alloc_, body)) {
1400
return null();
1401
}
1402
1403
ParseNode* node = body;
1404
// Don't constant-fold inside "use asm" code, as this could create a parse
1405
// tree that doesn't type-check as asm.js.
1406
if (!pc_->useAsmOrInsideUseAsm()) {
1407
if (!FoldConstants(cx_, &node, &handler_)) {
1408
return null();
1409
}
1410
}
1411
body = handler_.asLexicalScope(node);
1412
1413
if (!this->setSourceMapInfo()) {
1414
return nullptr;
1415
}
1416
1417
// For eval scripts, since all bindings are automatically considered
1418
// closed over, we don't need to call propagateFreeNamesAndMarkClosed-
1419
// OverBindings. However, Annex B.3.3 functions still need to be marked.
1420
if (!varScope.propagateAndMarkAnnexBFunctionBoxes(pc_)) {
1421
return nullptr;
1422
}
1423
1424
Maybe<EvalScope::Data*> bindings = newEvalScopeData(pc_->varScope());
1425
if (!bindings) {
1426
return nullptr;
1427
}
1428
evalsc->bindings = *bindings;
1429
1430
return body;
1431
}
1432
1433
template <typename Unit>
1434
ListNode* Parser<FullParseHandler, Unit>::globalBody(
1435
GlobalSharedContext* globalsc) {
1436
SourceParseContext globalpc(this, globalsc, /* newDirectives = */ nullptr);
1437
if (!globalpc.init()) {
1438
return nullptr;
1439
}
1440
1441
ParseContext::VarScope varScope(this);
1442
if (!varScope.init(pc_)) {
1443
return nullptr;
1444
}
1445
1446
ListNode* body = statementList(YieldIsName);
1447
if (!body) {
1448
return nullptr;
1449
}
1450
1451
if (!checkStatementsEOF()) {
1452
return nullptr;
1453
}
1454
1455
if (!CheckParseTree(cx_, alloc_, body)) {
1456
return null();
1457
}
1458
1459
ParseNode* node = body;
1460
// Don't constant-fold inside "use asm" code, as this could create a parse
1461
// tree that doesn't type-check as asm.js.
1462
if (!pc_->useAsmOrInsideUseAsm()) {
1463
if (!FoldConstants(cx_, &node, &handler_)) {
1464
return null();
1465
}
1466
}
1467
body = &node->as<ListNode>();
1468
1469
if (!this->setSourceMapInfo()) {
1470
return nullptr;
1471
}
1472
1473
// For global scripts, whether bindings are closed over or not doesn't
1474
// matter, so no need to call propagateFreeNamesAndMarkClosedOver-
1475
// Bindings. However, Annex B.3.3 functions still need to be marked.
1476
if (!varScope.propagateAndMarkAnnexBFunctionBoxes(pc_)) {
1477
return nullptr;
1478
}
1479
1480
Maybe<GlobalScope::Data*> bindings = newGlobalScopeData(pc_->varScope());
1481
if (!bindings) {
1482
return nullptr;
1483
}
1484
globalsc->bindings = *bindings;
1485
1486
return body;
1487
}
1488
1489
template <typename Unit>
1490
ModuleNode* Parser<FullParseHandler, Unit>::moduleBody(
1491
ModuleSharedContext* modulesc) {
1492
MOZ_ASSERT(checkOptionsCalled_);
1493
1494
SourceParseContext modulepc(this, modulesc, nullptr);
1495
if (!modulepc.init()) {
1496
return null();
1497
}
1498
1499
ParseContext::VarScope varScope(this);
1500
if (!varScope.init(pc_)) {
1501
return nullptr;
1502
}
1503
1504
ModuleNodeType moduleNode = handler_.newModule(pos());
1505
if (!moduleNode) {
1506
return null();
1507
}
1508
1509
AutoAwaitIsKeyword<FullParseHandler, Unit> awaitIsKeyword(
1510
this, AwaitIsModuleKeyword);
1511
ListNode* stmtList = statementList(YieldIsName);
1512
if (!stmtList) {
1513
return null();
1514
}
1515
1516
MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList));
1517
moduleNode->setBody(&stmtList->as<ListNode>());
1518
1519
TokenKind tt;
1520
if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
1521
return null();
1522
}
1523
if (tt != TokenKind::Eof) {
1524
error(JSMSG_GARBAGE_AFTER_INPUT, "module", TokenKindToDesc(tt));
1525
return null();
1526
}
1527
1528
if (!modulesc->builder.buildTables()) {
1529
return null();
1530
}
1531
1532
// Check exported local bindings exist and mark them as closed over.
1533
for (auto entry : modulesc->builder.localExportEntries()) {
1534
JSAtom* name = entry->localName();
1535
MOZ_ASSERT(name);
1536
1537
DeclaredNamePtr p = modulepc.varScope().lookupDeclaredName(name);
1538
if (!p) {
1539
UniqueChars str = AtomToPrintableString(cx_, name);
1540
if (!str) {
1541
return null();
1542
}
1543
1544
errorNoOffset(JSMSG_MISSING_EXPORT, str.get());
1545
return null();
1546
}
1547
1548
p->value()->setClosedOver();
1549
}
1550
1551
if (!CheckParseTree(cx_, alloc_, stmtList)) {
1552
return null();
1553
}
1554
1555
ParseNode* node = stmtList;
1556
// Don't constant-fold inside "use asm" code, as this could create a parse
1557
// tree that doesn't type-check as asm.js.
1558
if (!pc_->useAsmOrInsideUseAsm()) {
1559
if (!FoldConstants(cx_, &node, &handler_)) {
1560
return null();
1561
}
1562
}
1563
stmtList = &node->as<ListNode>();
1564
1565
if (!this->setSourceMapInfo()) {
1566
return null();
1567
}
1568
1569
if (!propagateFreeNamesAndMarkClosedOverBindings(modulepc.varScope())) {
1570
return null();
1571
}
1572
1573
Maybe<ModuleScope::Data*> bindings = newModuleScopeData(modulepc.varScope());
1574
if (!bindings) {
1575
return nullptr;
1576
}
1577
1578
modulesc->bindings = *bindings;
1579
return moduleNode;
1580
}
1581
1582
template <typename Unit>
1583
SyntaxParseHandler::ModuleNodeType Parser<SyntaxParseHandler, Unit>::moduleBody(
1584
ModuleSharedContext* modulesc) {
1585
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
1586
return SyntaxParseHandler::NodeFailure;
1587
}
1588
1589
template <class ParseHandler>
1590
typename ParseHandler::NameNodeType
1591
PerHandlerParser<ParseHandler>::newInternalDotName(HandlePropertyName name) {
1592
NameNodeType nameNode = newName(name);
1593
if (!nameNode) {
1594
return null();
1595
}
1596
if (!noteUsedName(name)) {
1597
return null();
1598
}
1599
return nameNode;
1600
}
1601
1602
template <class ParseHandler>
1603
typename ParseHandler::NameNodeType
1604
PerHandlerParser<ParseHandler>::newThisName() {
1605
return newInternalDotName(cx_->names().dotThis);
1606
}
1607
1608
template <class ParseHandler>
1609
typename ParseHandler::NameNodeType
1610
PerHandlerParser<ParseHandler>::newDotGeneratorName() {
1611
return newInternalDotName(cx_->names().dotGenerator);
1612
}
1613
1614
template <class ParseHandler>
1615
bool PerHandlerParser<ParseHandler>::finishFunctionScopes(
1616
bool isStandaloneFunction) {
1617
FunctionBox* funbox = pc_->functionBox();
1618
1619
if (funbox->hasParameterExprs) {
1620
if (!propagateFreeNamesAndMarkClosedOverBindings(pc_->functionScope())) {
1621
return false;
1622
}
1623
}
1624
1625
if (funbox->isNamedLambda() && !isStandaloneFunction) {
1626
if (!propagateFreeNamesAndMarkClosedOverBindings(pc_->namedLambdaScope())) {
1627
return false;
1628
}
1629
}
1630
1631
return true;
1632
}
1633
1634
template <>
1635
bool PerHandlerParser<FullParseHandler>::finishFunction(
1636
bool isStandaloneFunction /* = false */,
1637
IsFieldInitializer isFieldInitializer /* = IsFieldInitializer::No */) {
1638
if (!finishFunctionScopes(isStandaloneFunction)) {
1639
return false;
1640
}
1641
1642
FunctionBox* funbox = pc_->functionBox();
1643
bool hasParameterExprs = funbox->hasParameterExprs;
1644
1645
if (hasParameterExprs) {
1646
Maybe<VarScope::Data*> bindings = newVarScopeData(pc_->varScope());
1647
if (!bindings) {
1648
return false;
1649
}
1650
funbox->extraVarScopeBindings().set(*bindings);
1651
}
1652
1653
{
1654
Maybe<FunctionScope::Data*> bindings = newFunctionScopeData(
1655
pc_->functionScope(), hasParameterExprs, isFieldInitializer);
1656
if (!bindings) {
1657
return false;
1658
}
1659
funbox->functionScopeBindings().set(*bindings);
1660
}
1661
1662
if (funbox->isNamedLambda() && !isStandaloneFunction) {
1663
Maybe<LexicalScope::Data*> bindings =
1664
newLexicalScopeData(pc_->namedLambdaScope());
1665
if (!bindings) {
1666
return false;
1667
}
1668
funbox->namedLambdaBindings().set(*bindings);
1669
}
1670
1671
return true;
1672
}
1673
1674
template <>
1675
bool PerHandlerParser<SyntaxParseHandler>::finishFunction(
1676
bool isStandaloneFunction /* = false */,
1677
IsFieldInitializer isFieldInitializer /* = IsFieldInitializer::Yes */) {
1678
// The LazyScript for a lazily parsed function needs to know its set of
1679
// free variables and inner functions so that when it is fully parsed, we
1680
// can skip over any already syntax parsed inner functions and still
1681
// retain correct scope information.
1682
1683
if (!finishFunctionScopes(isStandaloneFunction)) {
1684
return false;
1685
}
1686
1687
// There are too many bindings or inner functions to be saved into the
1688
// LazyScript. Do a full parse.
1689
if (pc_->closedOverBindingsForLazy().length() >=
1690
LazyScript::NumClosedOverBindingsLimit ||
1691
pc_->innerFunctionsForLazy.length() >=
1692
LazyScript::NumInnerFunctionsLimit) {
1693
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
1694
return false;
1695
}
1696
1697
FunctionBox* funbox = pc_->functionBox();
1698
RootedFunction fun(cx_, funbox->function());
1699
LazyScript* lazy = LazyScript::Create(
1700
cx_, fun, sourceObject_, pc_->closedOverBindingsForLazy(),
1701
pc_->innerFunctionsForLazy, funbox->bufStart, funbox->bufEnd,
1702
funbox->toStringStart, funbox->startLine, funbox->startColumn,
1703
parseGoal());
1704
if (!lazy) {
1705
return false;
1706
}
1707
1708
// Flags that need to be copied into the JSScript when we do the full
1709
// parse.
1710
if (pc_->sc()->strict()) {
1711
lazy->setStrict();
1712
}
1713
lazy->setGeneratorKind(funbox->generatorKind());
1714
lazy->setAsyncKind(funbox->asyncKind());
1715
if (funbox->hasRest()) {
1716
lazy->setHasRest();
1717
}
1718
if (funbox->isLikelyConstructorWrapper()) {
1719
lazy->setLikelyConstructorWrapper();
1720
}
1721
if (funbox->isDerivedClassConstructor()) {
1722
lazy->setIsDerivedClassConstructor();
1723
}
1724
if (funbox->needsHomeObject()) {
1725
lazy->setNeedsHomeObject();
1726
}
1727
if (funbox->declaredArguments) {
1728
lazy->setShouldDeclareArguments();
1729
}
1730
if (funbox->hasThisBinding()) {
1731
lazy->setHasThisBinding();
1732
}
1733
1734
// Flags that need to copied back into the parser when we do the full
1735
// parse.
1736
PropagateTransitiveParseFlags(funbox, lazy);
1737
1738
fun->initLazyScript(lazy);
1739
return true;
1740
}
1741
1742
static YieldHandling GetYieldHandling(GeneratorKind generatorKind) {
1743
if (generatorKind == GeneratorKind::NotGenerator) {
1744
return YieldIsName;
1745
}
1746
return YieldIsKeyword;
1747
}
1748
1749
static AwaitHandling GetAwaitHandling(FunctionAsyncKind asyncKind) {
1750
if (asyncKind == FunctionAsyncKind::SyncFunction) {
1751
return AwaitIsName;
1752
}
1753
return AwaitIsKeyword;
1754
}
1755
1756
template <typename Unit>
1757
FunctionNode* Parser<FullParseHandler, Unit>::standaloneFunction(
1758
HandleFunction fun, HandleScope enclosingScope,
1759
const Maybe<uint32_t>& parameterListEnd, GeneratorKind generatorKind,
1760
FunctionAsyncKind asyncKind, Directives inheritedDirectives,
1761
Directives* newDirectives) {
1762
MOZ_ASSERT(checkOptionsCalled_);
1763
1764
// Skip prelude.
1765
TokenKind tt;
1766
if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
1767
return null();
1768
}
1769
if (asyncKind == FunctionAsyncKind::AsyncFunction) {
1770
MOZ_ASSERT(tt == TokenKind::Async);
1771
if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
1772
return null();
1773
}
1774
}
1775
MOZ_ASSERT(tt == TokenKind::Function);
1776
1777
if (!tokenStream.getToken(&tt)) {
1778
return null();
1779
}
1780
if (generatorKind == GeneratorKind::Generator) {
1781
MOZ_ASSERT(tt == TokenKind::Mul);
1782
if (!tokenStream.getToken(&tt)) {
1783
return null();
1784
}
1785
}
1786
1787
// Skip function name, if present.
1788
if (TokenKindIsPossibleIdentifierName(tt)) {
1789
MOZ_ASSERT(anyChars.currentName() == fun->explicitName());
1790
} else {
1791
MOZ_ASSERT(fun->explicitName() == nullptr);
1792
anyChars.ungetToken();
1793
}
1794
1795
FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::Statement;
1796
FunctionNodeType funNode = handler_.newFunction(syntaxKind, pos());
1797
if (!funNode) {
1798
return null();
1799
}