Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /*
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/Range.h"
23 : #include "mozilla/Sprintf.h"
24 :
25 : #include "jsapi.h"
26 : #include "jsatom.h"
27 : #include "jscntxt.h"
28 : #include "jsfun.h"
29 : #include "jsopcode.h"
30 : #include "jsscript.h"
31 : #include "jstypes.h"
32 :
33 : #include "builtin/ModuleObject.h"
34 : #include "builtin/SelfHostingDefines.h"
35 : #include "frontend/BytecodeCompiler.h"
36 : #include "frontend/FoldConstants.h"
37 : #include "frontend/TokenStream.h"
38 : #include "irregexp/RegExpParser.h"
39 : #include "vm/RegExpObject.h"
40 : #include "wasm/AsmJS.h"
41 :
42 : #include "jsatominlines.h"
43 : #include "jsscriptinlines.h"
44 :
45 : #include "frontend/ParseNode-inl.h"
46 : #include "vm/EnvironmentObject-inl.h"
47 :
48 : using namespace js;
49 : using namespace js::gc;
50 :
51 : using mozilla::Maybe;
52 : using mozilla::Move;
53 : using mozilla::Nothing;
54 : using mozilla::PodCopy;
55 : using mozilla::PodZero;
56 : using mozilla::Some;
57 :
58 : using JS::AutoGCRooter;
59 :
60 : namespace js {
61 : namespace frontend {
62 :
63 : using DeclaredNamePtr = ParseContext::Scope::DeclaredNamePtr;
64 : using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr;
65 : using BindingIter = ParseContext::Scope::BindingIter;
66 : using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
67 :
68 : // Read a token. Report an error and return null() if that token doesn't match
69 : // to the condition. Do not use MUST_MATCH_TOKEN_INTERNAL directly.
70 : #define MUST_MATCH_TOKEN_INTERNAL(cond, modifier, errorReport) \
71 : JS_BEGIN_MACRO \
72 : TokenKind token; \
73 : if (!tokenStream.getToken(&token, modifier)) \
74 : return null(); \
75 : if (!(cond)) { \
76 : errorReport; \
77 : return null(); \
78 : } \
79 : JS_END_MACRO
80 :
81 : #define MUST_MATCH_TOKEN_MOD(tt, modifier, errorNumber) \
82 : MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, error(errorNumber))
83 :
84 : #define MUST_MATCH_TOKEN(tt, errorNumber) \
85 : MUST_MATCH_TOKEN_MOD(tt, TokenStream::None, errorNumber)
86 :
87 : #define MUST_MATCH_TOKEN_FUNC_MOD(func, modifier, errorNumber) \
88 : MUST_MATCH_TOKEN_INTERNAL((func)(token), modifier, error(errorNumber))
89 :
90 : #define MUST_MATCH_TOKEN_FUNC(func, errorNumber) \
91 : MUST_MATCH_TOKEN_FUNC_MOD(func, TokenStream::None, errorNumber)
92 :
93 : #define MUST_MATCH_TOKEN_MOD_WITH_REPORT(tt, modifier, errorReport) \
94 : MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, errorReport)
95 :
96 : template <class T, class U>
97 : static inline void
98 8234 : PropagateTransitiveParseFlags(const T* inner, U* outer)
99 : {
100 8234 : if (inner->bindingsAccessedDynamically())
101 0 : outer->setBindingsAccessedDynamically();
102 8234 : if (inner->hasDebuggerStatement())
103 0 : outer->setHasDebuggerStatement();
104 8234 : if (inner->hasDirectEval())
105 0 : outer->setHasDirectEval();
106 8234 : }
107 :
108 : static const char*
109 0 : DeclarationKindString(DeclarationKind kind)
110 : {
111 0 : switch (kind) {
112 : case DeclarationKind::PositionalFormalParameter:
113 : case DeclarationKind::FormalParameter:
114 0 : return "formal parameter";
115 : case DeclarationKind::CoverArrowParameter:
116 0 : return "cover arrow parameter";
117 : case DeclarationKind::Var:
118 0 : return "var";
119 : case DeclarationKind::Let:
120 0 : return "let";
121 : case DeclarationKind::Const:
122 0 : return "const";
123 : case DeclarationKind::Import:
124 0 : return "import";
125 : case DeclarationKind::BodyLevelFunction:
126 : case DeclarationKind::ModuleBodyLevelFunction:
127 : case DeclarationKind::LexicalFunction:
128 : case DeclarationKind::SloppyLexicalFunction:
129 0 : return "function";
130 : case DeclarationKind::VarForAnnexBLexicalFunction:
131 0 : return "annex b var";
132 : case DeclarationKind::ForOfVar:
133 0 : return "var in for-of";
134 : case DeclarationKind::SimpleCatchParameter:
135 : case DeclarationKind::CatchParameter:
136 0 : return "catch parameter";
137 : }
138 :
139 0 : MOZ_CRASH("Bad DeclarationKind");
140 : }
141 :
142 : static bool
143 3001 : StatementKindIsBraced(StatementKind kind)
144 : {
145 1700 : return kind == StatementKind::Block ||
146 1647 : kind == StatementKind::Switch ||
147 1392 : kind == StatementKind::Try ||
148 737 : kind == StatementKind::Catch ||
149 3738 : kind == StatementKind::Finally ||
150 3001 : kind == StatementKind::Class;
151 : }
152 :
153 : void
154 0 : ParseContext::Scope::dump(ParseContext* pc)
155 : {
156 0 : JSContext* cx = pc->sc()->context;
157 :
158 0 : fprintf(stdout, "ParseScope %p", this);
159 :
160 0 : fprintf(stdout, "\n decls:\n");
161 0 : for (DeclaredNameMap::Range r = declared_->all(); !r.empty(); r.popFront()) {
162 0 : JSAutoByteString bytes;
163 0 : if (!AtomToPrintableString(cx, r.front().key(), &bytes))
164 0 : return;
165 0 : DeclaredNameInfo& info = r.front().value().wrapped;
166 0 : fprintf(stdout, " %s %s%s\n",
167 : DeclarationKindString(info.kind()),
168 : bytes.ptr(),
169 0 : info.closedOver() ? " (closed over)" : "");
170 : }
171 :
172 0 : fprintf(stdout, "\n");
173 : }
174 :
175 : bool
176 0 : ParseContext::Scope::addPossibleAnnexBFunctionBox(ParseContext* pc, FunctionBox* funbox)
177 : {
178 0 : if (!possibleAnnexBFunctionBoxes_) {
179 0 : if (!possibleAnnexBFunctionBoxes_.acquire(pc->sc()->context))
180 0 : return false;
181 : }
182 :
183 0 : return possibleAnnexBFunctionBoxes_->append(funbox);
184 : }
185 :
186 : bool
187 18830 : ParseContext::Scope::propagateAndMarkAnnexBFunctionBoxes(ParseContext* pc)
188 : {
189 : // Strict mode doesn't have wack Annex B function semantics.
190 41678 : if (pc->sc()->strict() ||
191 18830 : !possibleAnnexBFunctionBoxes_ ||
192 0 : possibleAnnexBFunctionBoxes_->empty())
193 : {
194 18830 : return true;
195 : }
196 :
197 0 : if (this == &pc->varScope()) {
198 : // Base case: actually declare the Annex B vars and mark applicable
199 : // function boxes as Annex B.
200 0 : RootedPropertyName name(pc->sc()->context);
201 0 : Maybe<DeclarationKind> redeclaredKind;
202 : uint32_t unused;
203 0 : for (FunctionBox* funbox : *possibleAnnexBFunctionBoxes_) {
204 0 : if (pc->annexBAppliesToLexicalFunctionInInnermostScope(funbox)) {
205 0 : name = funbox->function()->explicitName()->asPropertyName();
206 0 : if (!pc->tryDeclareVar(name,
207 : DeclarationKind::VarForAnnexBLexicalFunction,
208 : DeclaredNameInfo::npos, &redeclaredKind, &unused))
209 : {
210 0 : return false;
211 : }
212 :
213 0 : MOZ_ASSERT(!redeclaredKind);
214 0 : funbox->isAnnexB = true;
215 : }
216 : }
217 : } else {
218 : // Inner scope case: propagate still applicable function boxes to the
219 : // enclosing scope.
220 0 : for (FunctionBox* funbox : *possibleAnnexBFunctionBoxes_) {
221 0 : if (pc->annexBAppliesToLexicalFunctionInInnermostScope(funbox)) {
222 0 : if (!enclosing()->addPossibleAnnexBFunctionBox(pc, funbox))
223 0 : return false;
224 : }
225 : }
226 : }
227 :
228 0 : return true;
229 : }
230 :
231 : static bool
232 1315 : DeclarationKindIsCatchParameter(DeclarationKind kind)
233 : {
234 1315 : return kind == DeclarationKind::SimpleCatchParameter ||
235 1315 : kind == DeclarationKind::CatchParameter;
236 : }
237 :
238 : bool
239 655 : ParseContext::Scope::addCatchParameters(ParseContext* pc, Scope& catchParamScope)
240 : {
241 655 : if (pc->useAsmOrInsideUseAsm())
242 0 : return true;
243 :
244 1310 : for (DeclaredNameMap::Range r = catchParamScope.declared_->all(); !r.empty(); r.popFront()) {
245 655 : DeclarationKind kind = r.front().value()->kind();
246 655 : uint32_t pos = r.front().value()->pos();
247 655 : MOZ_ASSERT(DeclarationKindIsCatchParameter(kind));
248 655 : JSAtom* name = r.front().key();
249 655 : AddDeclaredNamePtr p = lookupDeclaredNameForAdd(name);
250 655 : MOZ_ASSERT(!p);
251 655 : if (!addDeclaredName(pc, p, name, kind, pos))
252 0 : return false;
253 : }
254 :
255 655 : return true;
256 : }
257 :
258 : void
259 655 : ParseContext::Scope::removeCatchParameters(ParseContext* pc, Scope& catchParamScope)
260 : {
261 655 : if (pc->useAsmOrInsideUseAsm())
262 0 : return;
263 :
264 1315 : for (DeclaredNameMap::Range r = catchParamScope.declared_->all(); !r.empty(); r.popFront()) {
265 660 : DeclaredNamePtr p = declared_->lookup(r.front().key());
266 660 : MOZ_ASSERT(p);
267 :
268 : // This check is needed because the catch body could have declared
269 : // vars, which would have been added to catchParamScope.
270 660 : if (DeclarationKindIsCatchParameter(r.front().value()->kind()))
271 655 : declared_->remove(p);
272 : }
273 : }
274 :
275 : void
276 281 : SharedContext::computeAllowSyntax(Scope* scope)
277 : {
278 590 : for (ScopeIter si(scope); si; si++) {
279 540 : if (si.kind() == ScopeKind::Function) {
280 262 : JSFunction* fun = si.scope()->as<FunctionScope>().canonicalFunction();
281 262 : if (fun->isArrow())
282 31 : continue;
283 231 : allowNewTarget_ = true;
284 231 : allowSuperProperty_ = fun->allowSuperProperty();
285 231 : allowSuperCall_ = fun->isDerivedClassConstructor();
286 462 : return;
287 : }
288 : }
289 : }
290 :
291 : void
292 281 : SharedContext::computeThisBinding(Scope* scope)
293 : {
294 590 : for (ScopeIter si(scope); si; si++) {
295 540 : if (si.kind() == ScopeKind::Module) {
296 0 : thisBinding_ = ThisBinding::Module;
297 231 : return;
298 : }
299 :
300 540 : if (si.kind() == ScopeKind::Function) {
301 262 : JSFunction* fun = si.scope()->as<FunctionScope>().canonicalFunction();
302 :
303 : // Arrow functions and generator expression lambdas don't have
304 : // their own `this` binding.
305 262 : if (fun->isArrow() || fun->nonLazyScript()->isGeneratorExp())
306 31 : continue;
307 :
308 : // Derived class constructors (including nested arrow functions and
309 : // eval) need TDZ checks when accessing |this|.
310 231 : if (fun->isDerivedClassConstructor())
311 0 : needsThisTDZChecks_ = true;
312 :
313 231 : thisBinding_ = ThisBinding::Function;
314 231 : return;
315 : }
316 : }
317 :
318 50 : thisBinding_ = ThisBinding::Global;
319 : }
320 :
321 : void
322 1409 : SharedContext::computeInWith(Scope* scope)
323 : {
324 3741 : for (ScopeIter si(scope); si; si++) {
325 2332 : if (si.kind() == ScopeKind::With) {
326 0 : inWith_ = true;
327 0 : break;
328 : }
329 : }
330 1409 : }
331 :
332 2 : EvalSharedContext::EvalSharedContext(JSContext* cx, JSObject* enclosingEnv,
333 : Scope* enclosingScope, Directives directives,
334 2 : bool extraWarnings)
335 : : SharedContext(cx, Kind::Eval, directives, extraWarnings),
336 : enclosingScope_(cx, enclosingScope),
337 2 : bindings(cx)
338 : {
339 2 : computeAllowSyntax(enclosingScope);
340 2 : computeInWith(enclosingScope);
341 2 : computeThisBinding(enclosingScope);
342 :
343 : // Like all things Debugger, Debugger.Frame.eval needs special
344 : // handling. Since the environment chain of such evals are non-syntactic
345 : // (DebuggerEnvironmentProxy is not an EnvironmentObject), computing the
346 : // this binding with respect to enclosingScope is incorrect if the
347 : // Debugger.Frame is a function frame. Recompute the this binding if we
348 : // are such an eval.
349 2 : if (enclosingEnv && enclosingScope->hasOnChain(ScopeKind::NonSyntactic)) {
350 : // For Debugger.Frame.eval with bindings, the environment chain may
351 : // have more than the DebugEnvironmentProxy.
352 0 : JSObject* env = enclosingEnv;
353 0 : while (env) {
354 0 : if (env->is<DebugEnvironmentProxy>())
355 0 : env = &env->as<DebugEnvironmentProxy>().environment();
356 :
357 0 : if (env->is<CallObject>()) {
358 0 : computeThisBinding(env->as<CallObject>().callee().nonLazyScript()->bodyScope());
359 0 : break;
360 : }
361 :
362 0 : env = env->enclosingEnvironment();
363 : }
364 : }
365 2 : }
366 :
367 : bool
368 7641 : ParseContext::init()
369 : {
370 7641 : if (scriptId_ == UINT32_MAX) {
371 0 : tokenStream_.reportErrorNoOffset(JSMSG_NEED_DIET, js_script_str);
372 0 : return false;
373 : }
374 :
375 7641 : JSContext* cx = sc()->context;
376 :
377 7641 : if (isFunctionBox()) {
378 : // Named lambdas always need a binding for their own name. If this
379 : // binding is closed over when we finish parsing the function in
380 : // finishExtraFunctionScopes, the function box needs to be marked as
381 : // needing a dynamic DeclEnv object.
382 14746 : RootedFunction fun(cx, functionBox()->function());
383 7373 : if (fun->isNamedLambda()) {
384 714 : if (!namedLambdaScope_->init(this))
385 0 : return false;
386 : AddDeclaredNamePtr p =
387 714 : namedLambdaScope_->lookupDeclaredNameForAdd(fun->explicitName());
388 714 : MOZ_ASSERT(!p);
389 714 : if (!namedLambdaScope_->addDeclaredName(this, p, fun->explicitName(),
390 : DeclarationKind::Const,
391 : DeclaredNameInfo::npos))
392 : {
393 0 : return false;
394 : }
395 : }
396 :
397 7373 : if (!functionScope_->init(this))
398 0 : return false;
399 :
400 7373 : if (!positionalFormalParameterNames_.acquire(cx))
401 0 : return false;
402 : }
403 :
404 7641 : if (!closedOverBindingsForLazy_.acquire(cx))
405 0 : return false;
406 :
407 7641 : return true;
408 : }
409 :
410 : bool
411 77354 : UsedNameTracker::noteUse(JSContext* cx, JSAtom* name, uint32_t scriptId, uint32_t scopeId)
412 : {
413 77354 : if (UsedNameMap::AddPtr p = map_.lookupForAdd(name)) {
414 65720 : if (!p->value().noteUsedInScope(scriptId, scopeId))
415 0 : return false;
416 : } else {
417 23268 : UsedNameInfo info(cx);
418 11634 : if (!info.noteUsedInScope(scriptId, scopeId))
419 0 : return false;
420 11634 : if (!map_.add(p, name, Move(info)))
421 0 : return false;
422 : }
423 :
424 77354 : return true;
425 : }
426 :
427 : void
428 0 : UsedNameTracker::UsedNameInfo::resetToScope(uint32_t scriptId, uint32_t scopeId)
429 : {
430 0 : while (!uses_.empty()) {
431 0 : Use& innermost = uses_.back();
432 0 : if (innermost.scopeId < scopeId)
433 0 : break;
434 0 : MOZ_ASSERT(innermost.scriptId >= scriptId);
435 0 : uses_.popBack();
436 : }
437 0 : }
438 :
439 : void
440 0 : UsedNameTracker::rewind(RewindToken token)
441 : {
442 0 : scriptCounter_ = token.scriptId;
443 0 : scopeCounter_ = token.scopeId;
444 :
445 0 : for (UsedNameMap::Range r = map_.all(); !r.empty(); r.popFront())
446 0 : r.front().value().resetToScope(token.scriptId, token.scopeId);
447 0 : }
448 :
449 7633 : FunctionBox::FunctionBox(JSContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead,
450 : JSFunction* fun, uint32_t toStringStart,
451 : Directives directives, bool extraWarnings,
452 7633 : GeneratorKind generatorKind, FunctionAsyncKind asyncKind)
453 : : ObjectBox(fun, traceListHead),
454 : SharedContext(cx, Kind::FunctionBox, directives, extraWarnings),
455 : enclosingScope_(nullptr),
456 : namedLambdaBindings_(nullptr),
457 : functionScopeBindings_(nullptr),
458 : extraVarScopeBindings_(nullptr),
459 : functionNode(nullptr),
460 : bufStart(0),
461 : bufEnd(0),
462 : startLine(1),
463 : startColumn(0),
464 : toStringStart(toStringStart),
465 : toStringEnd(0),
466 : length(0),
467 7633 : generatorKindBits_(GeneratorKindAsBits(generatorKind)),
468 7633 : asyncKindBits_(AsyncKindAsBits(asyncKind)),
469 : isGenexpLambda(false),
470 : hasDestructuringArgs(false),
471 : hasParameterExprs(false),
472 : hasDirectEvalInParameterExpr(false),
473 : hasDuplicateParameters(false),
474 : useAsm(false),
475 : insideUseAsm(false),
476 : isAnnexB(false),
477 : wasEmitted(false),
478 : declaredArguments(false),
479 : usesArguments(false),
480 : usesApply(false),
481 : usesThis(false),
482 : usesReturn(false),
483 : hasRest_(false),
484 : isExprBody_(false),
485 22899 : funCxFlags()
486 : {
487 : // Functions created at parse time may be set singleton after parsing and
488 : // baked into JIT code, so they must be allocated tenured. They are held by
489 : // the JSScript so cannot be collected during a minor GC anyway.
490 7633 : MOZ_ASSERT(fun->isTenured());
491 7633 : }
492 :
493 : void
494 1407 : FunctionBox::initFromLazyFunction()
495 : {
496 1407 : JSFunction* fun = function();
497 1407 : if (fun->lazyScript()->isDerivedClassConstructor())
498 2 : setDerivedClassConstructor();
499 1407 : if (fun->lazyScript()->needsHomeObject())
500 6 : setNeedsHomeObject();
501 1407 : enclosingScope_ = fun->lazyScript()->enclosingScope();
502 1407 : initWithEnclosingScope(enclosingScope_);
503 1407 : }
504 :
505 : void
506 15 : FunctionBox::initStandaloneFunction(Scope* enclosingScope)
507 : {
508 : // Standalone functions are Function or Generator constructors and are
509 : // always scoped to the global.
510 15 : MOZ_ASSERT(enclosingScope->is<GlobalScope>());
511 15 : enclosingScope_ = enclosingScope;
512 15 : allowNewTarget_ = true;
513 15 : thisBinding_ = ThisBinding::Function;
514 15 : }
515 :
516 : void
517 5951 : FunctionBox::initWithEnclosingParseContext(ParseContext* enclosing, FunctionSyntaxKind kind)
518 : {
519 5951 : SharedContext* sc = enclosing->sc();
520 5951 : useAsm = sc->isFunctionBox() && sc->asFunctionBox()->useAsmOrInsideUseAsm();
521 :
522 5951 : JSFunction* fun = function();
523 :
524 : // Arrow functions and generator expression lambdas don't have
525 : // their own `this` binding.
526 5951 : if (fun->isArrow()) {
527 830 : allowNewTarget_ = sc->allowNewTarget();
528 830 : allowSuperProperty_ = sc->allowSuperProperty();
529 830 : allowSuperCall_ = sc->allowSuperCall();
530 830 : needsThisTDZChecks_ = sc->needsThisTDZChecks();
531 830 : thisBinding_ = sc->thisBinding();
532 : } else {
533 5121 : allowNewTarget_ = true;
534 5121 : allowSuperProperty_ = fun->allowSuperProperty();
535 :
536 5121 : if (kind == ClassConstructor || kind == DerivedClassConstructor) {
537 31 : auto stmt = enclosing->findInnermostStatement<ParseContext::ClassStatement>();
538 31 : MOZ_ASSERT(stmt);
539 31 : stmt->constructorBox = this;
540 :
541 31 : if (kind == DerivedClassConstructor) {
542 15 : setDerivedClassConstructor();
543 15 : allowSuperCall_ = true;
544 15 : needsThisTDZChecks_ = true;
545 : }
546 : }
547 :
548 5121 : if (isGenexpLambda)
549 0 : thisBinding_ = sc->thisBinding();
550 : else
551 5121 : thisBinding_ = ThisBinding::Function;
552 : }
553 :
554 5951 : if (sc->inWith()) {
555 0 : inWith_ = true;
556 : } else {
557 1204 : auto isWith = [](ParseContext::Statement* stmt) {
558 1204 : return stmt->kind() == StatementKind::With;
559 1204 : };
560 :
561 5951 : inWith_ = enclosing->findInnermostStatement(isWith);
562 : }
563 5951 : }
564 :
565 : void
566 1407 : FunctionBox::initWithEnclosingScope(Scope* enclosingScope)
567 : {
568 1407 : if (!function()->isArrow()) {
569 1128 : allowNewTarget_ = true;
570 1128 : allowSuperProperty_ = function()->allowSuperProperty();
571 :
572 1128 : if (isDerivedClassConstructor()) {
573 2 : setDerivedClassConstructor();
574 2 : allowSuperCall_ = true;
575 2 : needsThisTDZChecks_ = true;
576 : }
577 :
578 1128 : thisBinding_ = ThisBinding::Function;
579 : } else {
580 279 : computeAllowSyntax(enclosingScope);
581 279 : computeThisBinding(enclosingScope);
582 : }
583 :
584 1407 : computeInWith(enclosingScope);
585 1407 : }
586 :
587 : void
588 0 : ParserBase::error(unsigned errorNumber, ...)
589 : {
590 : va_list args;
591 0 : va_start(args, errorNumber);
592 :
593 0 : ErrorMetadata metadata;
594 0 : if (tokenStream.computeErrorMetadata(&metadata, pos().begin))
595 0 : ReportCompileError(context, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
596 :
597 0 : va_end(args);
598 0 : }
599 :
600 : void
601 0 : ParserBase::errorWithNotes(UniquePtr<JSErrorNotes> notes, unsigned errorNumber, ...)
602 : {
603 : va_list args;
604 0 : va_start(args, errorNumber);
605 :
606 0 : ErrorMetadata metadata;
607 0 : if (tokenStream.computeErrorMetadata(&metadata, pos().begin)) {
608 0 : ReportCompileError(context, Move(metadata), Move(notes), JSREPORT_ERROR, errorNumber,
609 0 : args);
610 : }
611 :
612 0 : va_end(args);
613 0 : }
614 :
615 : void
616 0 : ParserBase::errorAt(uint32_t offset, unsigned errorNumber, ...)
617 : {
618 : va_list args;
619 0 : va_start(args, errorNumber);
620 :
621 0 : ErrorMetadata metadata;
622 0 : if (tokenStream.computeErrorMetadata(&metadata, offset))
623 0 : ReportCompileError(context, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args);
624 :
625 0 : va_end(args);
626 0 : }
627 :
628 : void
629 0 : ParserBase::errorWithNotesAt(UniquePtr<JSErrorNotes> notes, uint32_t offset,
630 : unsigned errorNumber, ...)
631 : {
632 : va_list args;
633 0 : va_start(args, errorNumber);
634 :
635 0 : ErrorMetadata metadata;
636 0 : if (tokenStream.computeErrorMetadata(&metadata, offset)) {
637 0 : ReportCompileError(context, Move(metadata), Move(notes), JSREPORT_ERROR, errorNumber,
638 0 : args);
639 : }
640 :
641 0 : va_end(args);
642 0 : }
643 :
644 : bool
645 0 : ParserBase::warning(unsigned errorNumber, ...)
646 : {
647 : va_list args;
648 0 : va_start(args, errorNumber);
649 :
650 0 : ErrorMetadata metadata;
651 : bool result =
652 0 : tokenStream.computeErrorMetadata(&metadata, pos().begin) &&
653 0 : tokenStream.compileWarning(Move(metadata), nullptr, JSREPORT_WARNING, errorNumber, args);
654 :
655 0 : va_end(args);
656 0 : return result;
657 : }
658 :
659 : bool
660 0 : ParserBase::warningAt(uint32_t offset, unsigned errorNumber, ...)
661 : {
662 : va_list args;
663 0 : va_start(args, errorNumber);
664 :
665 0 : ErrorMetadata metadata;
666 0 : bool result = tokenStream.computeErrorMetadata(&metadata, offset);
667 0 : if (result) {
668 : result =
669 0 : tokenStream.compileWarning(Move(metadata), nullptr, JSREPORT_WARNING, errorNumber,
670 0 : args);
671 : }
672 :
673 0 : va_end(args);
674 0 : return result;
675 : }
676 :
677 : bool
678 0 : ParserBase::extraWarning(unsigned errorNumber, ...)
679 : {
680 : va_list args;
681 0 : va_start(args, errorNumber);
682 :
683 : bool result =
684 0 : tokenStream.reportExtraWarningErrorNumberVA(nullptr, pos().begin, errorNumber, args);
685 :
686 0 : va_end(args);
687 0 : return result;
688 : }
689 :
690 : bool
691 0 : ParserBase::extraWarningAt(uint32_t offset, unsigned errorNumber, ...)
692 : {
693 : va_list args;
694 0 : va_start(args, errorNumber);
695 :
696 : bool result =
697 0 : tokenStream.reportExtraWarningErrorNumberVA(nullptr, offset, errorNumber, args);
698 :
699 0 : va_end(args);
700 0 : return result;
701 : }
702 :
703 : bool
704 0 : ParserBase::strictModeError(unsigned errorNumber, ...)
705 : {
706 : va_list args;
707 0 : va_start(args, errorNumber);
708 :
709 : bool res =
710 0 : tokenStream.reportStrictModeErrorNumberVA(nullptr, pos().begin, pc->sc()->strict(),
711 0 : errorNumber, args);
712 :
713 0 : va_end(args);
714 0 : return res;
715 : }
716 :
717 : bool
718 0 : ParserBase::strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...)
719 : {
720 : va_list args;
721 0 : va_start(args, errorNumber);
722 :
723 : bool res =
724 0 : tokenStream.reportStrictModeErrorNumberVA(nullptr, offset, pc->sc()->strict(),
725 0 : errorNumber, args);
726 :
727 0 : va_end(args);
728 0 : return res;
729 : }
730 :
731 : bool
732 0 : ParserBase::reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...)
733 : {
734 : va_list args;
735 0 : va_start(args, errorNumber);
736 :
737 0 : bool result = false;
738 0 : switch (kind) {
739 : case ParseError:
740 : case ParseWarning: {
741 0 : ErrorMetadata metadata;
742 0 : tokenStream.computeErrorMetadataNoOffset(&metadata);
743 :
744 0 : if (kind == ParseError) {
745 0 : ReportCompileError(context, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber,
746 0 : args);
747 0 : MOZ_ASSERT(!result);
748 : } else {
749 : result =
750 0 : tokenStream.compileWarning(Move(metadata), nullptr, JSREPORT_WARNING, errorNumber,
751 0 : args);
752 : }
753 :
754 0 : break;
755 : }
756 : case ParseExtraWarning:
757 0 : result = tokenStream.reportExtraWarningErrorNumberVA(nullptr, TokenStream::NoOffset,
758 0 : errorNumber, args);
759 0 : break;
760 : case ParseStrictError:
761 0 : result = tokenStream.reportStrictModeErrorNumberVA(nullptr, TokenStream::NoOffset, strict,
762 0 : errorNumber, args);
763 0 : break;
764 : }
765 :
766 0 : va_end(args);
767 0 : return result;
768 : }
769 :
770 : #define ABORTED_SYNTAX_PARSE_SENTINEL (SyntaxParser*)(0x1)
771 :
772 : template <>
773 : bool
774 0 : Parser<FullParseHandler, char16_t>::hadAbortedSyntaxParse()
775 : {
776 0 : return false;
777 : }
778 :
779 : template <>
780 : bool
781 0 : Parser<SyntaxParseHandler, char16_t>::hadAbortedSyntaxParse()
782 : {
783 0 : return syntaxParser_ == ABORTED_SYNTAX_PARSE_SENTINEL;
784 : }
785 :
786 : template <>
787 : void
788 0 : Parser<FullParseHandler, char16_t>::clearAbortedSyntaxParse()
789 : {
790 0 : }
791 :
792 : template <>
793 : void
794 0 : Parser<SyntaxParseHandler, char16_t>::clearAbortedSyntaxParse()
795 : {
796 0 : syntaxParser_ = nullptr;
797 0 : }
798 :
799 : template <>
800 : void
801 3 : Parser<FullParseHandler, char16_t>::disableSyntaxParser()
802 : {
803 3 : syntaxParser_ = nullptr;
804 3 : }
805 :
806 : template <>
807 : void
808 0 : Parser<SyntaxParseHandler, char16_t>::disableSyntaxParser()
809 : {
810 0 : }
811 :
812 : template <>
813 : inline bool
814 0 : Parser<FullParseHandler, char16_t>::abortIfSyntaxParser()
815 : {
816 0 : disableSyntaxParser();
817 0 : return true;
818 : }
819 :
820 : template <>
821 : inline bool
822 0 : Parser<SyntaxParseHandler, char16_t>::abortIfSyntaxParser()
823 : {
824 0 : syntaxParser_ = ABORTED_SYNTAX_PARSE_SENTINEL;
825 0 : return false;
826 : }
827 :
828 : #undef ABORTED_SYNTAX_PARSE_SENTINEL
829 :
830 1902 : ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
831 : const ReadOnlyCompileOptions& options,
832 : const char16_t* chars, size_t length,
833 : bool foldConstants,
834 : UsedNameTracker& usedNames,
835 1902 : LazyScript* lazyOuterFunction)
836 : : context(cx),
837 : alloc(alloc),
838 1902 : tokenStream(cx, options, chars, length, thisForCtor()),
839 : traceListHead(nullptr),
840 : pc(nullptr),
841 : usedNames(usedNames),
842 : ss(nullptr),
843 : keepAtoms(cx),
844 : foldConstants(foldConstants),
845 : #ifdef DEBUG
846 : checkOptionsCalled(false),
847 : #endif
848 : isUnexpectedEOF_(false),
849 3804 : awaitHandling_(AwaitIsName)
850 : {
851 1902 : cx->frontendCollectionPool().addActiveCompilation();
852 1902 : tempPoolMark = alloc.mark();
853 1902 : }
854 :
855 3806 : ParserBase::~ParserBase()
856 : {
857 1903 : alloc.release(tempPoolMark);
858 :
859 : /*
860 : * The parser can allocate enormous amounts of memory for large functions.
861 : * Eagerly free the memory now (which otherwise won't be freed until the
862 : * next GC) to avoid unnecessary OOMs.
863 : */
864 1903 : alloc.freeAllIfHugeAndUnused();
865 :
866 1903 : context->frontendCollectionPool().removeActiveCompilation();
867 1903 : }
868 :
869 : template <class ParseHandler, typename CharT>
870 1902 : Parser<ParseHandler, CharT>::Parser(JSContext* cx, LifoAlloc& alloc,
871 : const ReadOnlyCompileOptions& options,
872 : const CharT* chars, size_t length,
873 : bool foldConstants,
874 : UsedNameTracker& usedNames,
875 : SyntaxParser* syntaxParser,
876 : LazyScript* lazyOuterFunction)
877 : : ParserBase(cx, alloc, options, chars, length, foldConstants, usedNames, lazyOuterFunction),
878 : AutoGCRooter(cx, PARSER),
879 : syntaxParser_(syntaxParser),
880 1902 : handler(cx, alloc, lazyOuterFunction)
881 : {
882 : // The Mozilla specific JSOPTION_EXTRA_WARNINGS option adds extra warnings
883 : // which are not generated if functions are parsed lazily. Note that the
884 : // standard "use strict" does not inhibit lazy parsing.
885 1902 : if (options.extraWarningsOption)
886 3 : disableSyntaxParser();
887 1902 : }
888 :
889 : template<class ParseHandler, typename CharT>
890 : bool
891 1902 : Parser<ParseHandler, CharT>::checkOptions()
892 : {
893 : #ifdef DEBUG
894 1902 : checkOptionsCalled = true;
895 : #endif
896 :
897 1902 : return tokenStream.checkOptions();
898 : }
899 :
900 : template <class ParseHandler, typename CharT>
901 1903 : Parser<ParseHandler, CharT>::~Parser()
902 : {
903 1903 : MOZ_ASSERT(checkOptionsCalled);
904 3806 : }
905 :
906 : template <>
907 : void
908 9254 : Parser<SyntaxParseHandler, char16_t>::setAwaitHandling(AwaitHandling awaitHandling)
909 : {
910 9254 : awaitHandling_ = awaitHandling;
911 9254 : }
912 :
913 : template <>
914 : void
915 23564 : Parser<FullParseHandler, char16_t>::setAwaitHandling(AwaitHandling awaitHandling)
916 : {
917 23564 : awaitHandling_ = awaitHandling;
918 23564 : if (syntaxParser_)
919 918 : syntaxParser_->setAwaitHandling(awaitHandling);
920 23564 : }
921 :
922 : ObjectBox*
923 2178 : ParserBase::newObjectBox(JSObject* obj)
924 : {
925 2178 : MOZ_ASSERT(obj);
926 :
927 : /*
928 : * We use JSContext.tempLifoAlloc to allocate parsed objects and place them
929 : * on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
930 : * arenas containing the entries must be alive until we are done with
931 : * scanning, parsing and code generation for the whole script or top-level
932 : * function.
933 : */
934 :
935 2178 : ObjectBox* objbox = alloc.new_<ObjectBox>(obj, traceListHead);
936 2178 : if (!objbox) {
937 0 : ReportOutOfMemory(context);
938 0 : return nullptr;
939 : }
940 :
941 2178 : traceListHead = objbox;
942 :
943 2178 : return objbox;
944 : }
945 :
946 : template <class ParseHandler, typename CharT>
947 : FunctionBox*
948 7633 : Parser<ParseHandler, CharT>::newFunctionBox(Node fn, JSFunction* fun, uint32_t toStringStart,
949 : Directives inheritedDirectives,
950 : GeneratorKind generatorKind, FunctionAsyncKind asyncKind)
951 : {
952 7633 : MOZ_ASSERT(fun);
953 :
954 : /*
955 : * We use JSContext.tempLifoAlloc to allocate parsed objects and place them
956 : * on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
957 : * arenas containing the entries must be alive until we are done with
958 : * scanning, parsing and code generation for the whole script or top-level
959 : * function.
960 : */
961 : FunctionBox* funbox =
962 7633 : alloc.new_<FunctionBox>(context, alloc, traceListHead, fun, toStringStart,
963 7633 : inheritedDirectives, options().extraWarningsOption,
964 15266 : generatorKind, asyncKind);
965 7633 : if (!funbox) {
966 0 : ReportOutOfMemory(context);
967 0 : return nullptr;
968 : }
969 :
970 7633 : traceListHead = funbox;
971 7633 : if (fn)
972 7633 : handler.setFunctionBox(fn, funbox);
973 :
974 7633 : return funbox;
975 : }
976 :
977 0 : ModuleSharedContext::ModuleSharedContext(JSContext* cx, ModuleObject* module,
978 0 : Scope* enclosingScope, ModuleBuilder& builder)
979 : : SharedContext(cx, Kind::Module, Directives(true), false),
980 : module_(cx, module),
981 : enclosingScope_(cx, enclosingScope),
982 : bindings(cx),
983 0 : builder(builder)
984 : {
985 0 : thisBinding_ = ThisBinding::Module;
986 0 : }
987 :
988 : template <class ParseHandler, typename CharT>
989 : void
990 0 : Parser<ParseHandler, CharT>::trace(JSTracer* trc)
991 : {
992 0 : ObjectBox::TraceList(trc, traceListHead);
993 0 : }
994 :
995 : void
996 0 : TraceParser(JSTracer* trc, AutoGCRooter* parser)
997 : {
998 0 : static_cast<Parser<FullParseHandler, char16_t>*>(parser)->trace(trc);
999 0 : }
1000 :
1001 : /*
1002 : * Parse a top-level JS script.
1003 : */
1004 : template <class ParseHandler, typename CharT>
1005 : typename ParseHandler::Node
1006 0 : Parser<ParseHandler, CharT>::parse()
1007 : {
1008 0 : MOZ_ASSERT(checkOptionsCalled);
1009 :
1010 0 : Directives directives(options().strictOption);
1011 0 : GlobalSharedContext globalsc(context, ScopeKind::Global,
1012 0 : directives, options().extraWarningsOption);
1013 0 : ParseContext globalpc(this, &globalsc, /* newDirectives = */ nullptr);
1014 0 : if (!globalpc.init())
1015 0 : return null();
1016 :
1017 0 : ParseContext::VarScope varScope(this);
1018 0 : if (!varScope.init(pc))
1019 0 : return null();
1020 :
1021 0 : Node pn = statementList(YieldIsName);
1022 0 : if (!pn)
1023 0 : return null();
1024 :
1025 : TokenKind tt;
1026 0 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
1027 0 : return null();
1028 0 : if (tt != TOK_EOF) {
1029 0 : error(JSMSG_GARBAGE_AFTER_INPUT, "script", TokenKindToDesc(tt));
1030 0 : return null();
1031 : }
1032 0 : if (foldConstants) {
1033 0 : if (!FoldConstants(context, &pn, this))
1034 0 : return null();
1035 : }
1036 :
1037 0 : return pn;
1038 : }
1039 :
1040 : /*
1041 : * Strict mode forbids introducing new definitions for 'eval', 'arguments', or
1042 : * for any strict mode reserved word.
1043 : */
1044 : bool
1045 5 : ParserBase::isValidStrictBinding(PropertyName* name)
1046 : {
1047 5 : TokenKind tt = ReservedWordTokenKind(name);
1048 5 : if (tt == TOK_NAME) {
1049 10 : return name != context->names().eval &&
1050 10 : name != context->names().arguments;
1051 : }
1052 0 : return tt != TOK_LET &&
1053 0 : tt != TOK_STATIC &&
1054 0 : tt != TOK_YIELD &&
1055 0 : !TokenKindIsStrictReservedWord(tt);
1056 : }
1057 :
1058 : /*
1059 : * Returns true if all parameter names are valid strict mode binding names and
1060 : * no duplicate parameter names are present.
1061 : */
1062 : bool
1063 5 : ParserBase::hasValidSimpleStrictParameterNames()
1064 : {
1065 5 : MOZ_ASSERT(pc->isFunctionBox() && pc->functionBox()->hasSimpleParameterList());
1066 :
1067 5 : if (pc->functionBox()->hasDuplicateParameters)
1068 0 : return false;
1069 :
1070 10 : for (auto* name : pc->positionalFormalParameterNames()) {
1071 5 : MOZ_ASSERT(name);
1072 5 : if (!isValidStrictBinding(name->asPropertyName()))
1073 0 : return false;
1074 : }
1075 5 : return true;
1076 : }
1077 :
1078 : template <class ParseHandler, typename CharT>
1079 : void
1080 0 : Parser<ParseHandler, CharT>::reportMissingClosing(unsigned errorNumber, unsigned noteNumber,
1081 : uint32_t openedPos)
1082 : {
1083 0 : auto notes = MakeUnique<JSErrorNotes>();
1084 0 : if (!notes) {
1085 0 : ReportOutOfMemory(pc->sc()->context);
1086 0 : return;
1087 : }
1088 :
1089 : uint32_t line, column;
1090 0 : tokenStream.srcCoords.lineNumAndColumnIndex(openedPos, &line, &column);
1091 :
1092 0 : const size_t MaxWidth = sizeof("4294967295");
1093 : char columnNumber[MaxWidth];
1094 0 : SprintfLiteral(columnNumber, "%" PRIu32, column);
1095 : char lineNumber[MaxWidth];
1096 0 : SprintfLiteral(lineNumber, "%" PRIu32, line);
1097 :
1098 0 : if (!notes->addNoteASCII(pc->sc()->context,
1099 : getFilename(), line, column,
1100 : GetErrorMessage, nullptr,
1101 : noteNumber, lineNumber, columnNumber))
1102 : {
1103 0 : return;
1104 : }
1105 :
1106 0 : errorWithNotes(Move(notes), errorNumber);
1107 : }
1108 :
1109 : template <class ParseHandler, typename CharT>
1110 : void
1111 0 : Parser<ParseHandler, CharT>::reportRedeclaration(HandlePropertyName name, DeclarationKind prevKind,
1112 : TokenPos pos, uint32_t prevPos)
1113 : {
1114 0 : JSAutoByteString bytes;
1115 0 : if (!AtomToPrintableString(context, name, &bytes))
1116 0 : return;
1117 :
1118 0 : if (prevPos == DeclaredNameInfo::npos) {
1119 0 : errorAt(pos.begin, JSMSG_REDECLARED_VAR, DeclarationKindString(prevKind), bytes.ptr());
1120 0 : return;
1121 : }
1122 :
1123 0 : auto notes = MakeUnique<JSErrorNotes>();
1124 0 : if (!notes) {
1125 0 : ReportOutOfMemory(pc->sc()->context);
1126 0 : return;
1127 : }
1128 :
1129 : uint32_t line, column;
1130 0 : tokenStream.srcCoords.lineNumAndColumnIndex(prevPos, &line, &column);
1131 :
1132 0 : const size_t MaxWidth = sizeof("4294967295");
1133 : char columnNumber[MaxWidth];
1134 0 : SprintfLiteral(columnNumber, "%" PRIu32, column);
1135 : char lineNumber[MaxWidth];
1136 0 : SprintfLiteral(lineNumber, "%" PRIu32, line);
1137 :
1138 0 : if (!notes->addNoteASCII(pc->sc()->context,
1139 : getFilename(), line, column,
1140 : GetErrorMessage, nullptr,
1141 : JSMSG_REDECLARED_PREV,
1142 : lineNumber, columnNumber))
1143 : {
1144 0 : return;
1145 : }
1146 :
1147 0 : errorWithNotesAt(Move(notes), pos.begin, JSMSG_REDECLARED_VAR,
1148 : DeclarationKindString(prevKind), bytes.ptr());
1149 : }
1150 :
1151 : // notePositionalFormalParameter is called for both the arguments of a regular
1152 : // function definition and the arguments specified by the Function
1153 : // constructor.
1154 : //
1155 : // The 'disallowDuplicateParams' bool indicates whether the use of another
1156 : // feature (destructuring or default arguments) disables duplicate arguments.
1157 : // (ECMA-262 requires us to support duplicate parameter names, but, for newer
1158 : // features, we consider the code to have "opted in" to higher standards and
1159 : // forbid duplicates.)
1160 : template <class ParseHandler, typename CharT>
1161 : bool
1162 8338 : Parser<ParseHandler, CharT>::notePositionalFormalParameter(Node fn, HandlePropertyName name,
1163 : uint32_t beginPos,
1164 : bool disallowDuplicateParams,
1165 : bool* duplicatedParam)
1166 : {
1167 8338 : if (AddDeclaredNamePtr p = pc->functionScope().lookupDeclaredNameForAdd(name)) {
1168 0 : if (disallowDuplicateParams) {
1169 0 : error(JSMSG_BAD_DUP_ARGS);
1170 0 : return false;
1171 : }
1172 :
1173 : // Strict-mode disallows duplicate args. We may not know whether we are
1174 : // in strict mode or not (since the function body hasn't been parsed).
1175 : // In such cases, report will queue up the potential error and return
1176 : // 'true'.
1177 0 : if (pc->sc()->needStrictChecks()) {
1178 0 : JSAutoByteString bytes;
1179 0 : if (!AtomToPrintableString(context, name, &bytes))
1180 0 : return false;
1181 0 : if (!strictModeError(JSMSG_DUPLICATE_FORMAL, bytes.ptr()))
1182 0 : return false;
1183 : }
1184 :
1185 0 : *duplicatedParam = true;
1186 : } else {
1187 8338 : DeclarationKind kind = DeclarationKind::PositionalFormalParameter;
1188 8338 : if (!pc->functionScope().addDeclaredName(pc, p, name, kind, beginPos))
1189 0 : return false;
1190 : }
1191 :
1192 8338 : if (!pc->positionalFormalParameterNames().append(name)) {
1193 0 : ReportOutOfMemory(context);
1194 0 : return false;
1195 : }
1196 :
1197 8338 : Node paramNode = newName(name);
1198 8338 : if (!paramNode)
1199 0 : return false;
1200 :
1201 8338 : handler.addFunctionFormalParameter(fn, paramNode);
1202 8338 : return true;
1203 : }
1204 :
1205 : template <class ParseHandler, typename CharT>
1206 : bool
1207 78 : Parser<ParseHandler, CharT>::noteDestructuredPositionalFormalParameter(Node fn, Node destruct)
1208 : {
1209 : // Append an empty name to the positional formals vector to keep track of
1210 : // argument slots when making FunctionScope::Data.
1211 78 : if (!pc->positionalFormalParameterNames().append(nullptr)) {
1212 0 : ReportOutOfMemory(context);
1213 0 : return false;
1214 : }
1215 :
1216 78 : handler.addFunctionFormalParameter(fn, destruct);
1217 78 : return true;
1218 : }
1219 :
1220 : static bool
1221 8057 : DeclarationKindIsVar(DeclarationKind kind)
1222 : {
1223 1847 : return kind == DeclarationKind::Var ||
1224 16 : kind == DeclarationKind::BodyLevelFunction ||
1225 8073 : kind == DeclarationKind::VarForAnnexBLexicalFunction ||
1226 8057 : kind == DeclarationKind::ForOfVar;
1227 : }
1228 :
1229 : Maybe<DeclarationKind>
1230 0 : ParseContext::isVarRedeclaredInEval(HandlePropertyName name, DeclarationKind kind)
1231 : {
1232 0 : MOZ_ASSERT(DeclarationKindIsVar(kind));
1233 0 : MOZ_ASSERT(sc()->isEvalContext());
1234 :
1235 : // In the case of eval, we also need to check enclosing VM scopes to see
1236 : // if the var declaration is allowed in the context.
1237 : //
1238 : // This check is necessary in addition to
1239 : // js::CheckEvalDeclarationConflicts because we only know during parsing
1240 : // if a var is bound by for-of.
1241 0 : js::Scope* enclosingScope = sc()->compilationEnclosingScope();
1242 0 : js::Scope* varScope = EvalScope::nearestVarScopeForDirectEval(enclosingScope);
1243 0 : MOZ_ASSERT(varScope);
1244 0 : for (ScopeIter si(enclosingScope); si; si++) {
1245 0 : for (js::BindingIter bi(si.scope()); bi; bi++) {
1246 0 : if (bi.name() != name)
1247 0 : continue;
1248 :
1249 0 : switch (bi.kind()) {
1250 : case BindingKind::Let: {
1251 : // Annex B.3.5 allows redeclaring simple (non-destructured)
1252 : // catch parameters with var declarations, except when it
1253 : // appears in a for-of.
1254 0 : bool annexB35Allowance = si.kind() == ScopeKind::SimpleCatch &&
1255 0 : kind != DeclarationKind::ForOfVar;
1256 0 : if (!annexB35Allowance) {
1257 0 : return Some(ScopeKindIsCatch(si.kind())
1258 0 : ? DeclarationKind::CatchParameter
1259 0 : : DeclarationKind::Let);
1260 : }
1261 0 : break;
1262 : }
1263 :
1264 : case BindingKind::Const:
1265 0 : return Some(DeclarationKind::Const);
1266 :
1267 : case BindingKind::Import:
1268 : case BindingKind::FormalParameter:
1269 : case BindingKind::Var:
1270 : case BindingKind::NamedLambdaCallee:
1271 0 : break;
1272 : }
1273 : }
1274 :
1275 0 : if (si.scope() == varScope)
1276 0 : break;
1277 : }
1278 :
1279 0 : return Nothing();
1280 : }
1281 :
1282 : Maybe<DeclarationKind>
1283 0 : ParseContext::isVarRedeclaredInInnermostScope(HandlePropertyName name, DeclarationKind kind)
1284 : {
1285 0 : Maybe<DeclarationKind> redeclaredKind;
1286 : uint32_t unused;
1287 0 : MOZ_ALWAYS_TRUE(tryDeclareVarHelper<DryRunInnermostScopeOnly>(name, kind,
1288 : DeclaredNameInfo::npos,
1289 : &redeclaredKind, &unused));
1290 0 : return redeclaredKind;
1291 : }
1292 :
1293 : bool
1294 7145 : ParseContext::tryDeclareVar(HandlePropertyName name, DeclarationKind kind,
1295 : uint32_t beginPos, Maybe<DeclarationKind>* redeclaredKind,
1296 : uint32_t* prevPos)
1297 : {
1298 7145 : return tryDeclareVarHelper<NotDryRun>(name, kind, beginPos, redeclaredKind, prevPos);
1299 : }
1300 :
1301 : static bool
1302 0 : DeclarationKindIsParameter(DeclarationKind kind)
1303 : {
1304 0 : return kind == DeclarationKind::PositionalFormalParameter ||
1305 0 : kind == DeclarationKind::FormalParameter;
1306 : }
1307 :
1308 : template <ParseContext::DryRunOption dryRunOption>
1309 : bool
1310 7145 : ParseContext::tryDeclareVarHelper(HandlePropertyName name, DeclarationKind kind,
1311 : uint32_t beginPos, Maybe<DeclarationKind>* redeclaredKind,
1312 : uint32_t* prevPos)
1313 : {
1314 7145 : MOZ_ASSERT(DeclarationKindIsVar(kind));
1315 :
1316 : // It is an early error if a 'var' declaration appears inside a
1317 : // scope contour that has a lexical declaration of the same name. For
1318 : // example, the following are early errors:
1319 : //
1320 : // { let x; var x; }
1321 : // { { var x; } let x; }
1322 : //
1323 : // And the following are not:
1324 : //
1325 : // { var x; var x; }
1326 : // { { let x; } var x; }
1327 :
1328 32518 : for (ParseContext::Scope* scope = innermostScope();
1329 16259 : scope != varScope().enclosing();
1330 9114 : scope = scope->enclosing())
1331 : {
1332 9114 : if (AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name)) {
1333 912 : DeclarationKind declaredKind = p->value()->kind();
1334 912 : if (DeclarationKindIsVar(declaredKind)) {
1335 : // Any vars that are redeclared as body-level functions must
1336 : // be recorded as body-level functions.
1337 : //
1338 : // In the case of global and eval scripts, GlobalDeclaration-
1339 : // Instantiation [1] and EvalDeclarationInstantiation [2]
1340 : // check for the declarability of global var and function
1341 : // bindings via CanDeclareVar [3] and CanDeclareGlobal-
1342 : // Function [4]. CanDeclareGlobalFunction is strictly more
1343 : // restrictive than CanDeclareGlobalVar, so record the more
1344 : // restrictive kind. These semantics are implemented in
1345 : // CheckCanDeclareGlobalBinding.
1346 : //
1347 : // For a var previously declared as ForOfVar, this previous
1348 : // DeclarationKind is used only to check for if the
1349 : // 'arguments' binding should be declared. Since body-level
1350 : // functions shadow 'arguments' [5], it is correct to alter
1351 : // the kind to BodyLevelFunction. See
1352 : // declareFunctionArgumentsObject.
1353 : //
1354 : // VarForAnnexBLexicalFunction declarations are declared when
1355 : // the var scope exits. It is not possible for a var to be
1356 : // previously declared as VarForAnnexBLexicalFunction and
1357 : // checked for redeclaration.
1358 : //
1359 : // [1] ES 15.1.11
1360 : // [2] ES 18.2.1.3
1361 : // [3] ES 8.1.1.4.15
1362 : // [4] ES 8.1.1.4.16
1363 : // [5] ES 9.2.12
1364 912 : if (dryRunOption == NotDryRun && kind == DeclarationKind::BodyLevelFunction) {
1365 0 : MOZ_ASSERT(declaredKind != DeclarationKind::VarForAnnexBLexicalFunction);
1366 0 : p->value()->alterKind(kind);
1367 : }
1368 0 : } else if (!DeclarationKindIsParameter(declaredKind)) {
1369 : // Annex B.3.5 allows redeclaring simple (non-destructured)
1370 : // catch parameters with var declarations, except when it
1371 : // appears in a for-of.
1372 0 : bool annexB35Allowance = declaredKind == DeclarationKind::SimpleCatchParameter &&
1373 0 : kind != DeclarationKind::ForOfVar;
1374 :
1375 : // Annex B.3.3 allows redeclaring functions in the same block.
1376 0 : bool annexB33Allowance = declaredKind == DeclarationKind::SloppyLexicalFunction &&
1377 0 : kind == DeclarationKind::VarForAnnexBLexicalFunction &&
1378 0 : scope == innermostScope();
1379 :
1380 0 : if (!annexB35Allowance && !annexB33Allowance) {
1381 0 : *redeclaredKind = Some(declaredKind);
1382 0 : *prevPos = p->value()->pos();
1383 0 : return true;
1384 : }
1385 0 : } else if (kind == DeclarationKind::VarForAnnexBLexicalFunction) {
1386 0 : MOZ_ASSERT(DeclarationKindIsParameter(declaredKind));
1387 :
1388 : // Annex B.3.3.1 disallows redeclaring parameter names.
1389 : // We don't need to set *prevPos here since this case is not
1390 : // an error.
1391 0 : *redeclaredKind = Some(declaredKind);
1392 0 : return true;
1393 : }
1394 : } else if (dryRunOption == NotDryRun) {
1395 8202 : if (!scope->addDeclaredName(this, p, name, kind, beginPos))
1396 0 : return false;
1397 : }
1398 :
1399 : // DryRunOption is used for propagating Annex B functions: we don't
1400 : // want to declare the synthesized Annex B vars until we exit the var
1401 : // scope and know that no early errors would have occurred. In order
1402 : // to avoid quadratic search, we only check for var redeclarations in
1403 : // the innermost scope when doing a dry run.
1404 : if (dryRunOption == DryRunInnermostScopeOnly)
1405 0 : break;
1406 : }
1407 :
1408 7145 : if (!sc()->strict() && sc()->isEvalContext() &&
1409 0 : (dryRunOption == NotDryRun || innermostScope() == &varScope()))
1410 : {
1411 0 : *redeclaredKind = isVarRedeclaredInEval(name, kind);
1412 : // We don't have position information at runtime.
1413 0 : *prevPos = DeclaredNameInfo::npos;
1414 : }
1415 :
1416 7145 : return true;
1417 : }
1418 :
1419 : bool
1420 0 : ParseContext::annexBAppliesToLexicalFunctionInInnermostScope(FunctionBox* funbox)
1421 : {
1422 0 : MOZ_ASSERT(!sc()->strict());
1423 :
1424 0 : RootedPropertyName name(sc()->context, funbox->function()->explicitName()->asPropertyName());
1425 : Maybe<DeclarationKind> redeclaredKind =
1426 0 : isVarRedeclaredInInnermostScope(name, DeclarationKind::VarForAnnexBLexicalFunction);
1427 :
1428 0 : if (!redeclaredKind && isFunctionBox()) {
1429 0 : Scope& funScope = functionScope();
1430 0 : if (&funScope != &varScope()) {
1431 : // Annex B.3.3.1 disallows redeclaring parameter names. In the
1432 : // presence of parameter expressions, parameter names are on the
1433 : // function scope, which encloses the var scope. This means the
1434 : // isVarRedeclaredInInnermostScope call above would not catch this
1435 : // case, so test it manually.
1436 0 : if (AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(name)) {
1437 0 : DeclarationKind declaredKind = p->value()->kind();
1438 0 : if (DeclarationKindIsParameter(declaredKind))
1439 0 : redeclaredKind = Some(declaredKind);
1440 : else
1441 0 : MOZ_ASSERT(FunctionScope::isSpecialName(sc()->context, name));
1442 : }
1443 : }
1444 : }
1445 :
1446 : // If an early error would have occurred already, this function should not
1447 : // exhibit Annex B.3.3 semantics.
1448 0 : return !redeclaredKind;
1449 : }
1450 :
1451 : template <class ParseHandler, typename CharT>
1452 : bool
1453 3001 : Parser<ParseHandler, CharT>::checkLexicalDeclarationDirectlyWithinBlock(ParseContext::Statement& stmt,
1454 : DeclarationKind kind,
1455 : TokenPos pos)
1456 : {
1457 3001 : MOZ_ASSERT(DeclarationKindIsLexical(kind));
1458 :
1459 : // It is an early error to declare a lexical binding not directly
1460 : // within a block.
1461 3712 : if (!StatementKindIsBraced(stmt.kind()) &&
1462 711 : stmt.kind() != StatementKind::ForLoopLexicalHead)
1463 : {
1464 0 : errorAt(pos.begin,
1465 0 : stmt.kind() == StatementKind::Label
1466 : ? JSMSG_LEXICAL_DECL_LABEL
1467 : : JSMSG_LEXICAL_DECL_NOT_IN_BLOCK,
1468 : DeclarationKindString(kind));
1469 0 : return false;
1470 : }
1471 :
1472 3001 : return true;
1473 : }
1474 :
1475 : template <class ParseHandler, typename CharT>
1476 : bool
1477 14982 : Parser<ParseHandler, CharT>::noteDeclaredName(HandlePropertyName name, DeclarationKind kind,
1478 : TokenPos pos)
1479 : {
1480 : // The asm.js validator does all its own symbol-table management so, as an
1481 : // optimization, avoid doing any work here.
1482 14982 : if (pc->useAsmOrInsideUseAsm())
1483 0 : return true;
1484 :
1485 14982 : switch (kind) {
1486 : case DeclarationKind::Var:
1487 : case DeclarationKind::BodyLevelFunction:
1488 : case DeclarationKind::ForOfVar: {
1489 7145 : Maybe<DeclarationKind> redeclaredKind;
1490 : uint32_t prevPos;
1491 7145 : if (!pc->tryDeclareVar(name, kind, pos.begin, &redeclaredKind, &prevPos))
1492 0 : return false;
1493 :
1494 7145 : if (redeclaredKind) {
1495 0 : reportRedeclaration(name, *redeclaredKind, pos, prevPos);
1496 0 : return false;
1497 : }
1498 :
1499 7145 : break;
1500 : }
1501 :
1502 : case DeclarationKind::ModuleBodyLevelFunction: {
1503 0 : MOZ_ASSERT(pc->atModuleLevel());
1504 :
1505 0 : AddDeclaredNamePtr p = pc->varScope().lookupDeclaredNameForAdd(name);
1506 0 : if (p) {
1507 0 : reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
1508 0 : return false;
1509 : }
1510 :
1511 0 : if (!pc->varScope().addDeclaredName(pc, p, name, kind, pos.begin))
1512 0 : return false;
1513 :
1514 : // Body-level functions in modules are always closed over.
1515 0 : pc->varScope().lookupDeclaredName(name)->value()->setClosedOver();
1516 :
1517 0 : break;
1518 : }
1519 :
1520 : case DeclarationKind::FormalParameter: {
1521 : // It is an early error if any non-positional formal parameter name
1522 : // (e.g., destructuring formal parameter) is duplicated.
1523 :
1524 183 : AddDeclaredNamePtr p = pc->functionScope().lookupDeclaredNameForAdd(name);
1525 183 : if (p) {
1526 0 : error(JSMSG_BAD_DUP_ARGS);
1527 0 : return false;
1528 : }
1529 :
1530 183 : if (!pc->functionScope().addDeclaredName(pc, p, name, kind, pos.begin))
1531 0 : return false;
1532 :
1533 183 : break;
1534 : }
1535 :
1536 : case DeclarationKind::LexicalFunction: {
1537 0 : ParseContext::Scope* scope = pc->innermostScope();
1538 0 : AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name);
1539 0 : if (p) {
1540 0 : reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
1541 0 : return false;
1542 : }
1543 :
1544 0 : if (!scope->addDeclaredName(pc, p, name, kind, pos.begin))
1545 0 : return false;
1546 :
1547 0 : break;
1548 : }
1549 :
1550 : case DeclarationKind::SloppyLexicalFunction: {
1551 : // Functions in block have complex allowances in sloppy mode for being
1552 : // labelled that other lexical declarations do not have. Those checks
1553 : // are more complex than calling checkLexicalDeclarationDirectlyWithin-
1554 : // Block and are done in checkFunctionDefinition.
1555 :
1556 0 : ParseContext::Scope* scope = pc->innermostScope();
1557 0 : if (AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name)) {
1558 : // It is usually an early error if there is another declaration
1559 : // with the same name in the same scope.
1560 : //
1561 : // Sloppy lexical functions may redeclare other sloppy lexical
1562 : // functions for web compatibility reasons.
1563 0 : if (p->value()->kind() != DeclarationKind::SloppyLexicalFunction) {
1564 0 : reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
1565 0 : return false;
1566 : }
1567 : } else {
1568 0 : if (!scope->addDeclaredName(pc, p, name, kind, pos.begin))
1569 0 : return false;
1570 : }
1571 :
1572 0 : break;
1573 : }
1574 :
1575 : case DeclarationKind::Let:
1576 : case DeclarationKind::Const:
1577 : // The BoundNames of LexicalDeclaration and ForDeclaration must not
1578 : // contain 'let'. (CatchParameter is the only lexical binding form
1579 : // without this restriction.)
1580 6999 : if (name == context->names().let) {
1581 0 : errorAt(pos.begin, JSMSG_LEXICAL_DECL_DEFINES_LET);
1582 0 : return false;
1583 : }
1584 :
1585 : MOZ_FALLTHROUGH;
1586 :
1587 : case DeclarationKind::Import:
1588 : // Module code is always strict, so 'let' is always a keyword and never a name.
1589 6999 : MOZ_ASSERT(name != context->names().let);
1590 : MOZ_FALLTHROUGH;
1591 :
1592 : case DeclarationKind::SimpleCatchParameter:
1593 : case DeclarationKind::CatchParameter: {
1594 7654 : if (ParseContext::Statement* stmt = pc->innermostStatement()) {
1595 3001 : if (!checkLexicalDeclarationDirectlyWithinBlock(*stmt, kind, pos))
1596 0 : return false;
1597 : }
1598 :
1599 7654 : ParseContext::Scope* scope = pc->innermostScope();
1600 :
1601 : // For body-level lexically declared names in a function, it is an
1602 : // early error if there is a formal parameter of the same name. This
1603 : // needs a special check if there is an extra var scope due to
1604 : // parameter expressions.
1605 7654 : if (pc->isFunctionExtraBodyVarScopeInnermost()) {
1606 206 : DeclaredNamePtr p = pc->functionScope().lookupDeclaredName(name);
1607 206 : if (p && DeclarationKindIsParameter(p->value()->kind())) {
1608 0 : reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
1609 0 : return false;
1610 : }
1611 : }
1612 :
1613 : // It is an early error if there is another declaration with the same
1614 : // name in the same scope.
1615 7654 : AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name);
1616 7654 : if (p) {
1617 0 : reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
1618 0 : return false;
1619 : }
1620 :
1621 7654 : if (!scope->addDeclaredName(pc, p, name, kind, pos.begin))
1622 0 : return false;
1623 :
1624 7654 : break;
1625 : }
1626 :
1627 : case DeclarationKind::CoverArrowParameter:
1628 : // CoverArrowParameter is only used as a placeholder declaration kind.
1629 0 : break;
1630 :
1631 : case DeclarationKind::PositionalFormalParameter:
1632 0 : MOZ_CRASH("Positional formal parameter names should use "
1633 : "notePositionalFormalParameter");
1634 : break;
1635 :
1636 : case DeclarationKind::VarForAnnexBLexicalFunction:
1637 0 : MOZ_CRASH("Synthesized Annex B vars should go through "
1638 : "tryDeclareVarForAnnexBLexicalFunction");
1639 : break;
1640 : }
1641 :
1642 14982 : return true;
1643 : }
1644 :
1645 : template <class ParseHandler, typename CharT>
1646 : bool
1647 92570 : Parser<ParseHandler, CharT>::noteUsedName(HandlePropertyName name)
1648 : {
1649 : // If the we are delazifying, the LazyScript already has all the
1650 : // closed-over info for bindings and there's no need to track used names.
1651 92570 : if (handler.canSkipLazyClosedOverBindings())
1652 12276 : return true;
1653 :
1654 : // The asm.js validator does all its own symbol-table management so, as an
1655 : // optimization, avoid doing any work here.
1656 80294 : if (pc->useAsmOrInsideUseAsm())
1657 0 : return true;
1658 :
1659 : // Global bindings are properties and not actual bindings; we don't need
1660 : // to know if they are closed over. So no need to track used name at the
1661 : // global scope. It is not incorrect to track them, this is an
1662 : // optimization.
1663 80294 : ParseContext::Scope* scope = pc->innermostScope();
1664 80294 : if (pc->sc()->isGlobalContext() && scope == &pc->varScope())
1665 2940 : return true;
1666 :
1667 77354 : return usedNames.noteUse(context, name, pc->scriptId(), scope->id());
1668 : }
1669 :
1670 : template <class ParseHandler, typename CharT>
1671 : bool
1672 10274 : Parser<ParseHandler, CharT>::hasUsedName(HandlePropertyName name)
1673 : {
1674 10274 : if (UsedNamePtr p = usedNames.lookup(name))
1675 6154 : return p->value().isUsedInScript(pc->scriptId());
1676 4120 : return false;
1677 : }
1678 :
1679 : template <class ParseHandler, typename CharT>
1680 : bool
1681 18562 : Parser<ParseHandler, CharT>::propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope)
1682 : {
1683 : // Now that we have all the declared names in the scope, check which
1684 : // functions should exhibit Annex B semantics.
1685 18562 : if (!scope.propagateAndMarkAnnexBFunctionBoxes(pc))
1686 0 : return false;
1687 :
1688 18562 : if (handler.canSkipLazyClosedOverBindings()) {
1689 : // Scopes are nullptr-delimited in the LazyScript closed over bindings
1690 : // array.
1691 3973 : while (JSAtom* name = handler.nextLazyClosedOverBinding())
1692 291 : scope.lookupDeclaredName(name)->value()->setClosedOver();
1693 3391 : return true;
1694 : }
1695 :
1696 15171 : bool isSyntaxParser = mozilla::IsSame<ParseHandler, SyntaxParseHandler>::value;
1697 15171 : uint32_t scriptId = pc->scriptId();
1698 15171 : uint32_t scopeId = scope.id();
1699 35132 : for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1700 19961 : if (UsedNamePtr p = usedNames.lookup(bi.name())) {
1701 : bool closedOver;
1702 18876 : p->value().noteBoundInScope(scriptId, scopeId, &closedOver);
1703 18876 : if (closedOver) {
1704 1212 : bi.setClosedOver();
1705 :
1706 1212 : if (isSyntaxParser && !pc->closedOverBindingsForLazy().append(bi.name())) {
1707 0 : ReportOutOfMemory(context);
1708 0 : return false;
1709 : }
1710 : }
1711 : }
1712 : }
1713 :
1714 : // Append a nullptr to denote end-of-scope.
1715 15171 : if (isSyntaxParser && !pc->closedOverBindingsForLazy().append(nullptr)) {
1716 0 : ReportOutOfMemory(context);
1717 0 : return false;
1718 : }
1719 :
1720 15171 : return true;
1721 : }
1722 :
1723 : template <>
1724 : bool
1725 268 : Parser<FullParseHandler, char16_t>::checkStatementsEOF()
1726 : {
1727 : // This is designed to be paired with parsing a statement list at the top
1728 : // level.
1729 : //
1730 : // The statementList() call breaks on TOK_RC, so make sure we've
1731 : // reached EOF here.
1732 : TokenKind tt;
1733 268 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
1734 0 : return false;
1735 268 : if (tt != TOK_EOF) {
1736 0 : error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt));
1737 0 : return false;
1738 : }
1739 268 : return true;
1740 : }
1741 :
1742 : template <typename Scope>
1743 : static typename Scope::Data*
1744 8091 : NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc, uint32_t numBindings)
1745 : {
1746 8091 : size_t allocSize = Scope::sizeOfData(numBindings);
1747 8091 : typename Scope::Data* bindings = static_cast<typename Scope::Data*>(alloc.alloc(allocSize));
1748 8091 : if (!bindings) {
1749 0 : ReportOutOfMemory(cx);
1750 0 : return nullptr;
1751 : }
1752 8091 : PodZero(bindings);
1753 8091 : return bindings;
1754 : }
1755 :
1756 : Maybe<GlobalScope::Data*>
1757 266 : ParserBase::newGlobalScopeData(ParseContext::Scope& scope)
1758 : {
1759 532 : Vector<BindingName> funs(context);
1760 532 : Vector<BindingName> vars(context);
1761 532 : Vector<BindingName> lets(context);
1762 532 : Vector<BindingName> consts(context);
1763 :
1764 266 : bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
1765 3576 : for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1766 3310 : BindingName binding(bi.name(), allBindingsClosedOver || bi.closedOver());
1767 3310 : switch (bi.kind()) {
1768 : case BindingKind::Var:
1769 2140 : if (bi.declarationKind() == DeclarationKind::BodyLevelFunction) {
1770 1749 : if (!funs.append(binding))
1771 0 : return Nothing();
1772 : } else {
1773 391 : if (!vars.append(binding))
1774 0 : return Nothing();
1775 : }
1776 2140 : break;
1777 : case BindingKind::Let:
1778 64 : if (!lets.append(binding))
1779 0 : return Nothing();
1780 64 : break;
1781 : case BindingKind::Const:
1782 1106 : if (!consts.append(binding))
1783 0 : return Nothing();
1784 1106 : break;
1785 : default:
1786 0 : MOZ_CRASH("Bad global scope BindingKind");
1787 : }
1788 : }
1789 :
1790 266 : GlobalScope::Data* bindings = nullptr;
1791 266 : uint32_t numBindings = funs.length() + vars.length() + lets.length() + consts.length();
1792 :
1793 266 : if (numBindings > 0) {
1794 133 : bindings = NewEmptyBindingData<GlobalScope>(context, alloc, numBindings);
1795 133 : if (!bindings)
1796 0 : return Nothing();
1797 :
1798 : // The ordering here is important. See comments in GlobalScope.
1799 133 : BindingName* start = bindings->names;
1800 133 : BindingName* cursor = start;
1801 :
1802 133 : PodCopy(cursor, funs.begin(), funs.length());
1803 133 : cursor += funs.length();
1804 :
1805 133 : bindings->varStart = cursor - start;
1806 133 : PodCopy(cursor, vars.begin(), vars.length());
1807 133 : cursor += vars.length();
1808 :
1809 133 : bindings->letStart = cursor - start;
1810 133 : PodCopy(cursor, lets.begin(), lets.length());
1811 133 : cursor += lets.length();
1812 :
1813 133 : bindings->constStart = cursor - start;
1814 133 : PodCopy(cursor, consts.begin(), consts.length());
1815 133 : bindings->length = numBindings;
1816 : }
1817 :
1818 266 : return Some(bindings);
1819 : }
1820 :
1821 : Maybe<ModuleScope::Data*>
1822 0 : ParserBase::newModuleScopeData(ParseContext::Scope& scope)
1823 : {
1824 0 : Vector<BindingName> imports(context);
1825 0 : Vector<BindingName> vars(context);
1826 0 : Vector<BindingName> lets(context);
1827 0 : Vector<BindingName> consts(context);
1828 :
1829 0 : bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
1830 0 : for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1831 : // Imports are indirect bindings and must not be given known slots.
1832 0 : BindingName binding(bi.name(), (allBindingsClosedOver || bi.closedOver()) &&
1833 0 : bi.kind() != BindingKind::Import);
1834 0 : switch (bi.kind()) {
1835 : case BindingKind::Import:
1836 0 : if (!imports.append(binding))
1837 0 : return Nothing();
1838 0 : break;
1839 : case BindingKind::Var:
1840 0 : if (!vars.append(binding))
1841 0 : return Nothing();
1842 0 : break;
1843 : case BindingKind::Let:
1844 0 : if (!lets.append(binding))
1845 0 : return Nothing();
1846 0 : break;
1847 : case BindingKind::Const:
1848 0 : if (!consts.append(binding))
1849 0 : return Nothing();
1850 0 : break;
1851 : default:
1852 0 : MOZ_CRASH("Bad module scope BindingKind");
1853 : }
1854 : }
1855 :
1856 0 : ModuleScope::Data* bindings = nullptr;
1857 0 : uint32_t numBindings = imports.length() + vars.length() + lets.length() + consts.length();
1858 :
1859 0 : if (numBindings > 0) {
1860 0 : bindings = NewEmptyBindingData<ModuleScope>(context, alloc, numBindings);
1861 0 : if (!bindings)
1862 0 : return Nothing();
1863 :
1864 : // The ordering here is important. See comments in ModuleScope.
1865 0 : BindingName* start = bindings->names;
1866 0 : BindingName* cursor = start;
1867 :
1868 0 : PodCopy(cursor, imports.begin(), imports.length());
1869 0 : cursor += imports.length();
1870 :
1871 0 : bindings->varStart = cursor - start;
1872 0 : PodCopy(cursor, vars.begin(), vars.length());
1873 0 : cursor += vars.length();
1874 :
1875 0 : bindings->letStart = cursor - start;
1876 0 : PodCopy(cursor, lets.begin(), lets.length());
1877 0 : cursor += lets.length();
1878 :
1879 0 : bindings->constStart = cursor - start;
1880 0 : PodCopy(cursor, consts.begin(), consts.length());
1881 0 : bindings->length = numBindings;
1882 : }
1883 :
1884 0 : return Some(bindings);
1885 : }
1886 :
1887 : Maybe<EvalScope::Data*>
1888 2 : ParserBase::newEvalScopeData(ParseContext::Scope& scope)
1889 : {
1890 4 : Vector<BindingName> funs(context);
1891 4 : Vector<BindingName> vars(context);
1892 :
1893 28 : for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1894 : // Eval scopes only contain 'var' bindings. Make all bindings aliased
1895 : // for now.
1896 26 : MOZ_ASSERT(bi.kind() == BindingKind::Var);
1897 26 : BindingName binding(bi.name(), true);
1898 26 : if (bi.declarationKind() == DeclarationKind::BodyLevelFunction) {
1899 12 : if (!funs.append(binding))
1900 0 : return Nothing();
1901 : } else {
1902 14 : if (!vars.append(binding))
1903 0 : return Nothing();
1904 : }
1905 : }
1906 :
1907 2 : EvalScope::Data* bindings = nullptr;
1908 2 : uint32_t numBindings = funs.length() + vars.length();
1909 :
1910 2 : if (numBindings > 0) {
1911 2 : bindings = NewEmptyBindingData<EvalScope>(context, alloc, numBindings);
1912 2 : if (!bindings)
1913 0 : return Nothing();
1914 :
1915 2 : BindingName* start = bindings->names;
1916 2 : BindingName* cursor = start;
1917 :
1918 : // Keep track of what vars are functions. This is only used in BCE to omit
1919 : // superfluous DEFVARs.
1920 2 : PodCopy(cursor, funs.begin(), funs.length());
1921 2 : cursor += funs.length();
1922 :
1923 2 : bindings->varStart = cursor - start;
1924 2 : PodCopy(cursor, vars.begin(), vars.length());
1925 2 : bindings->length = numBindings;
1926 : }
1927 :
1928 2 : return Some(bindings);
1929 : }
1930 :
1931 : Maybe<FunctionScope::Data*>
1932 5350 : ParserBase::newFunctionScopeData(ParseContext::Scope& scope, bool hasParameterExprs)
1933 : {
1934 10700 : Vector<BindingName> positionalFormals(context);
1935 10700 : Vector<BindingName> formals(context);
1936 10700 : Vector<BindingName> vars(context);
1937 :
1938 5350 : bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
1939 5350 : bool hasDuplicateParams = pc->functionBox()->hasDuplicateParameters;
1940 :
1941 : // Positional parameter names must be added in order of appearance as they are
1942 : // referenced using argument slots.
1943 11651 : for (size_t i = 0; i < pc->positionalFormalParameterNames().length(); i++) {
1944 6301 : JSAtom* name = pc->positionalFormalParameterNames()[i];
1945 :
1946 6301 : BindingName bindName;
1947 6301 : if (name) {
1948 6259 : DeclaredNamePtr p = scope.lookupDeclaredName(name);
1949 :
1950 : // Do not consider any positional formal parameters closed over if
1951 : // there are parameter defaults. It is the binding in the defaults
1952 : // scope that is closed over instead.
1953 12958 : bool closedOver = allBindingsClosedOver ||
1954 18637 : (p && p->value()->closedOver());
1955 :
1956 : // If the parameter name has duplicates, only the final parameter
1957 : // name should be on the environment, as otherwise the environment
1958 : // object would have multiple, same-named properties.
1959 6259 : if (hasDuplicateParams) {
1960 0 : for (size_t j = pc->positionalFormalParameterNames().length() - 1; j > i; j--) {
1961 0 : if (pc->positionalFormalParameterNames()[j] == name) {
1962 0 : closedOver = false;
1963 0 : break;
1964 : }
1965 : }
1966 : }
1967 :
1968 6259 : bindName = BindingName(name, closedOver);
1969 : }
1970 :
1971 6301 : if (!positionalFormals.append(bindName))
1972 0 : return Nothing();
1973 : }
1974 :
1975 20375 : for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1976 15025 : BindingName binding(bi.name(), allBindingsClosedOver || bi.closedOver());
1977 15025 : switch (bi.kind()) {
1978 : case BindingKind::FormalParameter:
1979 : // Positional parameter names are already handled above.
1980 6366 : if (bi.declarationKind() == DeclarationKind::FormalParameter) {
1981 107 : if (!formals.append(binding))
1982 0 : return Nothing();
1983 : }
1984 6366 : break;
1985 : case BindingKind::Var:
1986 : // The only vars in the function scope when there are parameter
1987 : // exprs, which induces a separate var environment, should be the
1988 : // special bindings.
1989 6455 : MOZ_ASSERT_IF(hasParameterExprs, FunctionScope::isSpecialName(context, bi.name()));
1990 6455 : if (!vars.append(binding))
1991 0 : return Nothing();
1992 6455 : break;
1993 : default:
1994 2204 : break;
1995 : }
1996 : }
1997 :
1998 5350 : FunctionScope::Data* bindings = nullptr;
1999 5350 : uint32_t numBindings = positionalFormals.length() + formals.length() + vars.length();
2000 :
2001 5350 : if (numBindings > 0) {
2002 4571 : bindings = NewEmptyBindingData<FunctionScope>(context, alloc, numBindings);
2003 4571 : if (!bindings)
2004 0 : return Nothing();
2005 :
2006 : // The ordering here is important. See comments in FunctionScope.
2007 4571 : BindingName* start = bindings->names;
2008 4571 : BindingName* cursor = start;
2009 :
2010 4571 : PodCopy(cursor, positionalFormals.begin(), positionalFormals.length());
2011 4571 : cursor += positionalFormals.length();
2012 :
2013 4571 : bindings->nonPositionalFormalStart = cursor - start;
2014 4571 : PodCopy(cursor, formals.begin(), formals.length());
2015 4571 : cursor += formals.length();
2016 :
2017 4571 : bindings->varStart = cursor - start;
2018 4571 : PodCopy(cursor, vars.begin(), vars.length());
2019 4571 : bindings->length = numBindings;
2020 : }
2021 :
2022 5350 : return Some(bindings);
2023 : }
2024 :
2025 : Maybe<VarScope::Data*>
2026 183 : ParserBase::newVarScopeData(ParseContext::Scope& scope)
2027 : {
2028 366 : Vector<BindingName> vars(context);
2029 :
2030 183 : bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
2031 :
2032 627 : for (BindingIter bi = scope.bindings(pc); bi; bi++) {
2033 444 : BindingName binding(bi.name(), allBindingsClosedOver || bi.closedOver());
2034 444 : if (!vars.append(binding))
2035 0 : return Nothing();
2036 : }
2037 :
2038 183 : VarScope::Data* bindings = nullptr;
2039 183 : uint32_t numBindings = vars.length();
2040 :
2041 183 : if (numBindings > 0) {
2042 104 : bindings = NewEmptyBindingData<VarScope>(context, alloc, numBindings);
2043 104 : if (!bindings)
2044 0 : return Nothing();
2045 :
2046 : // The ordering here is important. See comments in FunctionScope.
2047 104 : BindingName* start = bindings->names;
2048 104 : BindingName* cursor = start;
2049 :
2050 104 : PodCopy(cursor, vars.begin(), vars.length());
2051 104 : bindings->length = numBindings;
2052 : }
2053 :
2054 183 : return Some(bindings);
2055 : }
2056 :
2057 : Maybe<LexicalScope::Data*>
2058 13189 : ParserBase::newLexicalScopeData(ParseContext::Scope& scope)
2059 : {
2060 26378 : Vector<BindingName> lets(context);
2061 26378 : Vector<BindingName> consts(context);
2062 :
2063 : // Unlike other scopes with bindings which are body-level, it is unknown
2064 : // if pc->sc()->allBindingsClosedOver() is correct at the time of
2065 : // finishing parsing a lexical scope.
2066 : //
2067 : // Instead, pc->sc()->allBindingsClosedOver() is checked in
2068 : // EmitterScope::enterLexical. Also see comment there.
2069 30664 : for (BindingIter bi = scope.bindings(pc); bi; bi++) {
2070 17475 : BindingName binding(bi.name(), bi.closedOver());
2071 17475 : switch (bi.kind()) {
2072 : case BindingKind::Let:
2073 4194 : if (!lets.append(binding))
2074 0 : return Nothing();
2075 4194 : break;
2076 : case BindingKind::Const:
2077 740 : if (!consts.append(binding))
2078 0 : return Nothing();
2079 740 : break;
2080 : default:
2081 12541 : break;
2082 : }
2083 : }
2084 :
2085 13189 : LexicalScope::Data* bindings = nullptr;
2086 13189 : uint32_t numBindings = lets.length() + consts.length();
2087 :
2088 13189 : if (numBindings > 0) {
2089 3281 : bindings = NewEmptyBindingData<LexicalScope>(context, alloc, numBindings);
2090 3281 : if (!bindings)
2091 0 : return Nothing();
2092 :
2093 : // The ordering here is important. See comments in LexicalScope.
2094 3281 : BindingName* cursor = bindings->names;
2095 3281 : BindingName* start = cursor;
2096 :
2097 3281 : PodCopy(cursor, lets.begin(), lets.length());
2098 3281 : cursor += lets.length();
2099 :
2100 3281 : bindings->constStart = cursor - start;
2101 3281 : PodCopy(cursor, consts.begin(), consts.length());
2102 3281 : bindings->length = numBindings;
2103 : }
2104 :
2105 13189 : return Some(bindings);
2106 : }
2107 :
2108 : template <>
2109 : SyntaxParseHandler::Node
2110 4786 : Parser<SyntaxParseHandler, char16_t>::finishLexicalScope(ParseContext::Scope& scope, Node body)
2111 : {
2112 4786 : if (!propagateFreeNamesAndMarkClosedOverBindings(scope))
2113 0 : return null();
2114 4786 : return body;
2115 : }
2116 :
2117 : template <>
2118 : ParseNode*
2119 12798 : Parser<FullParseHandler, char16_t>::finishLexicalScope(ParseContext::Scope& scope, ParseNode* body)
2120 : {
2121 12798 : if (!propagateFreeNamesAndMarkClosedOverBindings(scope))
2122 0 : return nullptr;
2123 25596 : Maybe<LexicalScope::Data*> bindings = newLexicalScopeData(scope);
2124 12798 : if (!bindings)
2125 0 : return nullptr;
2126 12798 : return handler.newLexicalScope(*bindings, body);
2127 : }
2128 :
2129 : static bool
2130 0 : IsArgumentsUsedInLegacyGenerator(JSContext* cx, Scope* scope)
2131 : {
2132 0 : JSAtom* argumentsName = cx->names().arguments;
2133 0 : for (ScopeIter si(scope); si; si++) {
2134 0 : if (si.scope()->is<LexicalScope>()) {
2135 : // Using a shadowed lexical 'arguments' is okay.
2136 0 : for (::BindingIter bi(si.scope()); bi; bi++) {
2137 0 : if (bi.name() == argumentsName)
2138 0 : return false;
2139 : }
2140 0 : } else if (si.scope()->is<FunctionScope>()) {
2141 : // It's an error to use 'arguments' in a legacy generator expression.
2142 0 : JSScript* script = si.scope()->as<FunctionScope>().script();
2143 0 : return script->isGeneratorExp() && script->isLegacyGenerator();
2144 : }
2145 : }
2146 :
2147 0 : return false;
2148 : }
2149 :
2150 : template <>
2151 : ParseNode*
2152 2 : Parser<FullParseHandler, char16_t>::evalBody(EvalSharedContext* evalsc)
2153 : {
2154 4 : ParseContext evalpc(this, evalsc, /* newDirectives = */ nullptr);
2155 2 : if (!evalpc.init())
2156 0 : return nullptr;
2157 :
2158 4 : ParseContext::VarScope varScope(this);
2159 2 : if (!varScope.init(pc))
2160 0 : return nullptr;
2161 :
2162 : ParseNode* body;
2163 : {
2164 : // All evals have an implicit non-extensible lexical scope.
2165 4 : ParseContext::Scope lexicalScope(this);
2166 2 : if (!lexicalScope.init(pc))
2167 0 : return nullptr;
2168 :
2169 2 : body = statementList(YieldIsName);
2170 2 : if (!body)
2171 0 : return nullptr;
2172 :
2173 2 : if (!checkStatementsEOF())
2174 0 : return nullptr;
2175 :
2176 2 : body = finishLexicalScope(lexicalScope, body);
2177 2 : if (!body)
2178 0 : return nullptr;
2179 : }
2180 :
2181 : // It's an error to use 'arguments' in a legacy generator expression.
2182 : //
2183 : // If 'arguments' appears free (i.e. not a declared name) or if the
2184 : // declaration does not shadow the enclosing script's 'arguments'
2185 : // binding (i.e. not a lexical declaration), check the enclosing
2186 : // script.
2187 2 : if (hasUsedName(context->names().arguments)) {
2188 0 : if (IsArgumentsUsedInLegacyGenerator(context, pc->sc()->compilationEnclosingScope())) {
2189 0 : error(JSMSG_BAD_GENEXP_BODY, js_arguments_str);
2190 0 : return nullptr;
2191 : }
2192 : }
2193 :
2194 : #ifdef DEBUG
2195 2 : if (evalpc.superScopeNeedsHomeObject() && evalsc->compilationEnclosingScope()) {
2196 : // If superScopeNeedsHomeObject_ is set and we are an entry-point
2197 : // ParseContext, then we must be emitting an eval script, and the
2198 : // outer function must already be marked as needing a home object
2199 : // since it contains an eval.
2200 0 : ScopeIter si(evalsc->compilationEnclosingScope());
2201 0 : for (; si; si++) {
2202 0 : if (si.kind() == ScopeKind::Function) {
2203 0 : JSFunction* fun = si.scope()->as<FunctionScope>().canonicalFunction();
2204 0 : if (fun->isArrow())
2205 0 : continue;
2206 0 : MOZ_ASSERT(fun->allowSuperProperty());
2207 0 : MOZ_ASSERT(fun->nonLazyScript()->needsHomeObject());
2208 0 : break;
2209 : }
2210 : }
2211 0 : MOZ_ASSERT(!si.done(),
2212 : "Eval must have found an enclosing function box scope that allows super.property");
2213 : }
2214 : #endif
2215 :
2216 2 : if (!FoldConstants(context, &body, this))
2217 0 : return nullptr;
2218 :
2219 : // For eval scripts, since all bindings are automatically considered
2220 : // closed over, we don't need to call propagateFreeNamesAndMarkClosed-
2221 : // OverBindings. However, Annex B.3.3 functions still need to be marked.
2222 2 : if (!varScope.propagateAndMarkAnnexBFunctionBoxes(pc))
2223 0 : return nullptr;
2224 :
2225 4 : Maybe<EvalScope::Data*> bindings = newEvalScopeData(pc->varScope());
2226 2 : if (!bindings)
2227 0 : return nullptr;
2228 2 : evalsc->bindings = *bindings;
2229 :
2230 2 : return body;
2231 : }
2232 :
2233 : template <>
2234 : ParseNode*
2235 266 : Parser<FullParseHandler, char16_t>::globalBody(GlobalSharedContext* globalsc)
2236 : {
2237 532 : ParseContext globalpc(this, globalsc, /* newDirectives = */ nullptr);
2238 266 : if (!globalpc.init())
2239 0 : return nullptr;
2240 :
2241 532 : ParseContext::VarScope varScope(this);
2242 266 : if (!varScope.init(pc))
2243 0 : return nullptr;
2244 :
2245 266 : ParseNode* body = statementList(YieldIsName);
2246 266 : if (!body)
2247 0 : return nullptr;
2248 :
2249 266 : if (!checkStatementsEOF())
2250 0 : return nullptr;
2251 :
2252 266 : if (!FoldConstants(context, &body, this))
2253 0 : return nullptr;
2254 :
2255 : // For global scripts, whether bindings are closed over or not doesn't
2256 : // matter, so no need to call propagateFreeNamesAndMarkClosedOver-
2257 : // Bindings. However, Annex B.3.3 functions still need to be marked.
2258 266 : if (!varScope.propagateAndMarkAnnexBFunctionBoxes(pc))
2259 0 : return nullptr;
2260 :
2261 532 : Maybe<GlobalScope::Data*> bindings = newGlobalScopeData(pc->varScope());
2262 266 : if (!bindings)
2263 0 : return nullptr;
2264 266 : globalsc->bindings = *bindings;
2265 :
2266 266 : return body;
2267 : }
2268 :
2269 : template <>
2270 : ParseNode*
2271 0 : Parser<FullParseHandler, char16_t>::moduleBody(ModuleSharedContext* modulesc)
2272 : {
2273 0 : MOZ_ASSERT(checkOptionsCalled);
2274 :
2275 0 : ParseContext modulepc(this, modulesc, nullptr);
2276 0 : if (!modulepc.init())
2277 0 : return null();
2278 :
2279 0 : ParseContext::VarScope varScope(this);
2280 0 : if (!varScope.init(pc))
2281 0 : return nullptr;
2282 :
2283 0 : Node mn = handler.newModule(pos());
2284 0 : if (!mn)
2285 0 : return null();
2286 :
2287 0 : AutoAwaitIsKeyword<Parser> awaitIsKeyword(this, AwaitIsModuleKeyword);
2288 0 : ParseNode* pn = statementList(YieldIsKeyword);
2289 0 : if (!pn)
2290 0 : return null();
2291 :
2292 0 : MOZ_ASSERT(pn->isKind(PNK_STATEMENTLIST));
2293 0 : mn->pn_body = pn;
2294 :
2295 : TokenKind tt;
2296 0 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
2297 0 : return null();
2298 0 : if (tt != TOK_EOF) {
2299 0 : error(JSMSG_GARBAGE_AFTER_INPUT, "module", TokenKindToDesc(tt));
2300 0 : return null();
2301 : }
2302 :
2303 0 : if (!modulesc->builder.buildTables())
2304 0 : return null();
2305 :
2306 : // Check exported local bindings exist and mark them as closed over.
2307 0 : for (auto entry : modulesc->builder.localExportEntries()) {
2308 0 : JSAtom* name = entry->localName();
2309 0 : MOZ_ASSERT(name);
2310 :
2311 0 : DeclaredNamePtr p = modulepc.varScope().lookupDeclaredName(name);
2312 0 : if (!p) {
2313 0 : JSAutoByteString str;
2314 0 : if (!AtomToPrintableString(context, name, &str))
2315 0 : return null();
2316 :
2317 0 : JS_ReportErrorNumberLatin1(context, GetErrorMessage, nullptr,
2318 0 : JSMSG_MISSING_EXPORT, str.ptr());
2319 0 : return null();
2320 : }
2321 :
2322 0 : p->value()->setClosedOver();
2323 : }
2324 :
2325 0 : if (!FoldConstants(context, &pn, this))
2326 0 : return null();
2327 :
2328 0 : if (!propagateFreeNamesAndMarkClosedOverBindings(modulepc.varScope()))
2329 0 : return null();
2330 :
2331 0 : Maybe<ModuleScope::Data*> bindings = newModuleScopeData(modulepc.varScope());
2332 0 : if (!bindings)
2333 0 : return nullptr;
2334 :
2335 0 : modulesc->bindings = *bindings;
2336 0 : return mn;
2337 : }
2338 :
2339 : template <>
2340 : SyntaxParseHandler::Node
2341 0 : Parser<SyntaxParseHandler, char16_t>::moduleBody(ModuleSharedContext* modulesc)
2342 : {
2343 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
2344 0 : return SyntaxParseHandler::NodeFailure;
2345 : }
2346 :
2347 : template <class ParseHandler, typename CharT>
2348 : bool
2349 10272 : Parser<ParseHandler, CharT>::hasUsedFunctionSpecialName(HandlePropertyName name)
2350 : {
2351 10272 : MOZ_ASSERT(name == context->names().arguments || name == context->names().dotThis);
2352 10272 : return hasUsedName(name) || pc->functionBox()->bindingsAccessedDynamically();
2353 : }
2354 :
2355 : template <class ParseHandler, typename CharT>
2356 : bool
2357 6264 : Parser<ParseHandler, CharT>::declareFunctionThis()
2358 : {
2359 : // The asm.js validator does all its own symbol-table management so, as an
2360 : // optimization, avoid doing any work here.
2361 6264 : if (pc->useAsmOrInsideUseAsm())
2362 0 : return true;
2363 :
2364 : // Derived class constructors emit JSOP_CHECKRETURN, which requires
2365 : // '.this' to be bound.
2366 6264 : FunctionBox* funbox = pc->functionBox();
2367 6264 : HandlePropertyName dotThis = context->names().dotThis;
2368 :
2369 : bool declareThis;
2370 6264 : if (handler.canSkipLazyClosedOverBindings())
2371 1128 : declareThis = funbox->function()->lazyScript()->hasThisBinding();
2372 : else
2373 5136 : declareThis = hasUsedFunctionSpecialName(dotThis) || funbox->isDerivedClassConstructor();
2374 :
2375 6264 : if (declareThis) {
2376 3128 : ParseContext::Scope& funScope = pc->functionScope();
2377 3128 : AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotThis);
2378 3128 : MOZ_ASSERT(!p);
2379 3128 : if (!funScope.addDeclaredName(pc, p, dotThis, DeclarationKind::Var,
2380 : DeclaredNameInfo::npos))
2381 : {
2382 0 : return false;
2383 : }
2384 3128 : funbox->setHasThisBinding();
2385 : }
2386 :
2387 6264 : return true;
2388 : }
2389 :
2390 : template <class ParseHandler, typename CharT>
2391 : typename ParseHandler::Node
2392 10497 : Parser<ParseHandler, CharT>::newInternalDotName(HandlePropertyName name)
2393 : {
2394 10497 : Node nameNode = newName(name);
2395 10497 : if (!nameNode)
2396 0 : return null();
2397 10497 : if (!noteUsedName(name))
2398 0 : return null();
2399 10497 : return nameNode;
2400 : }
2401 :
2402 : template <class ParseHandler, typename CharT>
2403 : typename ParseHandler::Node
2404 10325 : Parser<ParseHandler, CharT>::newThisName()
2405 : {
2406 10325 : return newInternalDotName(context->names().dotThis);
2407 : }
2408 :
2409 : template <class ParseHandler, typename CharT>
2410 : typename ParseHandler::Node
2411 172 : Parser<ParseHandler, CharT>::newDotGeneratorName()
2412 : {
2413 172 : return newInternalDotName(context->names().dotGenerator);
2414 : }
2415 :
2416 : template <class ParseHandler, typename CharT>
2417 : bool
2418 172 : Parser<ParseHandler, CharT>::declareDotGeneratorName()
2419 : {
2420 : // The special '.generator' binding must be on the function scope, as
2421 : // generators expect to find it on the CallObject.
2422 172 : ParseContext::Scope& funScope = pc->functionScope();
2423 172 : HandlePropertyName dotGenerator = context->names().dotGenerator;
2424 172 : AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(dotGenerator);
2425 172 : if (!p && !funScope.addDeclaredName(pc, p, dotGenerator, DeclarationKind::Var,
2426 : DeclaredNameInfo::npos))
2427 : {
2428 0 : return false;
2429 : }
2430 172 : return true;
2431 : }
2432 :
2433 : template <class ParseHandler, typename CharT>
2434 : bool
2435 7373 : Parser<ParseHandler, CharT>::finishFunctionScopes(bool isStandaloneFunction)
2436 : {
2437 7373 : FunctionBox* funbox = pc->functionBox();
2438 :
2439 7373 : if (funbox->hasParameterExprs) {
2440 268 : if (!propagateFreeNamesAndMarkClosedOverBindings(pc->functionScope()))
2441 0 : return false;
2442 : }
2443 :
2444 7373 : if (funbox->function()->isNamedLambda() && !isStandaloneFunction) {
2445 710 : if (!propagateFreeNamesAndMarkClosedOverBindings(pc->namedLambdaScope()))
2446 0 : return false;
2447 : }
2448 :
2449 7373 : return true;
2450 : }
2451 :
2452 : template <>
2453 : bool
2454 5350 : Parser<FullParseHandler, char16_t>::finishFunction(bool isStandaloneFunction /* = false */)
2455 : {
2456 5350 : if (!finishFunctionScopes(isStandaloneFunction))
2457 0 : return false;
2458 :
2459 5350 : FunctionBox* funbox = pc->functionBox();
2460 5350 : bool hasParameterExprs = funbox->hasParameterExprs;
2461 :
2462 5350 : if (hasParameterExprs) {
2463 366 : Maybe<VarScope::Data*> bindings = newVarScopeData(pc->varScope());
2464 183 : if (!bindings)
2465 0 : return false;
2466 183 : funbox->extraVarScopeBindings().set(*bindings);
2467 : }
2468 :
2469 : {
2470 5350 : Maybe<FunctionScope::Data*> bindings = newFunctionScopeData(pc->functionScope(),
2471 16050 : hasParameterExprs);
2472 5350 : if (!bindings)
2473 0 : return false;
2474 5350 : funbox->functionScopeBindings().set(*bindings);
2475 : }
2476 :
2477 5350 : if (funbox->function()->isNamedLambda() && !isStandaloneFunction) {
2478 782 : Maybe<LexicalScope::Data*> bindings = newLexicalScopeData(pc->namedLambdaScope());
2479 391 : if (!bindings)
2480 0 : return false;
2481 391 : funbox->namedLambdaBindings().set(*bindings);
2482 : }
2483 :
2484 5350 : return true;
2485 : }
2486 :
2487 : template <>
2488 : bool
2489 2023 : Parser<SyntaxParseHandler, char16_t>::finishFunction(bool isStandaloneFunction /* = false */)
2490 : {
2491 : // The LazyScript for a lazily parsed function needs to know its set of
2492 : // free variables and inner functions so that when it is fully parsed, we
2493 : // can skip over any already syntax parsed inner functions and still
2494 : // retain correct scope information.
2495 :
2496 2023 : if (!finishFunctionScopes(isStandaloneFunction))
2497 0 : return false;
2498 :
2499 : // There are too many bindings or inner functions to be saved into the
2500 : // LazyScript. Do a full parse.
2501 4046 : if (pc->closedOverBindingsForLazy().length() >= LazyScript::NumClosedOverBindingsLimit ||
2502 2023 : pc->innerFunctionsForLazy.length() >= LazyScript::NumInnerFunctionsLimit)
2503 : {
2504 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
2505 0 : return false;
2506 : }
2507 :
2508 2023 : FunctionBox* funbox = pc->functionBox();
2509 4046 : RootedFunction fun(context, funbox->function());
2510 6069 : LazyScript* lazy = LazyScript::Create(context, fun, pc->closedOverBindingsForLazy(),
2511 2023 : pc->innerFunctionsForLazy, versionNumber(),
2512 : funbox->bufStart, funbox->bufEnd,
2513 : funbox->toStringStart,
2514 2023 : funbox->startLine, funbox->startColumn);
2515 2023 : if (!lazy)
2516 0 : return false;
2517 :
2518 : // Flags that need to be copied into the JSScript when we do the full
2519 : // parse.
2520 2023 : if (pc->sc()->strict())
2521 1652 : lazy->setStrict();
2522 2023 : lazy->setGeneratorKind(funbox->generatorKind());
2523 2023 : lazy->setAsyncKind(funbox->asyncKind());
2524 2023 : if (funbox->hasRest())
2525 11 : lazy->setHasRest();
2526 2023 : if (funbox->isExprBody())
2527 177 : lazy->setIsExprBody();
2528 2023 : if (funbox->isLikelyConstructorWrapper())
2529 0 : lazy->setLikelyConstructorWrapper();
2530 2023 : if (funbox->isDerivedClassConstructor())
2531 4 : lazy->setIsDerivedClassConstructor();
2532 2023 : if (funbox->needsHomeObject())
2533 0 : lazy->setNeedsHomeObject();
2534 2023 : if (funbox->declaredArguments)
2535 6 : lazy->setShouldDeclareArguments();
2536 2023 : if (funbox->hasThisBinding())
2537 924 : lazy->setHasThisBinding();
2538 :
2539 : // Flags that need to copied back into the parser when we do the full
2540 : // parse.
2541 2023 : PropagateTransitiveParseFlags(funbox, lazy);
2542 :
2543 2023 : fun->initLazyScript(lazy);
2544 2023 : return true;
2545 : }
2546 :
2547 : static YieldHandling
2548 13992 : GetYieldHandling(GeneratorKind generatorKind)
2549 : {
2550 13992 : if (generatorKind == NotGenerator)
2551 13950 : return YieldIsName;
2552 42 : return YieldIsKeyword;
2553 : }
2554 :
2555 : static AwaitHandling
2556 8577 : GetAwaitHandling(FunctionAsyncKind asyncKind)
2557 : {
2558 8577 : if (asyncKind == SyncFunction)
2559 8418 : return AwaitIsName;
2560 159 : return AwaitIsKeyword;
2561 : }
2562 :
2563 : template <>
2564 : ParseNode*
2565 15 : Parser<FullParseHandler, char16_t>::standaloneFunction(HandleFunction fun,
2566 : HandleScope enclosingScope,
2567 : const Maybe<uint32_t>& parameterListEnd,
2568 : GeneratorKind generatorKind,
2569 : FunctionAsyncKind asyncKind,
2570 : Directives inheritedDirectives,
2571 : Directives* newDirectives)
2572 : {
2573 15 : MOZ_ASSERT(checkOptionsCalled);
2574 :
2575 : // Skip prelude.
2576 : TokenKind tt;
2577 15 : if (!tokenStream.getToken(&tt))
2578 0 : return null();
2579 15 : if (asyncKind == AsyncFunction) {
2580 0 : MOZ_ASSERT(tt == TOK_ASYNC);
2581 0 : if (!tokenStream.getToken(&tt))
2582 0 : return null();
2583 : }
2584 15 : MOZ_ASSERT(tt == TOK_FUNCTION);
2585 :
2586 15 : if (!tokenStream.getToken(&tt))
2587 0 : return null();
2588 15 : if (generatorKind == StarGenerator) {
2589 0 : MOZ_ASSERT(tt == TOK_MUL);
2590 0 : if (!tokenStream.getToken(&tt))
2591 0 : return null();
2592 : }
2593 :
2594 : // Skip function name, if present.
2595 15 : if (TokenKindIsPossibleIdentifierName(tt)) {
2596 15 : MOZ_ASSERT(tokenStream.currentName() == fun->explicitName());
2597 : } else {
2598 0 : MOZ_ASSERT(fun->explicitName() == nullptr);
2599 0 : tokenStream.ungetToken();
2600 : }
2601 :
2602 15 : Node fn = handler.newFunctionStatement(pos());
2603 15 : if (!fn)
2604 0 : return null();
2605 :
2606 15 : ParseNode* argsbody = handler.newList(PNK_PARAMSBODY, pos());
2607 15 : if (!argsbody)
2608 0 : return null();
2609 15 : fn->pn_body = argsbody;
2610 :
2611 15 : FunctionBox* funbox = newFunctionBox(fn, fun, /* toStringStart = */ 0, inheritedDirectives,
2612 30 : generatorKind, asyncKind);
2613 15 : if (!funbox)
2614 0 : return null();
2615 15 : funbox->initStandaloneFunction(enclosingScope);
2616 :
2617 30 : ParseContext funpc(this, funbox, newDirectives);
2618 15 : if (!funpc.init())
2619 0 : return null();
2620 15 : funpc.setIsStandaloneFunctionBody();
2621 :
2622 15 : YieldHandling yieldHandling = GetYieldHandling(generatorKind);
2623 15 : AwaitHandling awaitHandling = GetAwaitHandling(asyncKind);
2624 30 : AutoAwaitIsKeyword<Parser> awaitIsKeyword(this, awaitHandling);
2625 15 : if (!functionFormalParametersAndBody(InAllowed, yieldHandling, fn, Statement,
2626 : parameterListEnd, /* isStandaloneFunction = */ true))
2627 : {
2628 0 : return null();
2629 : }
2630 :
2631 15 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
2632 0 : return null();
2633 15 : if (tt != TOK_EOF) {
2634 0 : error(JSMSG_GARBAGE_AFTER_INPUT, "function body", TokenKindToDesc(tt));
2635 0 : return null();
2636 : }
2637 :
2638 15 : if (!FoldConstants(context, &fn, this))
2639 0 : return null();
2640 :
2641 15 : return fn;
2642 : }
2643 :
2644 : template <class ParseHandler, typename CharT>
2645 : bool
2646 6264 : Parser<ParseHandler, CharT>::declareFunctionArgumentsObject()
2647 : {
2648 6264 : FunctionBox* funbox = pc->functionBox();
2649 6264 : ParseContext::Scope& funScope = pc->functionScope();
2650 6264 : ParseContext::Scope& varScope = pc->varScope();
2651 :
2652 6264 : bool hasExtraBodyVarScope = &funScope != &varScope;
2653 :
2654 : // Time to implement the odd semantics of 'arguments'.
2655 6264 : HandlePropertyName argumentsName = context->names().arguments;
2656 :
2657 : bool tryDeclareArguments;
2658 6264 : if (handler.canSkipLazyClosedOverBindings())
2659 1128 : tryDeclareArguments = funbox->function()->lazyScript()->shouldDeclareArguments();
2660 : else
2661 5136 : tryDeclareArguments = hasUsedFunctionSpecialName(argumentsName);
2662 :
2663 : // ES 9.2.12 steps 19 and 20 say formal parameters, lexical bindings,
2664 : // and body-level functions named 'arguments' shadow the arguments
2665 : // object.
2666 : //
2667 : // So even if there wasn't a free use of 'arguments' but there is a var
2668 : // binding of 'arguments', we still might need the arguments object.
2669 : //
2670 : // If we have an extra var scope due to parameter expressions and the body
2671 : // declared 'var arguments', we still need to declare 'arguments' in the
2672 : // function scope.
2673 6264 : DeclaredNamePtr p = varScope.lookupDeclaredName(argumentsName);
2674 6264 : if (p && (p->value()->kind() == DeclarationKind::Var ||
2675 0 : p->value()->kind() == DeclarationKind::ForOfVar))
2676 : {
2677 0 : if (hasExtraBodyVarScope)
2678 0 : tryDeclareArguments = true;
2679 : else
2680 0 : funbox->usesArguments = true;
2681 : }
2682 :
2683 6264 : if (tryDeclareArguments) {
2684 270 : AddDeclaredNamePtr p = funScope.lookupDeclaredNameForAdd(argumentsName);
2685 270 : if (!p) {
2686 270 : if (!funScope.addDeclaredName(pc, p, argumentsName, DeclarationKind::Var,
2687 : DeclaredNameInfo::npos))
2688 : {
2689 0 : return false;
2690 : }
2691 270 : funbox->declaredArguments = true;
2692 270 : funbox->usesArguments = true;
2693 0 : } else if (hasExtraBodyVarScope) {
2694 : // Formal parameters shadow the arguments object.
2695 0 : return true;
2696 : }
2697 : }
2698 :
2699 : // Compute if we need an arguments object.
2700 6264 : if (funbox->usesArguments) {
2701 : // There is an 'arguments' binding. Is the arguments object definitely
2702 : // needed?
2703 : //
2704 : // Also see the flags' comments in ContextFlags.
2705 270 : funbox->setArgumentsHasLocalBinding();
2706 :
2707 : // Dynamic scope access destroys all hope of optimization.
2708 270 : if (pc->sc()->bindingsAccessedDynamically())
2709 2 : funbox->setDefinitelyNeedsArgsObj();
2710 :
2711 : // If a script contains the debugger statement either directly or
2712 : // within an inner function, the arguments object should be created
2713 : // eagerly so the Debugger API may observe bindings.
2714 270 : if (pc->sc()->hasDebuggerStatement())
2715 0 : funbox->setDefinitelyNeedsArgsObj();
2716 : }
2717 :
2718 6264 : return true;
2719 : }
2720 :
2721 : template <class ParseHandler, typename CharT>
2722 : typename ParseHandler::Node
2723 7373 : Parser<ParseHandler, CharT>::functionBody(InHandling inHandling, YieldHandling yieldHandling,
2724 : FunctionSyntaxKind kind, FunctionBodyType type)
2725 : {
2726 7373 : MOZ_ASSERT(pc->isFunctionBox());
2727 7373 : MOZ_ASSERT(!pc->funHasReturnExpr && !pc->funHasReturnVoid);
2728 :
2729 : #ifdef DEBUG
2730 7373 : uint32_t startYieldOffset = pc->lastYieldOffset;
2731 : #endif
2732 :
2733 : Node pn;
2734 7373 : if (type == StatementListBody) {
2735 6848 : bool inheritedStrict = pc->sc()->strict();
2736 6848 : pn = statementList(yieldHandling);
2737 6848 : if (!pn)
2738 0 : return null();
2739 :
2740 : // When we transitioned from non-strict to strict mode, we need to
2741 : // validate that all parameter names are valid strict mode names.
2742 6848 : if (!inheritedStrict && pc->sc()->strict()) {
2743 5 : MOZ_ASSERT(pc->sc()->hasExplicitUseStrict(),
2744 : "strict mode should only change when a 'use strict' directive is present");
2745 5 : if (!hasValidSimpleStrictParameterNames()) {
2746 : // Request that this function be reparsed as strict to report
2747 : // the invalid parameter name at the correct source location.
2748 0 : pc->newDirectives->setStrict();
2749 0 : return null();
2750 : }
2751 : }
2752 : } else {
2753 525 : MOZ_ASSERT(type == ExpressionBody);
2754 :
2755 : // Async functions are implemented as star generators, and star
2756 : // generators are assumed to be statement lists, to prepend initial
2757 : // `yield`.
2758 525 : Node stmtList = null();
2759 525 : if (pc->isAsync()) {
2760 1 : stmtList = handler.newStatementList(pos());
2761 1 : if (!stmtList)
2762 0 : return null();
2763 : }
2764 :
2765 525 : Node kid = assignExpr(inHandling, yieldHandling, TripledotProhibited);
2766 525 : if (!kid)
2767 0 : return null();
2768 :
2769 525 : pn = handler.newExpressionBody(kid);
2770 525 : if (!pn)
2771 0 : return null();
2772 :
2773 525 : if (pc->isAsync()) {
2774 1 : handler.addStatementToList(stmtList, pn);
2775 1 : pn = stmtList;
2776 : }
2777 : }
2778 :
2779 7373 : switch (pc->generatorKind()) {
2780 : case NotGenerator:
2781 7352 : MOZ_ASSERT_IF(!pc->isAsync(), pc->lastYieldOffset == startYieldOffset);
2782 7352 : break;
2783 :
2784 : case LegacyGenerator:
2785 0 : MOZ_ASSERT(pc->lastYieldOffset != startYieldOffset);
2786 :
2787 : // These should throw while parsing the yield expression.
2788 0 : MOZ_ASSERT(kind != Arrow);
2789 0 : MOZ_ASSERT(!IsGetterKind(kind));
2790 0 : MOZ_ASSERT(!IsSetterKind(kind));
2791 0 : MOZ_ASSERT(!IsConstructorKind(kind));
2792 0 : MOZ_ASSERT(kind != Method);
2793 0 : MOZ_ASSERT(type != ExpressionBody);
2794 0 : break;
2795 :
2796 : case StarGenerator:
2797 21 : MOZ_ASSERT(kind != Arrow);
2798 21 : MOZ_ASSERT(type == StatementListBody);
2799 21 : break;
2800 : }
2801 :
2802 7373 : if (pc->needsDotGeneratorName()) {
2803 172 : MOZ_ASSERT_IF(!pc->isAsync(), type == StatementListBody);
2804 172 : if (!declareDotGeneratorName())
2805 0 : return null();
2806 172 : Node generator = newDotGeneratorName();
2807 172 : if (!generator)
2808 0 : return null();
2809 172 : if (!handler.prependInitialYield(pn, generator))
2810 0 : return null();
2811 : }
2812 :
2813 : // Declare the 'arguments' and 'this' bindings if necessary before
2814 : // finishing up the scope so these special bindings get marked as closed
2815 : // over if necessary. Arrow functions don't have these bindings.
2816 7373 : if (kind != Arrow) {
2817 6264 : if (!declareFunctionArgumentsObject())
2818 0 : return null();
2819 6264 : if (!declareFunctionThis())
2820 0 : return null();
2821 : }
2822 :
2823 7373 : return finishLexicalScope(pc->varScope(), pn);
2824 : }
2825 :
2826 : JSFunction*
2827 5951 : ParserBase::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
2828 : GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
2829 : HandleObject proto)
2830 : {
2831 5951 : MOZ_ASSERT_IF(kind == Statement, atom != nullptr);
2832 :
2833 11902 : RootedFunction fun(context);
2834 :
2835 5951 : gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
2836 : JSFunction::Flags flags;
2837 : #ifdef DEBUG
2838 5951 : bool isGlobalSelfHostedBuiltin = false;
2839 : #endif
2840 5951 : switch (kind) {
2841 : case Expression:
2842 2269 : flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
2843 2261 : ? JSFunction::INTERPRETED_LAMBDA
2844 : : JSFunction::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC);
2845 1139 : break;
2846 : case Arrow:
2847 830 : flags = JSFunction::INTERPRETED_LAMBDA_ARROW;
2848 830 : allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2849 830 : break;
2850 : case Method:
2851 1779 : MOZ_ASSERT(generatorKind == NotGenerator || generatorKind == StarGenerator);
2852 3552 : flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
2853 3478 : ? JSFunction::INTERPRETED_METHOD
2854 : : JSFunction::INTERPRETED_METHOD_GENERATOR_OR_ASYNC);
2855 1779 : allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2856 1779 : break;
2857 : case ClassConstructor:
2858 : case DerivedClassConstructor:
2859 31 : flags = JSFunction::INTERPRETED_CLASS_CONSTRUCTOR;
2860 31 : allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2861 31 : break;
2862 : case Getter:
2863 : case GetterNoExpressionClosure:
2864 307 : flags = JSFunction::INTERPRETED_GETTER;
2865 307 : allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2866 307 : break;
2867 : case Setter:
2868 : case SetterNoExpressionClosure:
2869 42 : flags = JSFunction::INTERPRETED_SETTER;
2870 42 : allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2871 42 : break;
2872 : default:
2873 1823 : MOZ_ASSERT(kind == Statement);
2874 : #ifdef DEBUG
2875 1823 : if (options().selfHostingMode && !pc->isFunctionBox()) {
2876 1299 : isGlobalSelfHostedBuiltin = true;
2877 1299 : allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2878 : }
2879 : #endif
2880 3646 : flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
2881 3640 : ? JSFunction::INTERPRETED_NORMAL
2882 : : JSFunction::INTERPRETED_GENERATOR_OR_ASYNC);
2883 : }
2884 :
2885 : // We store the async wrapper in a slot for later access.
2886 5951 : if (asyncKind == AsyncFunction)
2887 126 : allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2888 :
2889 11902 : fun = NewFunctionWithProto(context, nullptr, 0, flags, nullptr, atom, proto,
2890 5951 : allocKind, TenuredObject);
2891 5951 : if (!fun)
2892 0 : return nullptr;
2893 5951 : if (options().selfHostingMode) {
2894 1392 : fun->setIsSelfHostedBuiltin();
2895 : #ifdef DEBUG
2896 1392 : if (isGlobalSelfHostedBuiltin)
2897 1299 : fun->setExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT, BooleanValue(false));
2898 : #endif
2899 : }
2900 5951 : return fun;
2901 : }
2902 :
2903 : /*
2904 : * WARNING: Do not call this function directly.
2905 : * Call either matchOrInsertSemicolonAfterExpression or
2906 : * matchOrInsertSemicolonAfterNonExpression instead, depending on context.
2907 : */
2908 : template <class ParseHandler, typename CharT>
2909 : bool
2910 38146 : Parser<ParseHandler, CharT>::matchOrInsertSemicolonHelper(TokenStream::Modifier modifier)
2911 : {
2912 38146 : TokenKind tt = TOK_EOF;
2913 38146 : if (!tokenStream.peekTokenSameLine(&tt, modifier))
2914 0 : return false;
2915 38146 : if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
2916 : /*
2917 : * When current token is `await` and it's outside of async function,
2918 : * it's possibly intended to be an await expression.
2919 : *
2920 : * await f();
2921 : * ^
2922 : * |
2923 : * tried to insert semicolon here
2924 : *
2925 : * Detect this situation and throw an understandable error. Otherwise
2926 : * we'd throw a confusing "missing ; before statement" error.
2927 : */
2928 0 : if (!pc->isAsync() && tokenStream.currentToken().type == TOK_AWAIT) {
2929 0 : error(JSMSG_AWAIT_OUTSIDE_ASYNC);
2930 0 : return false;
2931 : }
2932 :
2933 : /* Advance the scanner for proper error location reporting. */
2934 0 : tokenStream.consumeKnownToken(tt, modifier);
2935 0 : error(JSMSG_SEMI_BEFORE_STMNT);
2936 0 : return false;
2937 : }
2938 : bool matched;
2939 38146 : if (!tokenStream.matchToken(&matched, TOK_SEMI, modifier))
2940 0 : return false;
2941 38146 : if (!matched && modifier == TokenStream::None)
2942 341 : tokenStream.addModifierException(TokenStream::OperandIsNone);
2943 38146 : return true;
2944 : }
2945 :
2946 : template <class ParseHandler, typename CharT>
2947 : bool
2948 36559 : Parser<ParseHandler, CharT>::matchOrInsertSemicolonAfterExpression()
2949 : {
2950 36559 : return matchOrInsertSemicolonHelper(TokenStream::None);
2951 : }
2952 :
2953 : template <class ParseHandler, typename CharT>
2954 : bool
2955 1587 : Parser<ParseHandler, CharT>::matchOrInsertSemicolonAfterNonExpression()
2956 : {
2957 1587 : return matchOrInsertSemicolonHelper(TokenStream::Operand);
2958 : }
2959 :
2960 : template <class ParseHandler, typename CharT>
2961 : bool
2962 5951 : Parser<ParseHandler, CharT>::leaveInnerFunction(ParseContext* outerpc)
2963 : {
2964 5951 : MOZ_ASSERT(pc != outerpc);
2965 :
2966 : // If the current function allows super.property but cannot have a home
2967 : // object, i.e., it is an arrow function, we need to propagate the flag to
2968 : // the outer ParseContext.
2969 5951 : if (pc->superScopeNeedsHomeObject()) {
2970 7 : if (!pc->isArrowFunction())
2971 7 : MOZ_ASSERT(pc->functionBox()->needsHomeObject());
2972 : else
2973 0 : outerpc->setSuperScopeNeedsHomeObject();
2974 : }
2975 :
2976 : // Lazy functions inner to another lazy function need to be remembered by
2977 : // the inner function so that if the outer function is eventually parsed
2978 : // we do not need any further parsing or processing of the inner function.
2979 : //
2980 : // Append the inner function here unconditionally; the vector is only used
2981 : // if the Parser using outerpc is a syntax parsing. See
2982 : // Parser<SyntaxParseHandler>::finishFunction.
2983 5951 : if (!outerpc->innerFunctionsForLazy.append(pc->functionBox()->function()))
2984 0 : return false;
2985 :
2986 5951 : PropagateTransitiveParseFlags(pc->functionBox(), outerpc->sc());
2987 :
2988 5951 : return true;
2989 : }
2990 :
2991 : template <class ParseHandler, typename CharT>
2992 : JSAtom*
2993 355 : Parser<ParseHandler, CharT>::prefixAccessorName(PropertyType propType, HandleAtom propAtom)
2994 : {
2995 710 : RootedAtom prefix(context);
2996 355 : if (propType == PropertyType::Setter || propType == PropertyType::SetterNoExpressionClosure) {
2997 42 : prefix = context->names().setPrefix;
2998 : } else {
2999 313 : MOZ_ASSERT(propType == PropertyType::Getter || propType == PropertyType::GetterNoExpressionClosure);
3000 313 : prefix = context->names().getPrefix;
3001 : }
3002 :
3003 710 : RootedString str(context, ConcatStrings<CanGC>(context, prefix, propAtom));
3004 355 : if (!str)
3005 0 : return nullptr;
3006 :
3007 355 : return AtomizeString(context, str);
3008 : }
3009 :
3010 : template <class ParseHandler, typename CharT>
3011 : bool
3012 7373 : Parser<ParseHandler, CharT>::functionArguments(YieldHandling yieldHandling,
3013 : FunctionSyntaxKind kind,
3014 : Node funcpn)
3015 : {
3016 7373 : FunctionBox* funbox = pc->functionBox();
3017 :
3018 7373 : bool parenFreeArrow = false;
3019 : // Modifier for the following tokens.
3020 : // TokenStream::None for the following cases:
3021 : // async a => 1
3022 : // ^
3023 : //
3024 : // (a) => 1
3025 : // ^
3026 : //
3027 : // async (a) => 1
3028 : // ^
3029 : //
3030 : // function f(a) {}
3031 : // ^
3032 : //
3033 : // TokenStream::Operand for the following case:
3034 : // a => 1
3035 : // ^
3036 7373 : TokenStream::Modifier firstTokenModifier = TokenStream::None;
3037 :
3038 : // Modifier for the the first token in each argument.
3039 : // can be changed to TokenStream::None for the following case:
3040 : // async a => 1
3041 : // ^
3042 7373 : TokenStream::Modifier argModifier = TokenStream::Operand;
3043 7373 : if (kind == Arrow) {
3044 : TokenKind tt;
3045 : // In async function, the first token after `async` is already gotten
3046 : // with TokenStream::None.
3047 : // In sync function, the first token is already gotten with
3048 : // TokenStream::Operand.
3049 1109 : firstTokenModifier = funbox->isAsync() ? TokenStream::None : TokenStream::Operand;
3050 1109 : if (!tokenStream.peekToken(&tt, firstTokenModifier))
3051 0 : return false;
3052 1109 : if (TokenKindIsPossibleIdentifier(tt)) {
3053 388 : parenFreeArrow = true;
3054 388 : argModifier = firstTokenModifier;
3055 : }
3056 : }
3057 7373 : if (!parenFreeArrow) {
3058 : TokenKind tt;
3059 6985 : if (!tokenStream.getToken(&tt, firstTokenModifier))
3060 0 : return false;
3061 6985 : if (tt != TOK_LP) {
3062 0 : error(kind == Arrow ? JSMSG_BAD_ARROW_ARGS : JSMSG_PAREN_BEFORE_FORMAL);
3063 0 : return false;
3064 : }
3065 :
3066 : // Record the start of function source (for FunctionToString). If we
3067 : // are parenFreeArrow, we will set this below, after consuming the NAME.
3068 6985 : funbox->setStart(tokenStream);
3069 : }
3070 :
3071 7373 : Node argsbody = handler.newList(PNK_PARAMSBODY, pos());
3072 7373 : if (!argsbody)
3073 0 : return false;
3074 7373 : handler.setFunctionFormalParametersAndBody(funcpn, argsbody);
3075 :
3076 7373 : bool hasArguments = false;
3077 7373 : if (parenFreeArrow) {
3078 388 : hasArguments = true;
3079 : } else {
3080 : bool matched;
3081 6985 : if (!tokenStream.matchToken(&matched, TOK_RP, TokenStream::Operand))
3082 0 : return false;
3083 6985 : if (!matched)
3084 4503 : hasArguments = true;
3085 : }
3086 7373 : if (hasArguments) {
3087 4891 : bool hasRest = false;
3088 4891 : bool hasDefault = false;
3089 4891 : bool duplicatedParam = false;
3090 4891 : bool disallowDuplicateParams = kind == Arrow || kind == Method || kind == ClassConstructor;
3091 4891 : AtomVector& positionalFormals = pc->positionalFormalParameterNames();
3092 :
3093 4891 : if (IsGetterKind(kind)) {
3094 0 : error(JSMSG_ACCESSOR_WRONG_ARGS, "getter", "no", "s");
3095 0 : return false;
3096 : }
3097 :
3098 3525 : while (true) {
3099 8416 : if (hasRest) {
3100 0 : error(JSMSG_PARAMETER_AFTER_REST);
3101 0 : return false;
3102 : }
3103 :
3104 : TokenKind tt;
3105 8416 : if (!tokenStream.getToken(&tt, argModifier))
3106 0 : return false;
3107 8416 : argModifier = TokenStream::Operand;
3108 8416 : MOZ_ASSERT_IF(parenFreeArrow, TokenKindIsPossibleIdentifier(tt));
3109 :
3110 8416 : if (tt == TOK_TRIPLEDOT) {
3111 73 : if (IsSetterKind(kind)) {
3112 0 : error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", "");
3113 0 : return false;
3114 : }
3115 :
3116 73 : disallowDuplicateParams = true;
3117 73 : if (duplicatedParam) {
3118 : // Has duplicated args before the rest parameter.
3119 0 : error(JSMSG_BAD_DUP_ARGS);
3120 0 : return false;
3121 : }
3122 :
3123 73 : hasRest = true;
3124 73 : funbox->setHasRest();
3125 :
3126 73 : if (!tokenStream.getToken(&tt))
3127 0 : return false;
3128 :
3129 73 : if (!TokenKindIsPossibleIdentifier(tt) && tt != TOK_LB && tt != TOK_LC) {
3130 0 : error(JSMSG_NO_REST_NAME);
3131 0 : return false;
3132 : }
3133 : }
3134 :
3135 8416 : switch (tt) {
3136 : case TOK_LB:
3137 : case TOK_LC: {
3138 78 : disallowDuplicateParams = true;
3139 78 : if (duplicatedParam) {
3140 : // Has duplicated args before the destructuring parameter.
3141 0 : error(JSMSG_BAD_DUP_ARGS);
3142 0 : return false;
3143 : }
3144 :
3145 78 : funbox->hasDestructuringArgs = true;
3146 :
3147 78 : Node destruct = destructuringDeclarationWithoutYieldOrAwait(
3148 : DeclarationKind::FormalParameter,
3149 78 : yieldHandling, tt);
3150 78 : if (!destruct)
3151 0 : return false;
3152 :
3153 78 : if (!noteDestructuredPositionalFormalParameter(funcpn, destruct))
3154 0 : return false;
3155 :
3156 78 : break;
3157 : }
3158 :
3159 : default: {
3160 8338 : if (!TokenKindIsPossibleIdentifier(tt)) {
3161 0 : error(JSMSG_MISSING_FORMAL);
3162 0 : return false;
3163 : }
3164 :
3165 8338 : if (parenFreeArrow)
3166 388 : funbox->setStart(tokenStream);
3167 :
3168 8338 : RootedPropertyName name(context, bindingIdentifier(yieldHandling));
3169 8338 : if (!name)
3170 0 : return false;
3171 :
3172 8338 : if (!notePositionalFormalParameter(funcpn, name, pos().begin,
3173 : disallowDuplicateParams, &duplicatedParam))
3174 : {
3175 0 : return false;
3176 : }
3177 8338 : if (duplicatedParam)
3178 0 : funbox->hasDuplicateParameters = true;
3179 :
3180 8338 : break;
3181 : }
3182 : }
3183 :
3184 8416 : if (positionalFormals.length() >= ARGNO_LIMIT) {
3185 0 : error(JSMSG_TOO_MANY_FUN_ARGS);
3186 0 : return false;
3187 : }
3188 :
3189 : bool matched;
3190 8416 : if (!tokenStream.matchToken(&matched, TOK_ASSIGN))
3191 0 : return false;
3192 8416 : if (matched) {
3193 : // A default argument without parentheses would look like:
3194 : // a = expr => body, but both operators are right-associative, so
3195 : // that would have been parsed as a = (expr => body) instead.
3196 : // Therefore it's impossible to get here with parenFreeArrow.
3197 307 : MOZ_ASSERT(!parenFreeArrow);
3198 :
3199 307 : if (hasRest) {
3200 0 : error(JSMSG_REST_WITH_DEFAULT);
3201 0 : return false;
3202 : }
3203 307 : disallowDuplicateParams = true;
3204 307 : if (duplicatedParam) {
3205 0 : error(JSMSG_BAD_DUP_ARGS);
3206 0 : return false;
3207 : }
3208 :
3209 307 : if (!hasDefault) {
3210 261 : hasDefault = true;
3211 :
3212 : // The Function.length property is the number of formals
3213 : // before the first default argument.
3214 261 : funbox->length = positionalFormals.length() - 1;
3215 : }
3216 307 : funbox->hasParameterExprs = true;
3217 :
3218 307 : Node def_expr = assignExprWithoutYieldOrAwait(yieldHandling);
3219 307 : if (!def_expr)
3220 0 : return false;
3221 307 : if (!handler.setLastFunctionFormalParameterDefault(funcpn, def_expr))
3222 0 : return false;
3223 : }
3224 :
3225 8416 : if (parenFreeArrow || IsSetterKind(kind))
3226 5326 : break;
3227 :
3228 7981 : if (!tokenStream.matchToken(&matched, TOK_COMMA))
3229 0 : return false;
3230 7981 : if (!matched)
3231 4456 : break;
3232 :
3233 3525 : if (!hasRest) {
3234 3525 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
3235 0 : return null();
3236 3525 : if (tt == TOK_RP) {
3237 0 : tokenStream.addModifierException(TokenStream::NoneIsOperand);
3238 0 : break;
3239 : }
3240 : }
3241 : }
3242 :
3243 4891 : if (!parenFreeArrow) {
3244 : TokenKind tt;
3245 4503 : if (!tokenStream.getToken(&tt))
3246 0 : return false;
3247 4503 : if (tt != TOK_RP) {
3248 0 : if (IsSetterKind(kind)) {
3249 0 : error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", "");
3250 0 : return false;
3251 : }
3252 :
3253 0 : error(JSMSG_PAREN_AFTER_FORMAL);
3254 0 : return false;
3255 : }
3256 : }
3257 :
3258 4891 : if (!hasDefault)
3259 4630 : funbox->length = positionalFormals.length() - hasRest;
3260 :
3261 4891 : if (funbox->hasParameterExprs && funbox->hasDirectEval())
3262 0 : funbox->hasDirectEvalInParameterExpr = true;
3263 :
3264 4891 : funbox->function()->setArgCount(positionalFormals.length());
3265 2482 : } else if (IsSetterKind(kind)) {
3266 0 : error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", "");
3267 0 : return false;
3268 : }
3269 :
3270 7373 : return true;
3271 : }
3272 :
3273 : template <>
3274 : bool
3275 260 : Parser<FullParseHandler, char16_t>::skipLazyInnerFunction(ParseNode* pn, uint32_t toStringStart,
3276 : FunctionSyntaxKind kind, bool tryAnnexB)
3277 : {
3278 : // When a lazily-parsed function is called, we only fully parse (and emit)
3279 : // that function, not any of its nested children. The initial syntax-only
3280 : // parse recorded the free variables of nested functions and their extents,
3281 : // so we can skip over them after accounting for their free variables.
3282 :
3283 520 : RootedFunction fun(context, handler.nextLazyInnerFunction());
3284 260 : MOZ_ASSERT(!fun->isLegacyGenerator());
3285 1040 : FunctionBox* funbox = newFunctionBox(pn, fun, toStringStart, Directives(/* strict = */ false),
3286 1040 : fun->generatorKind(), fun->asyncKind());
3287 260 : if (!funbox)
3288 0 : return false;
3289 :
3290 260 : LazyScript* lazy = fun->lazyScript();
3291 260 : if (lazy->needsHomeObject())
3292 0 : funbox->setNeedsHomeObject();
3293 260 : if (lazy->isExprBody())
3294 84 : funbox->setIsExprBody();
3295 :
3296 260 : PropagateTransitiveParseFlags(lazy, pc->sc());
3297 :
3298 : // The position passed to tokenStream.advance() is an offset of the sort
3299 : // returned by userbuf.offset() and expected by userbuf.rawCharPtrAt(),
3300 : // while LazyScript::{begin,end} offsets are relative to the outermost
3301 : // script source.
3302 520 : Rooted<LazyScript*> lazyOuter(context, handler.lazyOuterFunction());
3303 260 : uint32_t userbufBase = lazyOuter->begin() - lazyOuter->column();
3304 260 : if (!tokenStream.advance(fun->lazyScript()->end() - userbufBase))
3305 0 : return false;
3306 :
3307 : #if JS_HAS_EXPR_CLOSURES
3308 : // Only expression closure can be Statement kind.
3309 : // If we remove expression closure, we can remove isExprBody flag from
3310 : // LazyScript and JSScript.
3311 260 : if (kind == Statement && funbox->isExprBody()) {
3312 0 : if (!matchOrInsertSemicolonAfterExpression())
3313 0 : return false;
3314 : }
3315 : #endif
3316 :
3317 : // Append possible Annex B function box only upon successfully parsing.
3318 260 : if (tryAnnexB && !pc->innermostScope()->addPossibleAnnexBFunctionBox(pc, funbox))
3319 0 : return false;
3320 :
3321 260 : return true;
3322 : }
3323 :
3324 : template <>
3325 : bool
3326 0 : Parser<SyntaxParseHandler, char16_t>::skipLazyInnerFunction(Node pn, uint32_t toStringStart,
3327 : FunctionSyntaxKind kind,
3328 : bool tryAnnexB)
3329 : {
3330 0 : MOZ_CRASH("Cannot skip lazy inner functions when syntax parsing");
3331 : }
3332 :
3333 : template <class ParseHandler, typename CharT>
3334 : bool
3335 665 : Parser<ParseHandler, CharT>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling,
3336 : Node nodeList,
3337 : TokenKind* ttp)
3338 : {
3339 665 : Node pn = expr(InAllowed, yieldHandling, TripledotProhibited);
3340 665 : if (!pn)
3341 0 : return false;
3342 665 : handler.addList(nodeList, pn);
3343 :
3344 : TokenKind tt;
3345 665 : if (!tokenStream.getToken(&tt))
3346 0 : return false;
3347 665 : if (tt != TOK_RC) {
3348 0 : error(JSMSG_TEMPLSTR_UNTERM_EXPR);
3349 0 : return false;
3350 : }
3351 :
3352 665 : return tokenStream.getToken(ttp, TokenStream::TemplateTail);
3353 : }
3354 :
3355 : template <class ParseHandler, typename CharT>
3356 : bool
3357 1 : Parser<ParseHandler, CharT>::taggedTemplate(YieldHandling yieldHandling, Node nodeList,
3358 : TokenKind tt)
3359 : {
3360 1 : Node callSiteObjNode = handler.newCallSiteObject(pos().begin);
3361 1 : if (!callSiteObjNode)
3362 0 : return false;
3363 1 : handler.addList(nodeList, callSiteObjNode);
3364 :
3365 : while (true) {
3366 5 : if (!appendToCallSiteObj(callSiteObjNode))
3367 0 : return false;
3368 3 : if (tt != TOK_TEMPLATE_HEAD)
3369 1 : break;
3370 :
3371 2 : if (!addExprAndGetNextTemplStrToken(yieldHandling, nodeList, &tt))
3372 0 : return false;
3373 : }
3374 1 : handler.setEndPosition(nodeList, callSiteObjNode);
3375 1 : return true;
3376 : }
3377 :
3378 : template <class ParseHandler, typename CharT>
3379 : typename ParseHandler::Node
3380 292 : Parser<ParseHandler, CharT>::templateLiteral(YieldHandling yieldHandling)
3381 : {
3382 292 : Node pn = noSubstitutionUntaggedTemplate();
3383 292 : if (!pn)
3384 0 : return null();
3385 :
3386 292 : Node nodeList = handler.newList(PNK_TEMPLATE_STRING_LIST, pn);
3387 292 : if (!nodeList)
3388 0 : return null();
3389 :
3390 : TokenKind tt;
3391 371 : do {
3392 663 : if (!addExprAndGetNextTemplStrToken(yieldHandling, nodeList, &tt))
3393 0 : return null();
3394 :
3395 663 : pn = noSubstitutionUntaggedTemplate();
3396 663 : if (!pn)
3397 0 : return null();
3398 :
3399 663 : handler.addList(nodeList, pn);
3400 663 : } while (tt == TOK_TEMPLATE_HEAD);
3401 292 : return nodeList;
3402 : }
3403 :
3404 : template <class ParseHandler, typename CharT>
3405 : typename ParseHandler::Node
3406 6211 : Parser<ParseHandler, CharT>::functionDefinition(Node pn, uint32_t toStringStart,
3407 : InHandling inHandling,
3408 : YieldHandling yieldHandling, HandleAtom funName,
3409 : FunctionSyntaxKind kind,
3410 : GeneratorKind generatorKind,
3411 : FunctionAsyncKind asyncKind,
3412 : bool tryAnnexB /* = false */)
3413 : {
3414 6211 : MOZ_ASSERT_IF(kind == Statement, funName);
3415 :
3416 : // When fully parsing a LazyScript, we do not fully reparse its inner
3417 : // functions, which are also lazy. Instead, their free variables and
3418 : // source extents are recorded and may be skipped.
3419 6211 : if (handler.canSkipLazyInnerFunctions()) {
3420 260 : if (!skipLazyInnerFunction(pn, toStringStart, kind, tryAnnexB))
3421 0 : return null();
3422 260 : return pn;
3423 : }
3424 :
3425 11902 : RootedObject proto(context);
3426 5951 : if (generatorKind == StarGenerator || asyncKind == AsyncFunction) {
3427 : // If we are off thread, the generator meta-objects have
3428 : // already been created by js::StartOffThreadParseTask, so cx will not
3429 : // be necessary.
3430 141 : JSContext* cx = context->helperThread() ? nullptr : context;
3431 141 : proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, context->global());
3432 141 : if (!proto)
3433 0 : return null();
3434 : }
3435 11902 : RootedFunction fun(context, newFunction(funName, kind, generatorKind, asyncKind, proto));
3436 5951 : if (!fun)
3437 0 : return null();
3438 :
3439 : // Speculatively parse using the directives of the parent parsing context.
3440 : // If a directive is encountered (e.g., "use strict") that changes how the
3441 : // function should have been parsed, we backup and reparse with the new set
3442 : // of directives.
3443 5951 : Directives directives(pc);
3444 5951 : Directives newDirectives = directives;
3445 :
3446 5951 : TokenStream::Position start(keepAtoms);
3447 5951 : tokenStream.tell(&start);
3448 :
3449 : // Parse the inner function. The following is a loop as we may attempt to
3450 : // reparse a function due to failed syntax parsing and encountering new
3451 : // "use foo" directives.
3452 : while (true) {
3453 5951 : if (trySyntaxParseInnerFunction(pn, fun, toStringStart, inHandling, yieldHandling, kind,
3454 : generatorKind, asyncKind, tryAnnexB, directives,
3455 : &newDirectives))
3456 : {
3457 5951 : break;
3458 : }
3459 :
3460 : // Return on error.
3461 0 : if (tokenStream.hadError() || directives == newDirectives)
3462 0 : return null();
3463 :
3464 : // Assignment must be monotonic to prevent infinitely attempting to
3465 : // reparse.
3466 0 : MOZ_ASSERT_IF(directives.strict(), newDirectives.strict());
3467 0 : MOZ_ASSERT_IF(directives.asmJS(), newDirectives.asmJS());
3468 0 : directives = newDirectives;
3469 :
3470 0 : tokenStream.seek(start);
3471 :
3472 : // functionFormalParametersAndBody may have already set pn->pn_body before failing.
3473 0 : handler.setFunctionFormalParametersAndBody(pn, null());
3474 : }
3475 :
3476 5951 : return pn;
3477 : }
3478 :
3479 : template <>
3480 : bool
3481 5479 : Parser<FullParseHandler, char16_t>::trySyntaxParseInnerFunction(ParseNode* pn, HandleFunction fun,
3482 : uint32_t toStringStart,
3483 : InHandling inHandling,
3484 : YieldHandling yieldHandling,
3485 : FunctionSyntaxKind kind,
3486 : GeneratorKind generatorKind,
3487 : FunctionAsyncKind asyncKind,
3488 : bool tryAnnexB,
3489 : Directives inheritedDirectives,
3490 : Directives* newDirectives)
3491 : {
3492 : // Try a syntax parse for this inner function.
3493 : do {
3494 : // If we're assuming this function is an IIFE, always perform a full
3495 : // parse to avoid the overhead of a lazy syntax-only parse. Although
3496 : // the prediction may be incorrect, IIFEs are common enough that it
3497 : // pays off for lots of code.
3498 5479 : if (pn->isLikelyIIFE() && generatorKind == NotGenerator && asyncKind == SyncFunction)
3499 3954 : break;
3500 :
3501 5453 : if (!syntaxParser_)
3502 3902 : break;
3503 :
3504 1551 : UsedNameTracker::RewindToken token = usedNames.getRewindToken();
3505 :
3506 : // Move the syntax parser to the current position in the stream.
3507 1551 : TokenStream::Position position(keepAtoms);
3508 1551 : tokenStream.tell(&position);
3509 1551 : if (!syntaxParser_->tokenStream.seek(position, tokenStream))
3510 1551 : return false;
3511 :
3512 : // Make a FunctionBox before we enter the syntax parser, because |pn|
3513 : // still expects a FunctionBox to be attached to it during BCE, and
3514 : // the syntax parser cannot attach one to it.
3515 1551 : FunctionBox* funbox = newFunctionBox(pn, fun, toStringStart, inheritedDirectives,
3516 3102 : generatorKind, asyncKind);
3517 1551 : if (!funbox)
3518 0 : return false;
3519 1551 : funbox->initWithEnclosingParseContext(pc, kind);
3520 :
3521 1551 : if (!syntaxParser_->innerFunction(SyntaxParseHandler::NodeGeneric,
3522 : pc, funbox, toStringStart,
3523 : inHandling, yieldHandling, kind,
3524 : inheritedDirectives, newDirectives))
3525 : {
3526 0 : if (syntaxParser_->hadAbortedSyntaxParse()) {
3527 : // Try again with a full parse. UsedNameTracker needs to be
3528 : // rewound to just before we tried the syntax parse for
3529 : // correctness.
3530 0 : syntaxParser_->clearAbortedSyntaxParse();
3531 0 : usedNames.rewind(token);
3532 0 : MOZ_ASSERT_IF(!syntaxParser_->context->helperThread(),
3533 : !syntaxParser_->context->isExceptionPending());
3534 0 : break;
3535 : }
3536 0 : return false;
3537 : }
3538 :
3539 : // Advance this parser over tokens processed by the syntax parser.
3540 1551 : syntaxParser_->tokenStream.tell(&position);
3541 1551 : if (!tokenStream.seek(position, syntaxParser_->tokenStream))
3542 0 : return false;
3543 :
3544 : // Update the end position of the parse node.
3545 1551 : pn->pn_pos.end = tokenStream.currentToken().pos.end;
3546 :
3547 : // Append possible Annex B function box only upon successfully parsing.
3548 1551 : if (tryAnnexB && !pc->innermostScope()->addPossibleAnnexBFunctionBox(pc, funbox))
3549 0 : return false;
3550 :
3551 1551 : return true;
3552 : } while (false);
3553 :
3554 : // We failed to do a syntax parse above, so do the full parse.
3555 3928 : return innerFunction(pn, pc, fun, toStringStart, inHandling, yieldHandling, kind,
3556 3928 : generatorKind, asyncKind, tryAnnexB, inheritedDirectives, newDirectives);
3557 : }
3558 :
3559 : template <>
3560 : bool
3561 472 : Parser<SyntaxParseHandler, char16_t>::trySyntaxParseInnerFunction(Node pn, HandleFunction fun,
3562 : uint32_t toStringStart,
3563 : InHandling inHandling,
3564 : YieldHandling yieldHandling,
3565 : FunctionSyntaxKind kind,
3566 : GeneratorKind generatorKind,
3567 : FunctionAsyncKind asyncKind,
3568 : bool tryAnnexB,
3569 : Directives inheritedDirectives,
3570 : Directives* newDirectives)
3571 : {
3572 : // This is already a syntax parser, so just parse the inner function.
3573 472 : return innerFunction(pn, pc, fun, toStringStart, inHandling, yieldHandling, kind,
3574 472 : generatorKind, asyncKind, tryAnnexB, inheritedDirectives, newDirectives);
3575 : }
3576 :
3577 : template <class ParseHandler, typename CharT>
3578 : bool
3579 5951 : Parser<ParseHandler, CharT>::innerFunction(Node pn, ParseContext* outerpc, FunctionBox* funbox,
3580 : uint32_t toStringStart,
3581 : InHandling inHandling, YieldHandling yieldHandling,
3582 : FunctionSyntaxKind kind, Directives inheritedDirectives,
3583 : Directives* newDirectives)
3584 : {
3585 : // Note that it is possible for outerpc != this->pc, as we may be
3586 : // attempting to syntax parse an inner function from an outer full
3587 : // parser. In that case, outerpc is a ParseContext from the full parser
3588 : // instead of the current top of the stack of the syntax parser.
3589 :
3590 : // Push a new ParseContext.
3591 11902 : ParseContext funpc(this, funbox, newDirectives);
3592 5951 : if (!funpc.init())
3593 0 : return false;
3594 :
3595 5951 : if (!functionFormalParametersAndBody(inHandling, yieldHandling, pn, kind))
3596 0 : return false;
3597 :
3598 5951 : return leaveInnerFunction(outerpc);
3599 : }
3600 :
3601 : template <class ParseHandler, typename CharT>
3602 : bool
3603 4400 : Parser<ParseHandler, CharT>::innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun,
3604 : uint32_t toStringStart,
3605 : InHandling inHandling, YieldHandling yieldHandling,
3606 : FunctionSyntaxKind kind,
3607 : GeneratorKind generatorKind,
3608 : FunctionAsyncKind asyncKind,
3609 : bool tryAnnexB,
3610 : Directives inheritedDirectives,
3611 : Directives* newDirectives)
3612 : {
3613 : // Note that it is possible for outerpc != this->pc, as we may be
3614 : // attempting to syntax parse an inner function from an outer full
3615 : // parser. In that case, outerpc is a ParseContext from the full parser
3616 : // instead of the current top of the stack of the syntax parser.
3617 :
3618 4400 : FunctionBox* funbox = newFunctionBox(pn, fun, toStringStart, inheritedDirectives,
3619 4400 : generatorKind, asyncKind);
3620 4400 : if (!funbox)
3621 0 : return false;
3622 4400 : funbox->initWithEnclosingParseContext(outerpc, kind);
3623 :
3624 4400 : if (!innerFunction(pn, outerpc, funbox, toStringStart, inHandling, yieldHandling, kind,
3625 : inheritedDirectives, newDirectives))
3626 : {
3627 0 : return false;
3628 : }
3629 :
3630 : // Append possible Annex B function box only upon successfully parsing.
3631 4400 : if (tryAnnexB && !pc->innermostScope()->addPossibleAnnexBFunctionBox(pc, funbox))
3632 0 : return false;
3633 :
3634 4400 : return true;
3635 : }
3636 :
3637 : template <class ParseHandler, typename CharT>
3638 : bool
3639 3 : Parser<ParseHandler, CharT>::appendToCallSiteObj(Node callSiteObj)
3640 : {
3641 3 : Node cookedNode = noSubstitutionTaggedTemplate();
3642 3 : if (!cookedNode)
3643 0 : return false;
3644 :
3645 3 : JSAtom* atom = tokenStream.getRawTemplateStringAtom();
3646 3 : if (!atom)
3647 0 : return false;
3648 3 : Node rawNode = handler.newTemplateStringLiteral(atom, pos());
3649 3 : if (!rawNode)
3650 0 : return false;
3651 :
3652 3 : handler.addToCallSiteObject(callSiteObj, rawNode, cookedNode);
3653 3 : return true;
3654 : }
3655 :
3656 : template <>
3657 : ParseNode*
3658 1407 : Parser<FullParseHandler, char16_t>::standaloneLazyFunction(HandleFunction fun,
3659 : uint32_t toStringStart,
3660 : bool strict,
3661 : GeneratorKind generatorKind,
3662 : FunctionAsyncKind asyncKind)
3663 : {
3664 1407 : MOZ_ASSERT(checkOptionsCalled);
3665 :
3666 1407 : Node pn = handler.newFunctionStatement(pos());
3667 1407 : if (!pn)
3668 0 : return null();
3669 :
3670 1407 : Directives directives(strict);
3671 1407 : FunctionBox* funbox = newFunctionBox(pn, fun, toStringStart, directives, generatorKind,
3672 2814 : asyncKind);
3673 1407 : if (!funbox)
3674 0 : return null();
3675 1407 : funbox->initFromLazyFunction();
3676 :
3677 1407 : Directives newDirectives = directives;
3678 2814 : ParseContext funpc(this, funbox, &newDirectives);
3679 1407 : if (!funpc.init())
3680 0 : return null();
3681 :
3682 : // Our tokenStream has no current token, so pn's position is garbage.
3683 : // Substitute the position of the first token in our source. If the function
3684 : // is a not-async arrow, use TokenStream::Operand to keep
3685 : // verifyConsistentModifier from complaining (we will use
3686 : // TokenStream::Operand in functionArguments).
3687 1686 : TokenStream::Modifier modifier = (fun->isArrow() && asyncKind == SyncFunction)
3688 1686 : ? TokenStream::Operand : TokenStream::None;
3689 1407 : if (!tokenStream.peekTokenPos(&pn->pn_pos, modifier))
3690 0 : return null();
3691 :
3692 1407 : YieldHandling yieldHandling = GetYieldHandling(generatorKind);
3693 1407 : FunctionSyntaxKind syntaxKind = Statement;
3694 1407 : if (fun->isClassConstructor())
3695 8 : syntaxKind = ClassConstructor;
3696 1399 : else if (fun->isMethod())
3697 681 : syntaxKind = Method;
3698 718 : else if (fun->isGetter())
3699 47 : syntaxKind = Getter;
3700 671 : else if (fun->isSetter())
3701 5 : syntaxKind = Setter;
3702 666 : else if (fun->isArrow())
3703 279 : syntaxKind = Arrow;
3704 :
3705 1407 : if (!functionFormalParametersAndBody(InAllowed, yieldHandling, pn, syntaxKind)) {
3706 0 : MOZ_ASSERT(directives == newDirectives);
3707 0 : return null();
3708 : }
3709 :
3710 1407 : if (!FoldConstants(context, &pn, this))
3711 0 : return null();
3712 :
3713 1407 : return pn;
3714 : }
3715 :
3716 : template <class ParseHandler, typename CharT>
3717 : bool
3718 7373 : Parser<ParseHandler, CharT>::functionFormalParametersAndBody(InHandling inHandling,
3719 : YieldHandling yieldHandling,
3720 : Node pn, FunctionSyntaxKind kind,
3721 : const Maybe<uint32_t>& parameterListEnd /* = Nothing() */,
3722 : bool isStandaloneFunction /* = false */)
3723 : {
3724 : // Given a properly initialized parse context, try to parse an actual
3725 : // function without concern for conversion to strict mode, use of lazy
3726 : // parsing and such.
3727 :
3728 7373 : FunctionBox* funbox = pc->functionBox();
3729 14746 : RootedFunction fun(context, funbox->function());
3730 :
3731 : // See below for an explanation why arrow function parameters and arrow
3732 : // function bodies are parsed with different yield/await settings.
3733 : {
3734 14595 : AwaitHandling awaitHandling = funbox->isAsync() || (kind == Arrow && awaitIsKeyword())
3735 7574 : ? AwaitIsKeyword
3736 7373 : : AwaitIsName;
3737 14746 : AutoAwaitIsKeyword<Parser> awaitIsKeyword(this, awaitHandling);
3738 7373 : if (!functionArguments(yieldHandling, kind, pn))
3739 0 : return false;
3740 : }
3741 :
3742 14746 : Maybe<ParseContext::VarScope> varScope;
3743 7373 : if (funbox->hasParameterExprs) {
3744 268 : varScope.emplace(this);
3745 268 : if (!varScope->init(pc))
3746 0 : return false;
3747 : } else {
3748 7105 : pc->functionScope().useAsVarScope(pc);
3749 : }
3750 :
3751 7373 : if (kind == Arrow) {
3752 : bool matched;
3753 1109 : if (!tokenStream.matchToken(&matched, TOK_ARROW))
3754 0 : return false;
3755 1109 : if (!matched) {
3756 0 : error(JSMSG_BAD_ARROW_ARGS);
3757 0 : return false;
3758 : }
3759 : }
3760 :
3761 : // When parsing something for new Function() we have to make sure to
3762 : // only treat a certain part of the source as a parameter list.
3763 7373 : if (parameterListEnd.isSome() && parameterListEnd.value() != pos().begin) {
3764 0 : error(JSMSG_UNEXPECTED_PARAMLIST_END);
3765 0 : return false;
3766 : }
3767 :
3768 : // Parse the function body.
3769 7373 : FunctionBodyType bodyType = StatementListBody;
3770 : TokenKind tt;
3771 7373 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
3772 0 : return false;
3773 7373 : uint32_t openedPos = 0;
3774 7373 : if (tt != TOK_LC) {
3775 525 : if (kind != Arrow) {
3776 0 : if (funbox->isStarGenerator() || funbox->isAsync() || kind == Method ||
3777 0 : kind == GetterNoExpressionClosure || kind == SetterNoExpressionClosure ||
3778 0 : IsConstructorKind(kind))
3779 : {
3780 0 : error(JSMSG_CURLY_BEFORE_BODY);
3781 0 : return false;
3782 : }
3783 :
3784 : #if JS_HAS_EXPR_CLOSURES
3785 0 : addTelemetry(DeprecatedLanguageExtension::ExpressionClosure);
3786 0 : if (!warnOnceAboutExprClosure())
3787 0 : return false;
3788 : #else
3789 : error(JSMSG_CURLY_BEFORE_BODY);
3790 : return false;
3791 : #endif
3792 : }
3793 :
3794 525 : tokenStream.ungetToken();
3795 525 : bodyType = ExpressionBody;
3796 525 : funbox->setIsExprBody();
3797 : } else {
3798 6848 : openedPos = pos().begin;
3799 : }
3800 :
3801 : // Arrow function parameters inherit yieldHandling from the enclosing
3802 : // context, but the arrow body doesn't. E.g. in |(a = yield) => yield|,
3803 : // |yield| in the parameters is either a name or keyword, depending on
3804 : // whether the arrow function is enclosed in a generator function or not.
3805 : // Whereas the |yield| in the function body is always parsed as a name.
3806 : // The same goes when parsing |await| in arrow functions.
3807 7373 : YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind());
3808 7373 : AwaitHandling bodyAwaitHandling = GetAwaitHandling(pc->asyncKind());
3809 7373 : bool inheritedStrict = pc->sc()->strict();
3810 : Node body;
3811 : {
3812 14746 : AutoAwaitIsKeyword<Parser> awaitIsKeyword(this, bodyAwaitHandling);
3813 7373 : body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
3814 7373 : if (!body)
3815 0 : return false;
3816 : }
3817 :
3818 : // Revalidate the function name when we transitioned to strict mode.
3819 12521 : if ((kind == Statement || kind == Expression) && fun->explicitName()
3820 10108 : && !inheritedStrict && pc->sc()->strict())
3821 : {
3822 0 : MOZ_ASSERT(pc->sc()->hasExplicitUseStrict(),
3823 : "strict mode should only change when a 'use strict' directive is present");
3824 :
3825 0 : PropertyName* propertyName = fun->explicitName()->asPropertyName();
3826 : YieldHandling nameYieldHandling;
3827 0 : if (kind == Expression) {
3828 : // Named lambda has binding inside it.
3829 0 : nameYieldHandling = bodyYieldHandling;
3830 : } else {
3831 : // Otherwise YieldHandling cannot be checked at this point
3832 : // because of different context.
3833 : // It should already be checked before this point.
3834 0 : nameYieldHandling = YieldIsName;
3835 : }
3836 :
3837 : // We already use the correct await-handling at this point, therefore
3838 : // we don't need call AutoAwaitIsKeyword here.
3839 :
3840 0 : uint32_t nameOffset = handler.getFunctionNameOffset(pn, tokenStream);
3841 0 : if (!checkBindingIdentifier(propertyName, nameOffset, nameYieldHandling))
3842 0 : return false;
3843 : }
3844 :
3845 7373 : if (bodyType == StatementListBody) {
3846 6848 : MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
3847 : reportMissingClosing(JSMSG_CURLY_AFTER_BODY,
3848 : JSMSG_CURLY_OPENED, openedPos));
3849 6848 : funbox->setEnd(tokenStream);
3850 : } else {
3851 : #if !JS_HAS_EXPR_CLOSURES
3852 : MOZ_ASSERT(kind == Arrow);
3853 : #endif
3854 525 : if (tokenStream.hadError())
3855 0 : return false;
3856 525 : funbox->setEnd(tokenStream);
3857 525 : if (kind == Statement && !matchOrInsertSemicolonAfterExpression())
3858 0 : return false;
3859 : }
3860 :
3861 7373 : if (IsMethodDefinitionKind(kind) && pc->superScopeNeedsHomeObject())
3862 13 : funbox->setNeedsHomeObject();
3863 :
3864 7373 : if (!finishFunction(isStandaloneFunction))
3865 0 : return false;
3866 :
3867 7373 : handler.setEndPosition(body, pos().begin);
3868 7373 : handler.setEndPosition(pn, pos().end);
3869 7373 : handler.setFunctionBody(pn, body);
3870 :
3871 7373 : return true;
3872 : }
3873 :
3874 : template <class ParseHandler, typename CharT>
3875 : typename ParseHandler::Node
3876 1831 : Parser<ParseHandler, CharT>::functionStmt(uint32_t toStringStart, YieldHandling yieldHandling,
3877 : DefaultHandling defaultHandling,
3878 : FunctionAsyncKind asyncKind)
3879 : {
3880 1831 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
3881 :
3882 : // In sloppy mode, Annex B.3.2 allows labelled function declarations.
3883 : // Otherwise it's a parse error.
3884 1831 : ParseContext::Statement* declaredInStmt = pc->innermostStatement();
3885 1831 : if (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) {
3886 0 : MOZ_ASSERT(!pc->sc()->strict(),
3887 : "labeled functions shouldn't be parsed in strict mode");
3888 :
3889 : // Find the innermost non-label statement. Report an error if it's
3890 : // unbraced: functions can't appear in it. Otherwise the statement
3891 : // (or its absence) determines the scope the function's bound in.
3892 0 : while (declaredInStmt && declaredInStmt->kind() == StatementKind::Label)
3893 0 : declaredInStmt = declaredInStmt->enclosing();
3894 :
3895 0 : if (declaredInStmt && !StatementKindIsBraced(declaredInStmt->kind())) {
3896 0 : error(JSMSG_SLOPPY_FUNCTION_LABEL);
3897 0 : return null();
3898 : }
3899 : }
3900 :
3901 : TokenKind tt;
3902 1831 : if (!tokenStream.getToken(&tt))
3903 0 : return null();
3904 :
3905 1831 : GeneratorKind generatorKind = NotGenerator;
3906 1831 : if (tt == TOK_MUL) {
3907 0 : if (!asyncIterationSupported()) {
3908 0 : if (asyncKind != SyncFunction) {
3909 0 : error(JSMSG_ASYNC_GENERATOR);
3910 0 : return null();
3911 : }
3912 : }
3913 0 : generatorKind = StarGenerator;
3914 0 : if (!tokenStream.getToken(&tt))
3915 0 : return null();
3916 : }
3917 :
3918 3662 : RootedPropertyName name(context);
3919 1831 : if (TokenKindIsPossibleIdentifier(tt)) {
3920 1831 : name = bindingIdentifier(yieldHandling);
3921 1831 : if (!name)
3922 0 : return null();
3923 0 : } else if (defaultHandling == AllowDefaultName) {
3924 0 : name = context->names().starDefaultStar;
3925 0 : tokenStream.ungetToken();
3926 : } else {
3927 : /* Unnamed function expressions are forbidden in statement context. */
3928 0 : error(JSMSG_UNNAMED_FUNCTION_STMT);
3929 0 : return null();
3930 : }
3931 :
3932 : // Note the declared name and check for early errors.
3933 : DeclarationKind kind;
3934 1831 : if (declaredInStmt) {
3935 0 : MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label);
3936 0 : MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind()));
3937 :
3938 0 : kind = !pc->sc()->strict() && generatorKind == NotGenerator && asyncKind == SyncFunction
3939 : ? DeclarationKind::SloppyLexicalFunction
3940 : : DeclarationKind::LexicalFunction;
3941 : } else {
3942 1831 : kind = pc->atModuleLevel()
3943 : ? DeclarationKind::ModuleBodyLevelFunction
3944 : : DeclarationKind::BodyLevelFunction;
3945 : }
3946 :
3947 1831 : if (!noteDeclaredName(name, kind, pos()))
3948 0 : return null();
3949 :
3950 1831 : Node pn = handler.newFunctionStatement(pos());
3951 1831 : if (!pn)
3952 0 : return null();
3953 :
3954 : // Under sloppy mode, try Annex B.3.3 semantics. If making an additional
3955 : // 'var' binding of the same name does not throw an early error, do so.
3956 : // This 'var' binding would be assigned the function object when its
3957 : // declaration is reached, not at the start of the block.
3958 : //
3959 : // This semantics is implemented upon Scope exit in
3960 : // Scope::propagateAndMarkAnnexBFunctionBoxes.
3961 1831 : bool tryAnnexB = kind == DeclarationKind::SloppyLexicalFunction;
3962 :
3963 1831 : YieldHandling newYieldHandling = GetYieldHandling(generatorKind);
3964 3662 : return functionDefinition(pn, toStringStart, InAllowed, newYieldHandling, name, Statement,
3965 1831 : generatorKind, asyncKind, tryAnnexB);
3966 : }
3967 :
3968 : template <class ParseHandler, typename CharT>
3969 : typename ParseHandler::Node
3970 1189 : Parser<ParseHandler, CharT>::functionExpr(uint32_t toStringStart, InvokedPrediction invoked,
3971 : FunctionAsyncKind asyncKind)
3972 : {
3973 1189 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
3974 :
3975 2378 : AutoAwaitIsKeyword<Parser> awaitIsKeyword(this, GetAwaitHandling(asyncKind));
3976 1189 : GeneratorKind generatorKind = NotGenerator;
3977 : TokenKind tt;
3978 1189 : if (!tokenStream.getToken(&tt))
3979 0 : return null();
3980 :
3981 1189 : if (tt == TOK_MUL) {
3982 9 : if (!asyncIterationSupported()) {
3983 9 : if (asyncKind != SyncFunction) {
3984 0 : error(JSMSG_ASYNC_GENERATOR);
3985 0 : return null();
3986 : }
3987 : }
3988 9 : generatorKind = StarGenerator;
3989 9 : if (!tokenStream.getToken(&tt))
3990 0 : return null();
3991 : }
3992 :
3993 1189 : YieldHandling yieldHandling = GetYieldHandling(generatorKind);
3994 :
3995 2378 : RootedPropertyName name(context);
3996 1189 : if (TokenKindIsPossibleIdentifier(tt)) {
3997 649 : name = bindingIdentifier(yieldHandling);
3998 649 : if (!name)
3999 0 : return null();
4000 : } else {
4001 540 : tokenStream.ungetToken();
4002 : }
4003 :
4004 1189 : Node pn = handler.newFunctionExpression(pos());
4005 1189 : if (!pn)
4006 0 : return null();
4007 :
4008 1189 : if (invoked)
4009 28 : pn = handler.setLikelyIIFE(pn);
4010 :
4011 2378 : return functionDefinition(pn, toStringStart, InAllowed, yieldHandling, name, Expression,
4012 1189 : generatorKind, asyncKind);
4013 : }
4014 :
4015 : /*
4016 : * Return true if this node, known to be an unparenthesized string literal,
4017 : * could be the string of a directive in a Directive Prologue. Directive
4018 : * strings never contain escape sequences or line continuations.
4019 : * isEscapeFreeStringLiteral, below, checks whether the node itself could be
4020 : * a directive.
4021 : */
4022 : static inline bool
4023 112 : IsEscapeFreeStringLiteral(const TokenPos& pos, JSAtom* str)
4024 : {
4025 : /*
4026 : * If the string's length in the source code is its length as a value,
4027 : * accounting for the quotes, then it must not contain any escape
4028 : * sequences or line continuations.
4029 : */
4030 112 : return pos.begin + str->length() + 2 == pos.end;
4031 : }
4032 :
4033 : template <>
4034 : bool
4035 0 : Parser<SyntaxParseHandler, char16_t>::asmJS(Node list)
4036 : {
4037 : // While asm.js could technically be validated and compiled during syntax
4038 : // parsing, we have no guarantee that some later JS wouldn't abort the
4039 : // syntax parse and cause us to re-parse (and re-compile) the asm.js module.
4040 : // For simplicity, unconditionally abort the syntax parse when "use asm" is
4041 : // encountered so that asm.js is always validated/compiled exactly once
4042 : // during a full parse.
4043 0 : JS_ALWAYS_FALSE(abortIfSyntaxParser());
4044 0 : return false;
4045 : }
4046 :
4047 : template <>
4048 : bool
4049 0 : Parser<FullParseHandler, char16_t>::asmJS(Node list)
4050 : {
4051 : // Disable syntax parsing in anything nested inside the asm.js module.
4052 0 : disableSyntaxParser();
4053 :
4054 : // We should be encountering the "use asm" directive for the first time; if
4055 : // the directive is already, we must have failed asm.js validation and we're
4056 : // reparsing. In that case, don't try to validate again. A non-null
4057 : // newDirectives means we're not in a normal function.
4058 0 : if (!pc->newDirectives || pc->newDirectives->asmJS())
4059 0 : return true;
4060 :
4061 : // If there is no ScriptSource, then we are doing a non-compiling parse and
4062 : // so we shouldn't (and can't, without a ScriptSource) compile.
4063 0 : if (ss == nullptr)
4064 0 : return true;
4065 :
4066 0 : pc->functionBox()->useAsm = true;
4067 :
4068 : // Attempt to validate and compile this asm.js module. On success, the
4069 : // tokenStream has been advanced to the closing }. On failure, the
4070 : // tokenStream is in an indeterminate state and we must reparse the
4071 : // function from the beginning. Reparsing is triggered by marking that a
4072 : // new directive has been encountered and returning 'false'.
4073 : bool validated;
4074 0 : if (!CompileAsmJS(context, *this, list, &validated))
4075 0 : return false;
4076 0 : if (!validated) {
4077 0 : pc->newDirectives->setAsmJS();
4078 0 : return false;
4079 : }
4080 :
4081 0 : return true;
4082 : }
4083 :
4084 : /*
4085 : * Recognize Directive Prologue members and directives. Assuming |pn| is a
4086 : * candidate for membership in a directive prologue, recognize directives and
4087 : * set |pc|'s flags accordingly. If |pn| is indeed part of a prologue, set its
4088 : * |pn_prologue| flag.
4089 : *
4090 : * Note that the following is a strict mode function:
4091 : *
4092 : * function foo() {
4093 : * "blah" // inserted semi colon
4094 : * "blurgh"
4095 : * "use\x20loose"
4096 : * "use strict"
4097 : * }
4098 : *
4099 : * That is, even though "use\x20loose" can never be a directive, now or in the
4100 : * future (because of the hex escape), the Directive Prologue extends through it
4101 : * to the "use strict" statement, which is indeed a directive.
4102 : */
4103 : template <class ParseHandler, typename CharT>
4104 : bool
4105 7089 : Parser<ParseHandler, CharT>::maybeParseDirective(Node list, Node possibleDirective, bool* cont)
4106 : {
4107 7089 : TokenPos directivePos;
4108 7089 : JSAtom* directive = handler.isStringExprStatement(possibleDirective, &directivePos);
4109 :
4110 7089 : *cont = !!directive;
4111 7089 : if (!*cont)
4112 6977 : return true;
4113 :
4114 112 : if (IsEscapeFreeStringLiteral(directivePos, directive)) {
4115 : // Mark this statement as being a possibly legitimate part of a
4116 : // directive prologue, so the bytecode emitter won't warn about it being
4117 : // useless code. (We mustn't just omit the statement entirely yet, as it
4118 : // could be producing the value of an eval or JSScript execution.)
4119 : //
4120 : // Note that even if the string isn't one we recognize as a directive,
4121 : // the emitter still shouldn't flag it as useless, as it could become a
4122 : // directive in the future. We don't want to interfere with people
4123 : // taking advantage of directive-prologue-enabled features that appear
4124 : // in other browsers first.
4125 112 : handler.setInDirectivePrologue(possibleDirective);
4126 :
4127 112 : if (directive == context->names().useStrict) {
4128 : // Functions with non-simple parameter lists (destructuring,
4129 : // default or rest parameters) must not contain a "use strict"
4130 : // directive.
4131 109 : if (pc->isFunctionBox()) {
4132 5 : FunctionBox* funbox = pc->functionBox();
4133 5 : if (!funbox->hasSimpleParameterList()) {
4134 0 : const char* parameterKind = funbox->hasDestructuringArgs
4135 : ? "destructuring"
4136 0 : : funbox->hasParameterExprs
4137 : ? "default"
4138 0 : : "rest";
4139 0 : errorAt(directivePos.begin, JSMSG_STRICT_NON_SIMPLE_PARAMS, parameterKind);
4140 0 : return false;
4141 : }
4142 : }
4143 :
4144 : // We're going to be in strict mode. Note that this scope explicitly
4145 : // had "use strict";
4146 109 : pc->sc()->setExplicitUseStrict();
4147 109 : if (!pc->sc()->strict()) {
4148 : // We keep track of the one possible strict violation that could
4149 : // occur in the directive prologue -- octal escapes -- and
4150 : // complain now.
4151 109 : if (tokenStream.sawOctalEscape()) {
4152 0 : error(JSMSG_DEPRECATED_OCTAL);
4153 0 : return false;
4154 : }
4155 109 : pc->sc()->strictScript = true;
4156 : }
4157 3 : } else if (directive == context->names().useAsm) {
4158 0 : if (pc->isFunctionBox())
4159 0 : return asmJS(list);
4160 0 : return warningAt(directivePos.begin, JSMSG_USE_ASM_DIRECTIVE_FAIL);
4161 : }
4162 : }
4163 112 : return true;
4164 : }
4165 :
4166 : template <class ParseHandler, typename CharT>
4167 : typename ParseHandler::Node
4168 15719 : Parser<ParseHandler, CharT>::statementList(YieldHandling yieldHandling)
4169 : {
4170 15719 : if (!CheckRecursionLimit(context))
4171 0 : return null();
4172 :
4173 15719 : Node pn = handler.newStatementList(pos());
4174 15719 : if (!pn)
4175 0 : return null();
4176 :
4177 15719 : bool canHaveDirectives = pc->atBodyLevel();
4178 15719 : if (canHaveDirectives)
4179 7116 : tokenStream.clearSawOctalEscape();
4180 15719 : bool afterReturn = false;
4181 15719 : bool warnedAboutStatementsAfterReturn = false;
4182 15719 : uint32_t statementBegin = 0;
4183 44716 : for (;;) {
4184 60435 : TokenKind tt = TOK_EOF;
4185 60435 : if (!tokenStream.peekToken(&tt, TokenStream::Operand)) {
4186 0 : if (tokenStream.isEOF())
4187 0 : isUnexpectedEOF_ = true;
4188 0 : return null();
4189 : }
4190 60435 : if (tt == TOK_EOF || tt == TOK_RC)
4191 : break;
4192 44716 : if (afterReturn) {
4193 0 : if (!tokenStream.peekOffset(&statementBegin, TokenStream::Operand))
4194 0 : return null();
4195 : }
4196 44716 : Node next = statementListItem(yieldHandling, canHaveDirectives);
4197 44716 : if (!next) {
4198 0 : if (tokenStream.isEOF())
4199 0 : isUnexpectedEOF_ = true;
4200 0 : return null();
4201 : }
4202 44716 : if (!warnedAboutStatementsAfterReturn) {
4203 44716 : if (afterReturn) {
4204 0 : if (!handler.isStatementPermittedAfterReturnStatement(next)) {
4205 0 : if (!warningAt(statementBegin, JSMSG_STMT_AFTER_RETURN))
4206 0 : return null();
4207 :
4208 0 : warnedAboutStatementsAfterReturn = true;
4209 : }
4210 44716 : } else if (handler.isReturnStatement(next)) {
4211 5611 : afterReturn = true;
4212 : }
4213 : }
4214 :
4215 44716 : if (canHaveDirectives) {
4216 7089 : if (!maybeParseDirective(pn, next, &canHaveDirectives))
4217 0 : return null();
4218 : }
4219 :
4220 44716 : handler.addStatementToList(pn, next);
4221 : }
4222 :
4223 15719 : return pn;
4224 : }
4225 :
4226 : template <class ParseHandler, typename CharT>
4227 : typename ParseHandler::Node
4228 9014 : Parser<ParseHandler, CharT>::condition(InHandling inHandling, YieldHandling yieldHandling)
4229 : {
4230 9014 : MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND);
4231 9014 : Node pn = exprInParens(inHandling, yieldHandling, TripledotProhibited);
4232 9014 : if (!pn)
4233 0 : return null();
4234 9014 : MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);
4235 :
4236 : /* Check for (a = b) and warn about possible (a == b) mistype. */
4237 9014 : if (handler.isUnparenthesizedAssignment(pn)) {
4238 0 : if (!extraWarning(JSMSG_EQUAL_AS_ASSIGN))
4239 0 : return null();
4240 : }
4241 9014 : return pn;
4242 : }
4243 :
4244 : template <class ParseHandler, typename CharT>
4245 : bool
4246 841 : Parser<ParseHandler, CharT>::matchLabel(YieldHandling yieldHandling,
4247 : MutableHandle<PropertyName*> label)
4248 : {
4249 841 : TokenKind tt = TOK_EOF;
4250 841 : if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
4251 0 : return false;
4252 :
4253 841 : if (TokenKindIsPossibleIdentifier(tt)) {
4254 0 : tokenStream.consumeKnownToken(tt, TokenStream::Operand);
4255 :
4256 0 : label.set(labelIdentifier(yieldHandling));
4257 0 : if (!label)
4258 0 : return false;
4259 : } else {
4260 841 : label.set(nullptr);
4261 : }
4262 841 : return true;
4263 : }
4264 :
4265 : template <class ParseHandler, typename CharT>
4266 72402 : Parser<ParseHandler, CharT>::PossibleError::PossibleError(Parser<ParseHandler, CharT>& parser)
4267 72402 : : parser_(parser)
4268 72402 : {}
4269 :
4270 : template <class ParseHandler, typename CharT>
4271 : typename Parser<ParseHandler, CharT>::PossibleError::Error&
4272 260316 : Parser<ParseHandler, CharT>::PossibleError::error(ErrorKind kind)
4273 : {
4274 260316 : if (kind == ErrorKind::Expression)
4275 82136 : return exprError_;
4276 178180 : if (kind == ErrorKind::Destructuring)
4277 101275 : return destructuringError_;
4278 76905 : MOZ_ASSERT(kind == ErrorKind::DestructuringWarning);
4279 76905 : return destructuringWarning_;
4280 : }
4281 :
4282 : template <class ParseHandler, typename CharT>
4283 : void
4284 153797 : Parser<ParseHandler, CharT>::PossibleError::setResolved(ErrorKind kind)
4285 : {
4286 153797 : error(kind).state_ = ErrorState::None;
4287 153797 : }
4288 :
4289 : template <class ParseHandler, typename CharT>
4290 : bool
4291 103837 : Parser<ParseHandler, CharT>::PossibleError::hasError(ErrorKind kind)
4292 : {
4293 103837 : return error(kind).state_ == ErrorState::Pending;
4294 : }
4295 :
4296 : template <class ParseHandler, typename CharT>
4297 : bool
4298 10906 : Parser<ParseHandler, CharT>::PossibleError::hasPendingDestructuringError()
4299 : {
4300 10906 : return hasError(ErrorKind::Destructuring);
4301 : }
4302 :
4303 : template <class ParseHandler, typename CharT>
4304 : void
4305 4359 : Parser<ParseHandler, CharT>::PossibleError::setPending(ErrorKind kind, const TokenPos& pos,
4306 : unsigned errorNumber)
4307 : {
4308 : // Don't overwrite a previously recorded error.
4309 4359 : if (hasError(kind))
4310 1841 : return;
4311 :
4312 : // If we report an error later, we'll do it from the position where we set
4313 : // the state to pending.
4314 2518 : Error& err = error(kind);
4315 2518 : err.offset_ = pos.begin;
4316 2518 : err.errorNumber_ = errorNumber;
4317 2518 : err.state_ = ErrorState::Pending;
4318 : }
4319 :
4320 : template <class ParseHandler, typename CharT>
4321 : void
4322 4359 : Parser<ParseHandler, CharT>::PossibleError::setPendingDestructuringErrorAt(const TokenPos& pos,
4323 : unsigned errorNumber)
4324 : {
4325 4359 : setPending(ErrorKind::Destructuring, pos, errorNumber);
4326 4359 : }
4327 :
4328 : template <class ParseHandler, typename CharT>
4329 : void
4330 0 : Parser<ParseHandler, CharT>::PossibleError::setPendingDestructuringWarningAt(const TokenPos& pos,
4331 : unsigned errorNumber)
4332 : {
4333 0 : setPending(ErrorKind::DestructuringWarning, pos, errorNumber);
4334 0 : }
4335 :
4336 : template <class ParseHandler, typename CharT>
4337 : void
4338 0 : Parser<ParseHandler, CharT>::PossibleError::setPendingExpressionErrorAt(const TokenPos& pos,
4339 : unsigned errorNumber)
4340 : {
4341 0 : setPending(ErrorKind::Expression, pos, errorNumber);
4342 0 : }
4343 :
4344 : template <class ParseHandler, typename CharT>
4345 : bool
4346 76905 : Parser<ParseHandler, CharT>::PossibleError::checkForError(ErrorKind kind)
4347 : {
4348 76905 : if (!hasError(kind))
4349 76905 : return true;
4350 :
4351 0 : Error& err = error(kind);
4352 0 : parser_.errorAt(err.offset_, err.errorNumber_);
4353 0 : return false;
4354 : }
4355 :
4356 : template <class ParseHandler, typename CharT>
4357 : bool
4358 13 : Parser<ParseHandler, CharT>::PossibleError::checkForWarning(ErrorKind kind)
4359 : {
4360 13 : if (!hasError(kind))
4361 13 : return true;
4362 :
4363 0 : Error& err = error(kind);
4364 0 : return parser_.extraWarningAt(err.offset_, err.errorNumber_);
4365 : }
4366 :
4367 : template <class ParseHandler, typename CharT>
4368 : bool
4369 13 : Parser<ParseHandler, CharT>::PossibleError::checkForDestructuringErrorOrWarning()
4370 : {
4371 : // Clear pending expression error, because we're definitely not in an
4372 : // expression context.
4373 13 : setResolved(ErrorKind::Expression);
4374 :
4375 : // Report any pending destructuring error or warning.
4376 26 : return checkForError(ErrorKind::Destructuring) &&
4377 26 : checkForWarning(ErrorKind::DestructuringWarning);
4378 : }
4379 :
4380 : template <class ParseHandler, typename CharT>
4381 : bool
4382 76892 : Parser<ParseHandler, CharT>::PossibleError::checkForExpressionError()
4383 : {
4384 : // Clear pending destructuring error or warning, because we're definitely
4385 : // not in a destructuring context.
4386 76892 : setResolved(ErrorKind::Destructuring);
4387 76892 : setResolved(ErrorKind::DestructuringWarning);
4388 :
4389 : // Report any pending expression error.
4390 76892 : return checkForError(ErrorKind::Expression);
4391 : }
4392 :
4393 : template <class ParseHandler, typename CharT>
4394 : void
4395 10462 : Parser<ParseHandler, CharT>::PossibleError::transferErrorTo(ErrorKind kind, PossibleError* other)
4396 : {
4397 10462 : if (hasError(kind) && !other->hasError(kind)) {
4398 82 : Error& err = error(kind);
4399 82 : Error& otherErr = other->error(kind);
4400 82 : otherErr.offset_ = err.offset_;
4401 82 : otherErr.errorNumber_ = err.errorNumber_;
4402 82 : otherErr.state_ = err.state_;
4403 : }
4404 10462 : }
4405 :
4406 : template <class ParseHandler, typename CharT>
4407 : void
4408 5231 : Parser<ParseHandler, CharT>::PossibleError::transferErrorsTo(PossibleError* other)
4409 : {
4410 5231 : MOZ_ASSERT(other);
4411 5231 : MOZ_ASSERT(this != other);
4412 5231 : MOZ_ASSERT(&parser_ == &other->parser_,
4413 : "Can't transfer fields to an instance which belongs to a different parser");
4414 :
4415 5231 : transferErrorTo(ErrorKind::Destructuring, other);
4416 5231 : transferErrorTo(ErrorKind::Expression, other);
4417 5231 : }
4418 :
4419 : template <class ParseHandler, typename CharT>
4420 : typename ParseHandler::Node
4421 18 : Parser<ParseHandler, CharT>::bindingInitializer(Node lhs, DeclarationKind kind,
4422 : YieldHandling yieldHandling)
4423 : {
4424 18 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_ASSIGN));
4425 :
4426 18 : if (kind == DeclarationKind::FormalParameter)
4427 15 : pc->functionBox()->hasParameterExprs = true;
4428 :
4429 18 : Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
4430 18 : if (!rhs)
4431 0 : return null();
4432 :
4433 18 : handler.checkAndSetIsDirectRHSAnonFunction(rhs);
4434 :
4435 18 : Node assign = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP);
4436 18 : if (!assign)
4437 0 : return null();
4438 :
4439 18 : if (foldConstants && !FoldConstants(context, &assign, this))
4440 0 : return null();
4441 :
4442 18 : return assign;
4443 : }
4444 :
4445 : template <class ParseHandler, typename CharT>
4446 : typename ParseHandler::Node
4447 1312 : Parser<ParseHandler, CharT>::bindingIdentifier(DeclarationKind kind, YieldHandling yieldHandling)
4448 : {
4449 2624 : RootedPropertyName name(context, bindingIdentifier(yieldHandling));
4450 1312 : if (!name)
4451 0 : return null();
4452 :
4453 1312 : Node binding = newName(name);
4454 1312 : if (!binding || !noteDeclaredName(name, kind, pos()))
4455 0 : return null();
4456 :
4457 1312 : return binding;
4458 : }
4459 :
4460 : template <class ParseHandler, typename CharT>
4461 : typename ParseHandler::Node
4462 404 : Parser<ParseHandler, CharT>::bindingIdentifierOrPattern(DeclarationKind kind,
4463 : YieldHandling yieldHandling, TokenKind tt)
4464 : {
4465 404 : if (tt == TOK_LB)
4466 8 : return arrayBindingPattern(kind, yieldHandling);
4467 :
4468 396 : if (tt == TOK_LC)
4469 11 : return objectBindingPattern(kind, yieldHandling);
4470 :
4471 385 : if (!TokenKindIsPossibleIdentifierName(tt)) {
4472 0 : error(JSMSG_NO_VARIABLE_NAME);
4473 0 : return null();
4474 : }
4475 :
4476 385 : return bindingIdentifier(kind, yieldHandling);
4477 : }
4478 :
4479 : template <class ParseHandler, typename CharT>
4480 : typename ParseHandler::Node
4481 221 : Parser<ParseHandler, CharT>::objectBindingPattern(DeclarationKind kind,
4482 : YieldHandling yieldHandling)
4483 : {
4484 221 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
4485 :
4486 221 : if (!CheckRecursionLimit(context))
4487 0 : return null();
4488 :
4489 221 : uint32_t begin = pos().begin;
4490 221 : Node literal = handler.newObjectLiteral(begin);
4491 221 : if (!literal)
4492 0 : return null();
4493 :
4494 442 : Maybe<DeclarationKind> declKind = Some(kind);
4495 442 : RootedAtom propAtom(context);
4496 280 : for (;;) {
4497 : TokenKind tt;
4498 501 : if (!tokenStream.peekToken(&tt))
4499 0 : return null();
4500 501 : if (tt == TOK_RC)
4501 226 : break;
4502 :
4503 496 : if (tt == TOK_TRIPLEDOT) {
4504 0 : tokenStream.consumeKnownToken(TOK_TRIPLEDOT);
4505 0 : uint32_t begin = pos().begin;
4506 :
4507 : TokenKind tt;
4508 0 : if (!tokenStream.getToken(&tt))
4509 0 : return null();
4510 :
4511 0 : Node inner = bindingIdentifierOrPattern(kind, yieldHandling, tt);
4512 0 : if (!inner)
4513 0 : return null();
4514 :
4515 0 : if (!handler.addSpreadProperty(literal, begin, inner))
4516 0 : return null();
4517 : } else {
4518 496 : TokenPos namePos = tokenStream.nextToken().pos;
4519 :
4520 : PropertyType propType;
4521 496 : Node propName = propertyName(yieldHandling, declKind, literal, &propType, &propAtom);
4522 496 : if (!propName)
4523 0 : return null();
4524 :
4525 496 : if (propType == PropertyType::Normal) {
4526 : // Handle e.g., |var {p: x} = o| and |var {p: x=0} = o|.
4527 :
4528 224 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
4529 0 : return null();
4530 :
4531 224 : Node binding = bindingIdentifierOrPattern(kind, yieldHandling, tt);
4532 224 : if (!binding)
4533 0 : return null();
4534 :
4535 : bool hasInitializer;
4536 224 : if (!tokenStream.matchToken(&hasInitializer, TOK_ASSIGN))
4537 0 : return null();
4538 :
4539 : Node bindingExpr = hasInitializer
4540 224 : ? bindingInitializer(binding, kind, yieldHandling)
4541 224 : : binding;
4542 224 : if (!bindingExpr)
4543 0 : return null();
4544 :
4545 224 : if (!handler.addPropertyDefinition(literal, propName, bindingExpr))
4546 0 : return null();
4547 272 : } else if (propType == PropertyType::Shorthand) {
4548 : // Handle e.g., |var {x, y} = o| as destructuring shorthand
4549 : // for |var {x: x, y: y} = o|.
4550 259 : MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt));
4551 :
4552 259 : Node binding = bindingIdentifier(kind, yieldHandling);
4553 259 : if (!binding)
4554 0 : return null();
4555 :
4556 259 : if (!handler.addShorthand(literal, propName, binding))
4557 0 : return null();
4558 13 : } else if (propType == PropertyType::CoverInitializedName) {
4559 : // Handle e.g., |var {x=1, y=2} = o| as destructuring
4560 : // shorthand with default values.
4561 13 : MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt));
4562 :
4563 13 : Node binding = bindingIdentifier(kind, yieldHandling);
4564 13 : if (!binding)
4565 0 : return null();
4566 :
4567 13 : tokenStream.consumeKnownToken(TOK_ASSIGN);
4568 :
4569 13 : Node bindingExpr = bindingInitializer(binding, kind, yieldHandling);
4570 13 : if (!bindingExpr)
4571 0 : return null();
4572 :
4573 13 : if (!handler.addPropertyDefinition(literal, propName, bindingExpr))
4574 0 : return null();
4575 : } else {
4576 0 : errorAt(namePos.begin, JSMSG_NO_VARIABLE_NAME);
4577 0 : return null();
4578 : }
4579 : }
4580 :
4581 : bool matched;
4582 496 : if (!tokenStream.matchToken(&matched, TOK_COMMA))
4583 0 : return null();
4584 496 : if (!matched)
4585 216 : break;
4586 280 : if (tt == TOK_TRIPLEDOT) {
4587 0 : error(JSMSG_REST_WITH_COMMA);
4588 0 : return null();
4589 : }
4590 : }
4591 :
4592 221 : MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::None,
4593 : reportMissingClosing(JSMSG_CURLY_AFTER_LIST,
4594 : JSMSG_CURLY_OPENED, begin));
4595 :
4596 221 : handler.setEndPosition(literal, pos().end);
4597 221 : return literal;
4598 : }
4599 :
4600 : template <class ParseHandler, typename CharT>
4601 : typename ParseHandler::Node
4602 91 : Parser<ParseHandler, CharT>::arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling)
4603 : {
4604 91 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB));
4605 :
4606 91 : if (!CheckRecursionLimit(context))
4607 0 : return null();
4608 :
4609 91 : uint32_t begin = pos().begin;
4610 91 : Node literal = handler.newArrayLiteral(begin);
4611 91 : if (!literal)
4612 0 : return null();
4613 :
4614 91 : uint32_t index = 0;
4615 91 : TokenStream::Modifier modifier = TokenStream::Operand;
4616 95 : for (; ; index++) {
4617 186 : if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) {
4618 0 : error(JSMSG_ARRAY_INIT_TOO_BIG);
4619 0 : return null();
4620 : }
4621 :
4622 : TokenKind tt;
4623 186 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
4624 0 : return null();
4625 :
4626 186 : if (tt == TOK_RB) {
4627 1 : tokenStream.ungetToken();
4628 1 : break;
4629 : }
4630 :
4631 185 : if (tt == TOK_COMMA) {
4632 5 : if (!handler.addElision(literal, pos()))
4633 0 : return null();
4634 180 : } else if (tt == TOK_TRIPLEDOT) {
4635 0 : uint32_t begin = pos().begin;
4636 :
4637 : TokenKind tt;
4638 0 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
4639 0 : return null();
4640 :
4641 0 : Node inner = bindingIdentifierOrPattern(kind, yieldHandling, tt);
4642 0 : if (!inner)
4643 0 : return null();
4644 :
4645 0 : if (!handler.addSpreadElement(literal, begin, inner))
4646 0 : return null();
4647 : } else {
4648 180 : Node binding = bindingIdentifierOrPattern(kind, yieldHandling, tt);
4649 180 : if (!binding)
4650 0 : return null();
4651 :
4652 : bool hasInitializer;
4653 180 : if (!tokenStream.matchToken(&hasInitializer, TOK_ASSIGN))
4654 0 : return null();
4655 :
4656 : Node element = hasInitializer
4657 180 : ? bindingInitializer(binding, kind, yieldHandling)
4658 180 : : binding;
4659 180 : if (!element)
4660 0 : return null();
4661 :
4662 180 : handler.addArrayElement(literal, element);
4663 : }
4664 :
4665 185 : if (tt != TOK_COMMA) {
4666 : // If we didn't already match TOK_COMMA in above case.
4667 : bool matched;
4668 180 : if (!tokenStream.matchToken(&matched, TOK_COMMA))
4669 0 : return null();
4670 180 : if (!matched) {
4671 90 : modifier = TokenStream::None;
4672 90 : break;
4673 : }
4674 90 : if (tt == TOK_TRIPLEDOT) {
4675 0 : error(JSMSG_REST_WITH_COMMA);
4676 0 : return null();
4677 : }
4678 : }
4679 : }
4680 :
4681 91 : MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RB, modifier,
4682 : reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
4683 : JSMSG_BRACKET_OPENED, begin));
4684 :
4685 91 : handler.setEndPosition(literal, pos().end);
4686 91 : return literal;
4687 : }
4688 :
4689 : template <class ParseHandler, typename CharT>
4690 : typename ParseHandler::Node
4691 293 : Parser<ParseHandler, CharT>::destructuringDeclaration(DeclarationKind kind,
4692 : YieldHandling yieldHandling,
4693 : TokenKind tt)
4694 : {
4695 293 : MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
4696 293 : MOZ_ASSERT(tt == TOK_LB || tt == TOK_LC);
4697 :
4698 : return tt == TOK_LB
4699 293 : ? arrayBindingPattern(kind, yieldHandling)
4700 293 : : objectBindingPattern(kind, yieldHandling);
4701 : }
4702 :
4703 : template <class ParseHandler, typename CharT>
4704 : typename ParseHandler::Node
4705 78 : Parser<ParseHandler, CharT>::destructuringDeclarationWithoutYieldOrAwait(DeclarationKind kind,
4706 : YieldHandling yieldHandling,
4707 : TokenKind tt)
4708 : {
4709 78 : uint32_t startYieldOffset = pc->lastYieldOffset;
4710 78 : uint32_t startAwaitOffset = pc->lastAwaitOffset;
4711 78 : Node res = destructuringDeclaration(kind, yieldHandling, tt);
4712 78 : if (res) {
4713 78 : if (pc->lastYieldOffset != startYieldOffset) {
4714 0 : errorAt(pc->lastYieldOffset, JSMSG_YIELD_IN_DEFAULT);
4715 0 : return null();
4716 : }
4717 78 : if (pc->lastAwaitOffset != startAwaitOffset) {
4718 0 : errorAt(pc->lastAwaitOffset, JSMSG_AWAIT_IN_DEFAULT);
4719 0 : return null();
4720 : }
4721 : }
4722 78 : return res;
4723 : }
4724 :
4725 : template <class ParseHandler, typename CharT>
4726 : typename ParseHandler::Node
4727 7206 : Parser<ParseHandler, CharT>::blockStatement(YieldHandling yieldHandling, unsigned errorNumber)
4728 : {
4729 7206 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
4730 7206 : uint32_t openedPos = pos().begin;
4731 :
4732 14412 : ParseContext::Statement stmt(pc, StatementKind::Block);
4733 14412 : ParseContext::Scope scope(this);
4734 7206 : if (!scope.init(pc))
4735 0 : return null();
4736 :
4737 7206 : Node list = statementList(yieldHandling);
4738 7206 : if (!list)
4739 0 : return null();
4740 :
4741 7206 : MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
4742 : reportMissingClosing(errorNumber, JSMSG_CURLY_OPENED,
4743 : openedPos));
4744 :
4745 7206 : return finishLexicalScope(scope, list);
4746 : }
4747 :
4748 : template <class ParseHandler, typename CharT>
4749 : typename ParseHandler::Node
4750 501 : Parser<ParseHandler, CharT>::expressionAfterForInOrOf(ParseNodeKind forHeadKind,
4751 : YieldHandling yieldHandling)
4752 : {
4753 501 : MOZ_ASSERT(forHeadKind == PNK_FORIN || forHeadKind == PNK_FOROF);
4754 : Node pn = forHeadKind == PNK_FOROF
4755 501 : ? assignExpr(InAllowed, yieldHandling, TripledotProhibited)
4756 501 : : expr(InAllowed, yieldHandling, TripledotProhibited);
4757 501 : return pn;
4758 : }
4759 :
4760 : template <class ParseHandler, typename CharT>
4761 : typename ParseHandler::Node
4762 215 : Parser<ParseHandler, CharT>::declarationPattern(Node decl, DeclarationKind declKind, TokenKind tt,
4763 : bool initialDeclaration,
4764 : YieldHandling yieldHandling,
4765 : ParseNodeKind* forHeadKind,
4766 : Node* forInOrOfExpression)
4767 : {
4768 215 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB) ||
4769 : tokenStream.isCurrentTokenType(TOK_LC));
4770 :
4771 215 : Node pattern = destructuringDeclaration(declKind, yieldHandling, tt);
4772 215 : if (!pattern)
4773 0 : return null();
4774 :
4775 215 : if (initialDeclaration && forHeadKind) {
4776 : bool isForIn, isForOf;
4777 60 : if (!matchInOrOf(&isForIn, &isForOf))
4778 60 : return null();
4779 :
4780 60 : if (isForIn) {
4781 0 : *forHeadKind = PNK_FORIN;
4782 60 : } else if (isForOf) {
4783 60 : *forHeadKind = PNK_FOROF;
4784 :
4785 : // Annex B.3.5 has different early errors for vars in for-of loops.
4786 60 : if (declKind == DeclarationKind::Var)
4787 0 : declKind = DeclarationKind::ForOfVar;
4788 : } else {
4789 0 : *forHeadKind = PNK_FORHEAD;
4790 : }
4791 :
4792 60 : if (*forHeadKind != PNK_FORHEAD) {
4793 60 : *forInOrOfExpression = expressionAfterForInOrOf(*forHeadKind, yieldHandling);
4794 60 : if (!*forInOrOfExpression)
4795 0 : return null();
4796 :
4797 60 : return pattern;
4798 : }
4799 : }
4800 :
4801 155 : MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_BAD_DESTRUCT_DECL);
4802 :
4803 155 : Node init = assignExpr(forHeadKind ? InProhibited : InAllowed,
4804 155 : yieldHandling, TripledotProhibited);
4805 155 : if (!init)
4806 0 : return null();
4807 :
4808 155 : handler.checkAndSetIsDirectRHSAnonFunction(init);
4809 :
4810 155 : if (forHeadKind) {
4811 : // For for(;;) declarations, consistency with |for (;| parsing requires
4812 : // that the ';' first be examined as Operand, even though absence of a
4813 : // binary operator (examined with modifier None) terminated |init|.
4814 : // For all other declarations, through ASI's infinite majesty, a next
4815 : // token on a new line would begin an expression.
4816 : // Similar to the case in initializerInNameDeclaration(), we need to
4817 : // peek at the next token when assignExpr() is a lazily parsed arrow
4818 : // function.
4819 : TokenKind ignored;
4820 0 : if (!tokenStream.peekToken(&ignored))
4821 0 : return null();
4822 0 : tokenStream.addModifierException(TokenStream::OperandIsNone);
4823 : }
4824 :
4825 155 : return handler.newBinary(PNK_ASSIGN, pattern, init);
4826 : }
4827 :
4828 : template <class ParseHandler, typename CharT>
4829 : bool
4830 10798 : Parser<ParseHandler, CharT>::initializerInNameDeclaration(Node decl, Node binding,
4831 : Handle<PropertyName*> name,
4832 : DeclarationKind declKind,
4833 : bool initialDeclaration,
4834 : YieldHandling yieldHandling,
4835 : ParseNodeKind* forHeadKind,
4836 : Node* forInOrOfExpression)
4837 : {
4838 10798 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_ASSIGN));
4839 :
4840 : uint32_t initializerOffset;
4841 10798 : if (!tokenStream.peekOffset(&initializerOffset, TokenStream::Operand))
4842 0 : return false;
4843 :
4844 10798 : Node initializer = assignExpr(forHeadKind ? InProhibited : InAllowed,
4845 10798 : yieldHandling, TripledotProhibited);
4846 10798 : if (!initializer)
4847 0 : return false;
4848 :
4849 10798 : handler.checkAndSetIsDirectRHSAnonFunction(initializer);
4850 :
4851 10798 : if (forHeadKind) {
4852 426 : if (initialDeclaration) {
4853 : bool isForIn, isForOf;
4854 412 : if (!matchInOrOf(&isForIn, &isForOf))
4855 0 : return false;
4856 :
4857 : // An initialized declaration can't appear in a for-of:
4858 : //
4859 : // for (var/let/const x = ... of ...); // BAD
4860 412 : if (isForOf) {
4861 0 : errorAt(initializerOffset, JSMSG_OF_AFTER_FOR_LOOP_DECL);
4862 0 : return false;
4863 : }
4864 :
4865 412 : if (isForIn) {
4866 : // Lexical declarations in for-in loops can't be initialized:
4867 : //
4868 : // for (let/const x = ... in ...); // BAD
4869 0 : if (DeclarationKindIsLexical(declKind)) {
4870 0 : errorAt(initializerOffset, JSMSG_IN_AFTER_LEXICAL_FOR_DECL);
4871 0 : return false;
4872 : }
4873 :
4874 : // This leaves only initialized for-in |var| declarations. ES6
4875 : // forbids these; later ES un-forbids in non-strict mode code.
4876 0 : *forHeadKind = PNK_FORIN;
4877 0 : if (!strictModeErrorAt(initializerOffset, JSMSG_INVALID_FOR_IN_DECL_WITH_INIT))
4878 0 : return false;
4879 :
4880 0 : *forInOrOfExpression = expressionAfterForInOrOf(PNK_FORIN, yieldHandling);
4881 0 : if (!*forInOrOfExpression)
4882 0 : return false;
4883 : } else {
4884 412 : *forHeadKind = PNK_FORHEAD;
4885 : }
4886 : } else {
4887 14 : MOZ_ASSERT(*forHeadKind == PNK_FORHEAD);
4888 :
4889 : // In the very rare case of Parser::assignExpr consuming an
4890 : // ArrowFunction with block body, when full-parsing with the arrow
4891 : // function being a skipped lazy inner function, we don't have
4892 : // lookahead for the next token. Do a one-off peek here to be
4893 : // consistent with what Parser::matchForInOrOf does in the other
4894 : // arm of this |if|.
4895 : //
4896 : // If you think this all sounds pretty code-smelly, you're almost
4897 : // certainly correct.
4898 : TokenKind ignored;
4899 14 : if (!tokenStream.peekToken(&ignored))
4900 0 : return false;
4901 : }
4902 :
4903 426 : if (*forHeadKind == PNK_FORHEAD) {
4904 : // Per Parser::forHeadStart, the semicolon in |for (;| is
4905 : // ultimately gotten as Operand. But initializer expressions
4906 : // terminate with the absence of an operator gotten as None,
4907 : // so we need an exception.
4908 426 : tokenStream.addModifierException(TokenStream::OperandIsNone);
4909 : }
4910 : }
4911 :
4912 10798 : return handler.finishInitializerAssignment(binding, initializer);
4913 : }
4914 :
4915 : template <class ParseHandler, typename CharT>
4916 : typename ParseHandler::Node
4917 11787 : Parser<ParseHandler, CharT>::declarationName(Node decl, DeclarationKind declKind, TokenKind tt,
4918 : bool initialDeclaration, YieldHandling yieldHandling,
4919 : ParseNodeKind* forHeadKind, Node* forInOrOfExpression)
4920 : {
4921 : // Anything other than possible identifier is an error.
4922 11787 : if (!TokenKindIsPossibleIdentifier(tt)) {
4923 0 : error(JSMSG_NO_VARIABLE_NAME);
4924 0 : return null();
4925 : }
4926 :
4927 23574 : RootedPropertyName name(context, bindingIdentifier(yieldHandling));
4928 11787 : if (!name)
4929 0 : return null();
4930 :
4931 11787 : Node binding = newName(name);
4932 11787 : if (!binding)
4933 0 : return null();
4934 :
4935 11787 : TokenPos namePos = pos();
4936 :
4937 : // The '=' context after a variable name in a declaration is an opportunity
4938 : // for ASI, and thus for the next token to start an ExpressionStatement:
4939 : //
4940 : // var foo // VariableDeclaration
4941 : // /bar/g; // ExpressionStatement
4942 : //
4943 : // Therefore get the token here as Operand.
4944 : bool matched;
4945 11787 : if (!tokenStream.matchToken(&matched, TOK_ASSIGN, TokenStream::Operand))
4946 0 : return null();
4947 :
4948 11787 : if (matched) {
4949 10798 : if (!initializerInNameDeclaration(decl, binding, name, declKind, initialDeclaration,
4950 : yieldHandling, forHeadKind, forInOrOfExpression))
4951 : {
4952 0 : return null();
4953 : }
4954 : } else {
4955 989 : tokenStream.addModifierException(TokenStream::NoneIsOperand);
4956 :
4957 989 : if (initialDeclaration && forHeadKind) {
4958 : bool isForIn, isForOf;
4959 441 : if (!matchInOrOf(&isForIn, &isForOf))
4960 0 : return null();
4961 :
4962 441 : if (isForIn) {
4963 64 : *forHeadKind = PNK_FORIN;
4964 377 : } else if (isForOf) {
4965 377 : *forHeadKind = PNK_FOROF;
4966 :
4967 : // Annex B.3.5 has different early errors for vars in for-of loops.
4968 377 : if (declKind == DeclarationKind::Var)
4969 16 : declKind = DeclarationKind::ForOfVar;
4970 : } else {
4971 0 : *forHeadKind = PNK_FORHEAD;
4972 : }
4973 : }
4974 :
4975 989 : if (forHeadKind && *forHeadKind != PNK_FORHEAD) {
4976 441 : *forInOrOfExpression = expressionAfterForInOrOf(*forHeadKind, yieldHandling);
4977 882 : if (!*forInOrOfExpression)
4978 0 : return null();
4979 : } else {
4980 : // Normal const declarations, and const declarations in for(;;)
4981 : // heads, must be initialized.
4982 548 : if (declKind == DeclarationKind::Const) {
4983 0 : errorAt(namePos.begin, JSMSG_BAD_CONST_DECL);
4984 0 : return null();
4985 : }
4986 : }
4987 : }
4988 :
4989 : // Note the declared name after knowing whether or not we are in a for-of
4990 : // loop, due to special early error semantics in Annex B.3.5.
4991 11787 : if (!noteDeclaredName(name, declKind, namePos))
4992 0 : return null();
4993 :
4994 11787 : return binding;
4995 : }
4996 :
4997 : template <class ParseHandler, typename CharT>
4998 : typename ParseHandler::Node
4999 11867 : Parser<ParseHandler, CharT>::declarationList(YieldHandling yieldHandling,
5000 : ParseNodeKind kind,
5001 : ParseNodeKind* forHeadKind /* = nullptr */,
5002 : Node* forInOrOfExpression /* = nullptr */)
5003 : {
5004 11867 : MOZ_ASSERT(kind == PNK_VAR || kind == PNK_LET || kind == PNK_CONST);
5005 :
5006 : JSOp op;
5007 : DeclarationKind declKind;
5008 11867 : switch (kind) {
5009 : case PNK_VAR:
5010 5183 : op = JSOP_DEFVAR;
5011 5183 : declKind = DeclarationKind::Var;
5012 5183 : break;
5013 : case PNK_CONST:
5014 1428 : op = JSOP_DEFCONST;
5015 1428 : declKind = DeclarationKind::Const;
5016 1428 : break;
5017 : case PNK_LET:
5018 5256 : op = JSOP_DEFLET;
5019 5256 : declKind = DeclarationKind::Let;
5020 5256 : break;
5021 : default:
5022 0 : MOZ_CRASH("Unknown declaration kind");
5023 : }
5024 :
5025 11867 : Node decl = handler.newDeclarationList(kind, pos(), op);
5026 11867 : if (!decl)
5027 0 : return null();
5028 :
5029 : bool matched;
5030 11867 : bool initialDeclaration = true;
5031 11636 : do {
5032 12002 : MOZ_ASSERT_IF(!initialDeclaration && forHeadKind,
5033 : *forHeadKind == PNK_FORHEAD);
5034 :
5035 : TokenKind tt;
5036 12002 : if (!tokenStream.getToken(&tt))
5037 0 : return null();
5038 :
5039 23931 : Node binding = (tt == TOK_LB || tt == TOK_LC)
5040 24004 : ? declarationPattern(decl, declKind, tt, initialDeclaration, yieldHandling,
5041 : forHeadKind, forInOrOfExpression)
5042 11787 : : declarationName(decl, declKind, tt, initialDeclaration, yieldHandling,
5043 12002 : forHeadKind, forInOrOfExpression);
5044 12002 : if (!binding)
5045 0 : return null();
5046 :
5047 12002 : handler.addList(decl, binding);
5048 :
5049 12002 : if (forHeadKind && *forHeadKind != PNK_FORHEAD)
5050 501 : break;
5051 :
5052 11501 : initialDeclaration = false;
5053 :
5054 11501 : if (!tokenStream.matchToken(&matched, TOK_COMMA))
5055 0 : return null();
5056 : } while (matched);
5057 :
5058 11867 : return decl;
5059 : }
5060 :
5061 : template <class ParseHandler, typename CharT>
5062 : typename ParseHandler::Node
5063 6034 : Parser<ParseHandler, CharT>::lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind)
5064 : {
5065 6034 : MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let);
5066 :
5067 : /*
5068 : * Parse body-level lets without a new block object. ES6 specs
5069 : * that an execution environment's initial lexical environment
5070 : * is the VariableEnvironment, i.e., body-level lets are in
5071 : * the same environment record as vars.
5072 : *
5073 : * However, they cannot be parsed exactly as vars, as ES6
5074 : * requires that uninitialized lets throw ReferenceError on use.
5075 : *
5076 : * See 8.1.1.1.6 and the note in 13.2.1.
5077 : */
5078 6034 : Node decl = declarationList(yieldHandling,
5079 6034 : kind == DeclarationKind::Const ? PNK_CONST : PNK_LET);
5080 6034 : if (!decl || !matchOrInsertSemicolonAfterExpression())
5081 0 : return null();
5082 :
5083 6034 : return decl;
5084 : }
5085 :
5086 : template <>
5087 : bool
5088 0 : Parser<FullParseHandler, char16_t>::namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet)
5089 : {
5090 0 : if (tt == TOK_LC) {
5091 : while (true) {
5092 : // Handle the forms |import {} from 'a'| and
5093 : // |import { ..., } from 'a'| (where ... is non empty), by
5094 : // escaping the loop early if the next token is }.
5095 0 : if (!tokenStream.getToken(&tt))
5096 0 : return false;
5097 :
5098 0 : if (tt == TOK_RC)
5099 0 : break;
5100 :
5101 0 : if (!TokenKindIsPossibleIdentifierName(tt)) {
5102 0 : error(JSMSG_NO_IMPORT_NAME);
5103 0 : return false;
5104 : }
5105 :
5106 0 : Rooted<PropertyName*> importName(context, tokenStream.currentName());
5107 0 : TokenPos importNamePos = pos();
5108 :
5109 : bool matched;
5110 0 : if (!tokenStream.matchToken(&matched, TOK_AS))
5111 0 : return null();
5112 :
5113 0 : if (matched) {
5114 : TokenKind afterAs;
5115 0 : if (!tokenStream.getToken(&afterAs))
5116 0 : return false;
5117 :
5118 0 : if (!TokenKindIsPossibleIdentifierName(afterAs)) {
5119 0 : error(JSMSG_NO_BINDING_NAME);
5120 0 : return false;
5121 : }
5122 : } else {
5123 : // Keywords cannot be bound to themselves, so an import name
5124 : // that is a keyword is a syntax error if it is not followed
5125 : // by the keyword 'as'.
5126 : // See the ImportSpecifier production in ES6 section 15.2.2.
5127 0 : if (IsKeyword(importName)) {
5128 0 : error(JSMSG_AS_AFTER_RESERVED_WORD, ReservedWordToCharZ(importName));
5129 0 : return false;
5130 : }
5131 : }
5132 :
5133 0 : RootedPropertyName bindingAtom(context, importedBinding());
5134 0 : if (!bindingAtom)
5135 0 : return false;
5136 :
5137 0 : Node bindingName = newName(bindingAtom);
5138 0 : if (!bindingName)
5139 0 : return false;
5140 0 : if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos()))
5141 0 : return false;
5142 :
5143 0 : Node importNameNode = newName(importName, importNamePos);
5144 0 : if (!importNameNode)
5145 0 : return false;
5146 :
5147 0 : Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importNameNode, bindingName);
5148 0 : if (!importSpec)
5149 0 : return false;
5150 :
5151 0 : handler.addList(importSpecSet, importSpec);
5152 :
5153 : TokenKind next;
5154 0 : if (!tokenStream.getToken(&next))
5155 0 : return false;
5156 :
5157 0 : if (next == TOK_RC)
5158 0 : break;
5159 :
5160 0 : if (next != TOK_COMMA) {
5161 0 : error(JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
5162 0 : return false;
5163 : }
5164 0 : }
5165 : } else {
5166 0 : MOZ_ASSERT(tt == TOK_MUL);
5167 :
5168 0 : MUST_MATCH_TOKEN(TOK_AS, JSMSG_AS_AFTER_IMPORT_STAR);
5169 :
5170 0 : MUST_MATCH_TOKEN_FUNC(TokenKindIsPossibleIdentifierName, JSMSG_NO_BINDING_NAME);
5171 :
5172 0 : Node importName = newName(context->names().star);
5173 0 : if (!importName)
5174 0 : return false;
5175 :
5176 : // Namespace imports are are not indirect bindings but lexical
5177 : // definitions that hold a module namespace object. They are treated
5178 : // as const variables which are initialized during the
5179 : // ModuleDeclarationInstantiation step.
5180 0 : RootedPropertyName bindingName(context, importedBinding());
5181 0 : if (!bindingName)
5182 0 : return false;
5183 0 : Node bindingNameNode = newName(bindingName);
5184 0 : if (!bindingNameNode)
5185 0 : return false;
5186 0 : if (!noteDeclaredName(bindingName, DeclarationKind::Const, pos()))
5187 0 : return false;
5188 :
5189 : // The namespace import name is currently required to live on the
5190 : // environment.
5191 0 : pc->varScope().lookupDeclaredName(bindingName)->value()->setClosedOver();
5192 :
5193 0 : Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingNameNode);
5194 0 : if (!importSpec)
5195 0 : return false;
5196 :
5197 0 : handler.addList(importSpecSet, importSpec);
5198 : }
5199 :
5200 0 : return true;
5201 : }
5202 :
5203 : template<>
5204 : bool
5205 0 : Parser<SyntaxParseHandler, char16_t>::namedImportsOrNamespaceImport(TokenKind tt,
5206 : Node importSpecSet)
5207 : {
5208 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5209 0 : return false;
5210 : }
5211 :
5212 : template<>
5213 : ParseNode*
5214 0 : Parser<FullParseHandler, char16_t>::importDeclaration()
5215 : {
5216 0 : MOZ_ASSERT(tokenStream.currentToken().type == TOK_IMPORT);
5217 :
5218 0 : if (!pc->atModuleLevel()) {
5219 0 : error(JSMSG_IMPORT_DECL_AT_TOP_LEVEL);
5220 0 : return null();
5221 : }
5222 :
5223 0 : uint32_t begin = pos().begin;
5224 : TokenKind tt;
5225 0 : if (!tokenStream.getToken(&tt))
5226 0 : return null();
5227 :
5228 0 : Node importSpecSet = handler.newList(PNK_IMPORT_SPEC_LIST, pos());
5229 0 : if (!importSpecSet)
5230 0 : return null();
5231 :
5232 0 : if (tt == TOK_STRING) {
5233 : // Handle the form |import 'a'| by leaving the list empty. This is
5234 : // equivalent to |import {} from 'a'|.
5235 0 : importSpecSet->pn_pos.end = importSpecSet->pn_pos.begin;
5236 : } else {
5237 0 : if (tt == TOK_LC || tt == TOK_MUL) {
5238 0 : if (!namedImportsOrNamespaceImport(tt, importSpecSet))
5239 0 : return null();
5240 0 : } else if (TokenKindIsPossibleIdentifierName(tt)) {
5241 : // Handle the form |import a from 'b'|, by adding a single import
5242 : // specifier to the list, with 'default' as the import name and
5243 : // 'a' as the binding name. This is equivalent to
5244 : // |import { default as a } from 'b'|.
5245 0 : Node importName = newName(context->names().default_);
5246 0 : if (!importName)
5247 0 : return null();
5248 :
5249 0 : RootedPropertyName bindingAtom(context, importedBinding());
5250 0 : if (!bindingAtom)
5251 0 : return null();
5252 :
5253 0 : Node bindingName = newName(bindingAtom);
5254 0 : if (!bindingName)
5255 0 : return null();
5256 :
5257 0 : if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos()))
5258 0 : return null();
5259 :
5260 0 : Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
5261 0 : if (!importSpec)
5262 0 : return null();
5263 :
5264 0 : handler.addList(importSpecSet, importSpec);
5265 :
5266 0 : if (!tokenStream.peekToken(&tt))
5267 0 : return null();
5268 :
5269 0 : if (tt == TOK_COMMA) {
5270 0 : tokenStream.consumeKnownToken(tt);
5271 0 : if (!tokenStream.getToken(&tt))
5272 0 : return null();
5273 :
5274 0 : if (tt != TOK_LC && tt != TOK_MUL) {
5275 0 : error(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT);
5276 0 : return null();
5277 : }
5278 :
5279 0 : if (!namedImportsOrNamespaceImport(tt, importSpecSet))
5280 0 : return null();
5281 : }
5282 : } else {
5283 0 : error(JSMSG_DECLARATION_AFTER_IMPORT);
5284 0 : return null();
5285 : }
5286 :
5287 0 : MUST_MATCH_TOKEN(TOK_FROM, JSMSG_FROM_AFTER_IMPORT_CLAUSE);
5288 :
5289 0 : MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM);
5290 : }
5291 :
5292 0 : Node moduleSpec = stringLiteral();
5293 0 : if (!moduleSpec)
5294 0 : return null();
5295 :
5296 0 : if (!matchOrInsertSemicolonAfterNonExpression())
5297 0 : return null();
5298 :
5299 : ParseNode* node =
5300 0 : handler.newImportDeclaration(importSpecSet, moduleSpec, TokenPos(begin, pos().end));
5301 0 : if (!node || !pc->sc()->asModuleContext()->builder.processImport(node))
5302 0 : return null();
5303 :
5304 0 : return node;
5305 : }
5306 :
5307 : template<>
5308 : SyntaxParseHandler::Node
5309 0 : Parser<SyntaxParseHandler, char16_t>::importDeclaration()
5310 : {
5311 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5312 0 : return SyntaxParseHandler::NodeFailure;
5313 : }
5314 :
5315 : template<>
5316 : bool
5317 0 : Parser<FullParseHandler, char16_t>::checkExportedName(JSAtom* exportName)
5318 : {
5319 0 : if (!pc->sc()->asModuleContext()->builder.hasExportedName(exportName))
5320 0 : return true;
5321 :
5322 0 : JSAutoByteString str;
5323 0 : if (!AtomToPrintableString(context, exportName, &str))
5324 0 : return false;
5325 :
5326 0 : error(JSMSG_DUPLICATE_EXPORT_NAME, str.ptr());
5327 0 : return false;
5328 : }
5329 :
5330 : template<>
5331 : bool
5332 0 : Parser<SyntaxParseHandler, char16_t>::checkExportedName(JSAtom* exportName)
5333 : {
5334 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5335 0 : return false;
5336 : }
5337 :
5338 : template<>
5339 : bool
5340 0 : Parser<FullParseHandler, char16_t>::checkExportedNamesForDeclaration(ParseNode* node)
5341 : {
5342 0 : MOZ_ASSERT(node->isArity(PN_LIST));
5343 0 : for (ParseNode* binding = node->pn_head; binding; binding = binding->pn_next) {
5344 0 : if (binding->isKind(PNK_ASSIGN))
5345 0 : binding = binding->pn_left;
5346 0 : MOZ_ASSERT(binding->isKind(PNK_NAME));
5347 0 : if (!checkExportedName(binding->pn_atom))
5348 0 : return false;
5349 : }
5350 :
5351 0 : return true;
5352 : }
5353 :
5354 : template<>
5355 : bool
5356 0 : Parser<SyntaxParseHandler, char16_t>::checkExportedNamesForDeclaration(Node node)
5357 : {
5358 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5359 0 : return false;
5360 : }
5361 :
5362 : template<>
5363 : bool
5364 0 : Parser<FullParseHandler, char16_t>::checkExportedNameForClause(ParseNode* node)
5365 : {
5366 0 : return checkExportedName(node->pn_atom);
5367 : }
5368 :
5369 : template<>
5370 : bool
5371 0 : Parser<SyntaxParseHandler, char16_t>::checkExportedNameForClause(Node node)
5372 : {
5373 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5374 0 : return false;
5375 : }
5376 :
5377 : template<>
5378 : bool
5379 0 : Parser<FullParseHandler, char16_t>::checkExportedNameForFunction(ParseNode* node)
5380 : {
5381 0 : return checkExportedName(node->pn_funbox->function()->explicitName());
5382 : }
5383 :
5384 : template<>
5385 : bool
5386 0 : Parser<SyntaxParseHandler, char16_t>::checkExportedNameForFunction(Node node)
5387 : {
5388 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5389 0 : return false;
5390 : }
5391 :
5392 : template<>
5393 : bool
5394 0 : Parser<FullParseHandler, char16_t>::checkExportedNameForClass(ParseNode* node)
5395 : {
5396 0 : const ClassNode& cls = node->as<ClassNode>();
5397 0 : MOZ_ASSERT(cls.names());
5398 0 : return checkExportedName(cls.names()->innerBinding()->pn_atom);
5399 : }
5400 :
5401 : template<>
5402 : bool
5403 0 : Parser<SyntaxParseHandler, char16_t>::checkExportedNameForClass(Node node)
5404 : {
5405 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5406 0 : return false;
5407 : }
5408 :
5409 : template<>
5410 : bool
5411 0 : Parser<FullParseHandler, char16_t>::processExport(ParseNode* node)
5412 : {
5413 0 : return pc->sc()->asModuleContext()->builder.processExport(node);
5414 : }
5415 :
5416 : template<>
5417 : bool
5418 0 : Parser<SyntaxParseHandler, char16_t>::processExport(Node node)
5419 : {
5420 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5421 0 : return false;
5422 : }
5423 :
5424 : template<>
5425 : bool
5426 0 : Parser<FullParseHandler, char16_t>::processExportFrom(ParseNode* node)
5427 : {
5428 0 : return pc->sc()->asModuleContext()->builder.processExportFrom(node);
5429 : }
5430 :
5431 : template<>
5432 : bool
5433 0 : Parser<SyntaxParseHandler, char16_t>::processExportFrom(Node node)
5434 : {
5435 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5436 0 : return false;
5437 : }
5438 :
5439 : template <class ParseHandler, typename CharT>
5440 : typename ParseHandler::Node
5441 0 : Parser<ParseHandler, CharT>::exportFrom(uint32_t begin, Node specList)
5442 : {
5443 0 : if (!abortIfSyntaxParser())
5444 0 : return null();
5445 :
5446 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FROM));
5447 :
5448 0 : if (!abortIfSyntaxParser())
5449 0 : return null();
5450 :
5451 0 : MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM);
5452 :
5453 0 : Node moduleSpec = stringLiteral();
5454 0 : if (!moduleSpec)
5455 0 : return null();
5456 :
5457 0 : if (!matchOrInsertSemicolonAfterNonExpression())
5458 0 : return null();
5459 :
5460 0 : Node node = handler.newExportFromDeclaration(begin, specList, moduleSpec);
5461 0 : if (!node)
5462 0 : return null();
5463 :
5464 0 : if (!processExportFrom(node))
5465 0 : return null();
5466 :
5467 0 : return node;
5468 : }
5469 :
5470 : template <class ParseHandler, typename CharT>
5471 : typename ParseHandler::Node
5472 0 : Parser<ParseHandler, CharT>::exportBatch(uint32_t begin)
5473 : {
5474 0 : if (!abortIfSyntaxParser())
5475 0 : return null();
5476 :
5477 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_MUL));
5478 :
5479 0 : Node kid = handler.newList(PNK_EXPORT_SPEC_LIST, pos());
5480 0 : if (!kid)
5481 0 : return null();
5482 :
5483 : // Handle the form |export *| by adding a special export batch
5484 : // specifier to the list.
5485 0 : Node exportSpec = handler.newNullary(PNK_EXPORT_BATCH_SPEC, JSOP_NOP, pos());
5486 0 : if (!exportSpec)
5487 0 : return null();
5488 :
5489 0 : handler.addList(kid, exportSpec);
5490 :
5491 0 : MUST_MATCH_TOKEN(TOK_FROM, JSMSG_FROM_AFTER_EXPORT_STAR);
5492 :
5493 0 : return exportFrom(begin, kid);
5494 : }
5495 :
5496 : template<>
5497 : bool
5498 0 : Parser<FullParseHandler, char16_t>::checkLocalExportNames(ParseNode* node)
5499 : {
5500 : // ES 2017 draft 15.2.3.1.
5501 0 : for (ParseNode* next = node->pn_head; next; next = next->pn_next) {
5502 0 : ParseNode* name = next->pn_left;
5503 0 : MOZ_ASSERT(name->isKind(PNK_NAME));
5504 :
5505 0 : RootedPropertyName ident(context, name->pn_atom->asPropertyName());
5506 0 : if (!checkLocalExportName(ident, name->pn_pos.begin))
5507 0 : return false;
5508 : }
5509 :
5510 0 : return true;
5511 : }
5512 :
5513 : template<>
5514 : bool
5515 0 : Parser<SyntaxParseHandler, char16_t>::checkLocalExportNames(Node node)
5516 : {
5517 0 : MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5518 0 : return false;
5519 : }
5520 :
5521 : template <class ParseHandler, typename CharT>
5522 : typename ParseHandler::Node
5523 0 : Parser<ParseHandler, CharT>::exportClause(uint32_t begin)
5524 : {
5525 0 : if (!abortIfSyntaxParser())
5526 0 : return null();
5527 :
5528 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
5529 :
5530 0 : Node kid = handler.newList(PNK_EXPORT_SPEC_LIST, pos());
5531 0 : if (!kid)
5532 0 : return null();
5533 :
5534 : TokenKind tt;
5535 0 : while (true) {
5536 : // Handle the forms |export {}| and |export { ..., }| (where ... is non
5537 : // empty), by escaping the loop early if the next token is }.
5538 0 : if (!tokenStream.getToken(&tt))
5539 0 : return null();
5540 :
5541 0 : if (tt == TOK_RC)
5542 0 : break;
5543 :
5544 0 : if (!TokenKindIsPossibleIdentifierName(tt)) {
5545 0 : error(JSMSG_NO_BINDING_NAME);
5546 0 : return null();
5547 : }
5548 :
5549 0 : Node bindingName = newName(tokenStream.currentName());
5550 0 : if (!bindingName)
5551 0 : return null();
5552 :
5553 : bool foundAs;
5554 0 : if (!tokenStream.matchToken(&foundAs, TOK_AS))
5555 0 : return null();
5556 0 : if (foundAs)
5557 0 : MUST_MATCH_TOKEN_FUNC(TokenKindIsPossibleIdentifierName, JSMSG_NO_EXPORT_NAME);
5558 :
5559 0 : Node exportName = newName(tokenStream.currentName());
5560 0 : if (!exportName)
5561 0 : return null();
5562 :
5563 0 : if (!checkExportedNameForClause(exportName))
5564 0 : return null();
5565 :
5566 0 : Node exportSpec = handler.newBinary(PNK_EXPORT_SPEC, bindingName, exportName);
5567 0 : if (!exportSpec)
5568 0 : return null();
5569 :
5570 0 : handler.addList(kid, exportSpec);
5571 :
5572 : TokenKind next;
5573 0 : if (!tokenStream.getToken(&next))
5574 0 : return null();
5575 :
5576 0 : if (next == TOK_RC)
5577 0 : break;
5578 :
5579 0 : if (next != TOK_COMMA) {
5580 0 : error(JSMSG_RC_AFTER_EXPORT_SPEC_LIST);
5581 0 : return null();
5582 : }
5583 : }
5584 :
5585 : // Careful! If |from| follows, even on a new line, it must start a
5586 : // FromClause:
5587 : //
5588 : // export { x }
5589 : // from "foo"; // a single ExportDeclaration
5590 : //
5591 : // But if it doesn't, we might have an ASI opportunity in Operand context:
5592 : //
5593 : // export { x } // ExportDeclaration, terminated by ASI
5594 : // fro\u006D // ExpressionStatement, the name "from"
5595 : //
5596 : // In that case let matchOrInsertSemicolonAfterNonExpression sort out ASI
5597 : // or any necessary error.
5598 : bool matched;
5599 0 : if (!tokenStream.matchToken(&matched, TOK_FROM, TokenStream::Operand))
5600 0 : return null();
5601 :
5602 0 : if (matched)
5603 0 : return exportFrom(begin, kid);
5604 :
5605 0 : if (!matchOrInsertSemicolonAfterNonExpression())
5606 0 : return null();
5607 :
5608 0 : if (!checkLocalExportNames(kid))
5609 0 : return null();
5610 :
5611 0 : Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end));
5612 0 : if (!node)
5613 0 : return null();
5614 :
5615 0 : if (!processExport(node))
5616 0 : return null();
5617 :
5618 0 : return node;
5619 : }
5620 :
5621 : template <class ParseHandler, typename CharT>
5622 : typename ParseHandler::Node
5623 0 : Parser<ParseHandler, CharT>::exportVariableStatement(uint32_t begin)
5624 : {
5625 0 : if (!abortIfSyntaxParser())
5626 0 : return null();
5627 :
5628 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_VAR));
5629 :
5630 0 : Node kid = declarationList(YieldIsName, PNK_VAR);
5631 0 : if (!kid)
5632 0 : return null();
5633 0 : if (!matchOrInsertSemicolonAfterExpression())
5634 0 : return null();
5635 0 : if (!checkExportedNamesForDeclaration(kid))
5636 0 : return null();
5637 :
5638 0 : Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end));
5639 0 : if (!node)
5640 0 : return null();
5641 :
5642 0 : if (!processExport(node))
5643 0 : return null();
5644 :
5645 0 : return node;
5646 : }
5647 :
5648 : template <class ParseHandler, typename CharT>
5649 : typename ParseHandler::Node
5650 0 : Parser<ParseHandler, CharT>::exportFunctionDeclaration(uint32_t begin, uint32_t toStringStart,
5651 : FunctionAsyncKind asyncKind /* = SyncFunction */)
5652 : {
5653 0 : if (!abortIfSyntaxParser())
5654 0 : return null();
5655 :
5656 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
5657 :
5658 0 : Node kid = functionStmt(toStringStart, YieldIsKeyword, NameRequired, asyncKind);
5659 0 : if (!kid)
5660 0 : return null();
5661 :
5662 0 : if (!checkExportedNameForFunction(kid))
5663 0 : return null();
5664 :
5665 0 : Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end));
5666 0 : if (!node)
5667 0 : return null();
5668 :
5669 0 : if (!processExport(node))
5670 0 : return null();
5671 :
5672 0 : return node;
5673 : }
5674 :
5675 : template <class ParseHandler, typename CharT>
5676 : typename ParseHandler::Node
5677 0 : Parser<ParseHandler, CharT>::exportClassDeclaration(uint32_t begin)
5678 : {
5679 0 : if (!abortIfSyntaxParser())
5680 0 : return null();
5681 :
5682 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS));
5683 :
5684 0 : Node kid = classDefinition(YieldIsKeyword, ClassStatement, NameRequired);
5685 0 : if (!kid)
5686 0 : return null();
5687 :
5688 0 : if (!checkExportedNameForClass(kid))
5689 0 : return null();
5690 :
5691 0 : Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end));
5692 0 : if (!node)
5693 0 : return null();
5694 :
5695 0 : if (!processExport(node))
5696 0 : return null();
5697 :
5698 0 : return node;
5699 : }
5700 :
5701 : template <class ParseHandler, typename CharT>
5702 : typename ParseHandler::Node
5703 0 : Parser<ParseHandler, CharT>::exportLexicalDeclaration(uint32_t begin, DeclarationKind kind)
5704 : {
5705 0 : if (!abortIfSyntaxParser())
5706 0 : return null();
5707 :
5708 0 : MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let);
5709 0 : MOZ_ASSERT_IF(kind == DeclarationKind::Const, tokenStream.isCurrentTokenType(TOK_CONST));
5710 0 : MOZ_ASSERT_IF(kind == DeclarationKind::Let, tokenStream.isCurrentTokenType(TOK_LET));
5711 :
5712 0 : Node kid = lexicalDeclaration(YieldIsName, kind);
5713 0 : if (!kid)
5714 0 : return null();
5715 0 : if (!checkExportedNamesForDeclaration(kid))
5716 0 : return null();
5717 :
5718 0 : Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end));
5719 0 : if (!node)
5720 0 : return null();
5721 :
5722 0 : if (!processExport(node))
5723 0 : return null();
5724 :
5725 0 : return node;
5726 : }
5727 :
5728 : template <class ParseHandler, typename CharT>
5729 : typename ParseHandler::Node
5730 0 : Parser<ParseHandler, CharT>::exportDefaultFunctionDeclaration(uint32_t begin,
5731 : uint32_t toStringStart,
5732 : FunctionAsyncKind asyncKind /* = SyncFunction */)
5733 : {
5734 0 : if (!abortIfSyntaxParser())
5735 0 : return null();
5736 :
5737 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
5738 :
5739 0 : Node kid = functionStmt(toStringStart, YieldIsKeyword, AllowDefaultName, asyncKind);
5740 0 : if (!kid)
5741 0 : return null();
5742 :
5743 0 : Node node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end));
5744 0 : if (!node)
5745 0 : return null();
5746 :
5747 0 : if (!processExport(node))
5748 0 : return null();
5749 :
5750 0 : return node;
5751 : }
5752 :
5753 : template <class ParseHandler, typename CharT>
5754 : typename ParseHandler::Node
5755 0 : Parser<ParseHandler, CharT>::exportDefaultClassDeclaration(uint32_t begin)
5756 : {
5757 0 : if (!abortIfSyntaxParser())
5758 0 : return null();
5759 :
5760 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS));
5761 :
5762 0 : Node kid = classDefinition(YieldIsKeyword, ClassStatement, AllowDefaultName);
5763 0 : if (!kid)
5764 0 : return null();
5765 :
5766 0 : Node node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end));
5767 0 : if (!node)
5768 0 : return null();
5769 :
5770 0 : if (!processExport(node))
5771 0 : return null();
5772 :
5773 0 : return node;
5774 : }
5775 :
5776 : template <class ParseHandler, typename CharT>
5777 : typename ParseHandler::Node
5778 0 : Parser<ParseHandler, CharT>::exportDefaultAssignExpr(uint32_t begin)
5779 : {
5780 0 : if (!abortIfSyntaxParser())
5781 0 : return null();
5782 :
5783 0 : RootedPropertyName name(context, context->names().starDefaultStar);
5784 0 : Node nameNode = newName(name);
5785 0 : if (!nameNode)
5786 0 : return null();
5787 0 : if (!noteDeclaredName(name, DeclarationKind::Const, pos()))
5788 0 : return null();
5789 :
5790 0 : Node kid = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited);
5791 0 : if (!kid)
5792 0 : return null();
5793 0 : if (!matchOrInsertSemicolonAfterExpression())
5794 0 : return null();
5795 :
5796 0 : Node node = handler.newExportDefaultDeclaration(kid, nameNode, TokenPos(begin, pos().end));
5797 0 : if (!node)
5798 0 : return null();
5799 :
5800 0 : if (!processExport(node))
5801 0 : return null();
5802 :
5803 0 : return node;
5804 : }
5805 :
5806 : template <class ParseHandler, typename CharT>
5807 : typename ParseHandler::Node
5808 0 : Parser<ParseHandler, CharT>::exportDefault(uint32_t begin)
5809 : {
5810 0 : if (!abortIfSyntaxParser())
5811 0 : return null();
5812 :
5813 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_DEFAULT));
5814 :
5815 : TokenKind tt;
5816 0 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
5817 0 : return null();
5818 :
5819 0 : if (!checkExportedName(context->names().default_))
5820 0 : return null();
5821 :
5822 0 : switch (tt) {
5823 : case TOK_FUNCTION:
5824 0 : return exportDefaultFunctionDeclaration(begin, pos().begin);
5825 :
5826 : case TOK_ASYNC: {
5827 0 : TokenKind nextSameLine = TOK_EOF;
5828 0 : if (!tokenStream.peekTokenSameLine(&nextSameLine))
5829 0 : return null();
5830 :
5831 0 : if (nextSameLine == TOK_FUNCTION) {
5832 0 : uint32_t toStringStart = pos().begin;
5833 0 : tokenStream.consumeKnownToken(TOK_FUNCTION);
5834 0 : return exportDefaultFunctionDeclaration(begin, toStringStart, AsyncFunction);
5835 : }
5836 :
5837 0 : tokenStream.ungetToken();
5838 0 : return exportDefaultAssignExpr(begin);
5839 : }
5840 :
5841 : case TOK_CLASS:
5842 0 : return exportDefaultClassDeclaration(begin);
5843 :
5844 : default:
5845 0 : tokenStream.ungetToken();
5846 0 : return exportDefaultAssignExpr(begin);
5847 : }
5848 : }
5849 :
5850 : template <class ParseHandler, typename CharT>
5851 : typename ParseHandler::Node
5852 0 : Parser<ParseHandler, CharT>::exportDeclaration()
5853 : {
5854 0 : if (!abortIfSyntaxParser())
5855 0 : return null();
5856 :
5857 0 : MOZ_ASSERT(tokenStream.currentToken().type == TOK_EXPORT);
5858 :
5859 0 : if (!pc->atModuleLevel()) {
5860 0 : error(JSMSG_EXPORT_DECL_AT_TOP_LEVEL);
5861 0 : return null();
5862 : }
5863 :
5864 0 : uint32_t begin = pos().begin;
5865 :
5866 : TokenKind tt;
5867 0 : if (!tokenStream.getToken(&tt))
5868 0 : return null();
5869 0 : switch (tt) {
5870 : case TOK_MUL:
5871 0 : return exportBatch(begin);
5872 :
5873 : case TOK_LC:
5874 0 : return exportClause(begin);
5875 :
5876 : case TOK_VAR:
5877 0 : return exportVariableStatement(begin);
5878 :
5879 : case TOK_FUNCTION:
5880 0 : return exportFunctionDeclaration(begin, pos().begin);
5881 :
5882 : case TOK_ASYNC: {
5883 0 : TokenKind nextSameLine = TOK_EOF;
5884 0 : if (!tokenStream.peekTokenSameLine(&nextSameLine))
5885 0 : return null();
5886 :
5887 0 : if (nextSameLine == TOK_FUNCTION) {
5888 0 : uint32_t toStringStart = pos().begin;
5889 0 : tokenStream.consumeKnownToken(TOK_FUNCTION);
5890 0 : return exportFunctionDeclaration(begin, toStringStart, AsyncFunction);
5891 : }
5892 :
5893 0 : error(JSMSG_DECLARATION_AFTER_EXPORT);
5894 0 : return null();
5895 : }
5896 :
5897 : case TOK_CLASS:
5898 0 : return exportClassDeclaration(begin);
5899 :
5900 : case TOK_CONST:
5901 0 : return exportLexicalDeclaration(begin, DeclarationKind::Const);
5902 :
5903 : case TOK_LET:
5904 0 : return exportLexicalDeclaration(begin, DeclarationKind::Let);
5905 :
5906 : case TOK_DEFAULT:
5907 0 : return exportDefault(begin);
5908 :
5909 : default:
5910 0 : error(JSMSG_DECLARATION_AFTER_EXPORT);
5911 0 : return null();
5912 : }
5913 : }
5914 :
5915 : template <class ParseHandler, typename CharT>
5916 : typename ParseHandler::Node
5917 18460 : Parser<ParseHandler, CharT>::expressionStatement(YieldHandling yieldHandling,
5918 : InvokedPrediction invoked)
5919 : {
5920 18460 : tokenStream.ungetToken();
5921 : Node pnexpr = expr(InAllowed, yieldHandling, TripledotProhibited,
5922 18460 : /* possibleError = */ nullptr, invoked);
5923 18460 : if (!pnexpr)
5924 0 : return null();
5925 18460 : if (!matchOrInsertSemicolonAfterExpression())
5926 0 : return null();
5927 18460 : return handler.newExprStatement(pnexpr, pos().end);
5928 : }
5929 :
5930 : template <class ParseHandler, typename CharT>
5931 : typename ParseHandler::Node
5932 9594 : Parser<ParseHandler, CharT>::consequentOrAlternative(YieldHandling yieldHandling)
5933 : {
5934 : TokenKind next;
5935 9594 : if (!tokenStream.peekToken(&next, TokenStream::Operand))
5936 0 : return null();
5937 :
5938 : // Annex B.3.4 says that unbraced FunctionDeclarations under if/else in
5939 : // non-strict code act as if they were braced: |if (x) function f() {}|
5940 : // parses as |if (x) { function f() {} }|.
5941 : //
5942 : // Careful! FunctionDeclaration doesn't include generators or async
5943 : // functions.
5944 9594 : if (next == TOK_FUNCTION) {
5945 0 : tokenStream.consumeKnownToken(next, TokenStream::Operand);
5946 :
5947 : // Parser::statement would handle this, but as this function handles
5948 : // every other error case, it seems best to handle this.
5949 0 : if (pc->sc()->strict()) {
5950 0 : error(JSMSG_FORBIDDEN_AS_STATEMENT, "function declarations");
5951 0 : return null();
5952 : }
5953 :
5954 : TokenKind maybeStar;
5955 0 : if (!tokenStream.peekToken(&maybeStar))
5956 0 : return null();
5957 :
5958 0 : if (maybeStar == TOK_MUL) {
5959 0 : error(JSMSG_FORBIDDEN_AS_STATEMENT, "generator declarations");
5960 0 : return null();
5961 : }
5962 :
5963 0 : ParseContext::Statement stmt(pc, StatementKind::Block);
5964 0 : ParseContext::Scope scope(this);
5965 0 : if (!scope.init(pc))
5966 0 : return null();
5967 :
5968 0 : TokenPos funcPos = pos();
5969 0 : Node fun = functionStmt(pos().begin, yieldHandling, NameRequired);
5970 0 : if (!fun)
5971 0 : return null();
5972 :
5973 0 : Node block = handler.newStatementList(funcPos);
5974 0 : if (!block)
5975 0 : return null();
5976 :
5977 0 : handler.addStatementToList(block, fun);
5978 0 : return finishLexicalScope(scope, block);
5979 : }
5980 :
5981 9594 : return statement(yieldHandling);
5982 : }
5983 :
5984 : template <class ParseHandler, typename CharT>
5985 : typename ParseHandler::Node
5986 8445 : Parser<ParseHandler, CharT>::ifStatement(YieldHandling yieldHandling)
5987 : {
5988 16890 : Vector<Node, 4> condList(context), thenList(context);
5989 16890 : Vector<uint32_t, 4> posList(context);
5990 : Node elseBranch;
5991 :
5992 16890 : ParseContext::Statement stmt(pc, StatementKind::If);
5993 :
5994 345 : while (true) {
5995 8790 : uint32_t begin = pos().begin;
5996 :
5997 : /* An IF node has three kids: condition, then, and optional else. */
5998 8790 : Node cond = condition(InAllowed, yieldHandling);
5999 8790 : if (!cond)
6000 0 : return null();
6001 :
6002 : TokenKind tt;
6003 8790 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
6004 0 : return null();
6005 8790 : if (tt == TOK_SEMI) {
6006 0 : if (!extraWarning(JSMSG_EMPTY_CONSEQUENT))
6007 0 : return null();
6008 : }
6009 :
6010 8790 : Node thenBranch = consequentOrAlternative(yieldHandling);
6011 8790 : if (!thenBranch)
6012 0 : return null();
6013 :
6014 8790 : if (!condList.append(cond) || !thenList.append(thenBranch) || !posList.append(begin))
6015 0 : return null();
6016 :
6017 : bool matched;
6018 8790 : if (!tokenStream.matchToken(&matched, TOK_ELSE, TokenStream::Operand))
6019 0 : return null();
6020 8790 : if (matched) {
6021 1149 : if (!tokenStream.matchToken(&matched, TOK_IF, TokenStream::Operand))
6022 0 : return null();
6023 1149 : if (matched)
6024 345 : continue;
6025 804 : elseBranch = consequentOrAlternative(yieldHandling);
6026 804 : if (!elseBranch)
6027 0 : return null();
6028 : } else {
6029 7641 : elseBranch = null();
6030 : }
6031 8445 : break;
6032 : }
6033 :
6034 34470 : for (int i = condList.length() - 1; i >= 0; i--) {
6035 8790 : elseBranch = handler.newIfStatement(posList[i], condList[i], thenList[i], elseBranch);
6036 8790 : if (!elseBranch)
6037 0 : return null();
6038 : }
6039 :
6040 8445 : return elseBranch;
6041 : }
6042 :
6043 : template <class ParseHandler, typename CharT>
6044 : typename ParseHandler::Node
6045 20 : Parser<ParseHandler, CharT>::doWhileStatement(YieldHandling yieldHandling)
6046 : {
6047 20 : uint32_t begin = pos().begin;
6048 40 : ParseContext::Statement stmt(pc, StatementKind::DoLoop);
6049 20 : Node body = statement(yieldHandling);
6050 20 : if (!body)
6051 0 : return null();
6052 20 : MUST_MATCH_TOKEN_MOD(TOK_WHILE, TokenStream::Operand, JSMSG_WHILE_AFTER_DO);
6053 20 : Node cond = condition(InAllowed, yieldHandling);
6054 20 : if (!cond)
6055 0 : return null();
6056 :
6057 : // The semicolon after do-while is even more optional than most
6058 : // semicolons in JS. Web compat required this by 2004:
6059 : // http://bugzilla.mozilla.org/show_bug.cgi?id=238945
6060 : // ES3 and ES5 disagreed, but ES6 conforms to Web reality:
6061 : // https://bugs.ecmascript.org/show_bug.cgi?id=157
6062 : // To parse |do {} while (true) false| correctly, use Operand.
6063 : bool ignored;
6064 20 : if (!tokenStream.matchToken(&ignored, TOK_SEMI, TokenStream::Operand))
6065 0 : return null();
6066 20 : return handler.newDoWhileStatement(body, cond, TokenPos(begin, pos().end));
6067 : }
6068 :
6069 : template <class ParseHandler, typename CharT>
6070 : typename ParseHandler::Node
6071 204 : Parser<ParseHandler, CharT>::whileStatement(YieldHandling yieldHandling)
6072 : {
6073 204 : uint32_t begin = pos().begin;
6074 408 : ParseContext::Statement stmt(pc, StatementKind::WhileLoop);
6075 204 : Node cond = condition(InAllowed, yieldHandling);
6076 204 : if (!cond)
6077 0 : return null();
6078 204 : Node body = statement(yieldHandling);
6079 204 : if (!body)
6080 0 : return null();
6081 204 : return handler.newWhileStatement(begin, cond, body);
6082 : }
6083 :
6084 : template <class ParseHandler, typename CharT>
6085 : bool
6086 942 : Parser<ParseHandler, CharT>::matchInOrOf(bool* isForInp, bool* isForOfp)
6087 : {
6088 : TokenKind tt;
6089 942 : if (!tokenStream.getToken(&tt))
6090 0 : return false;
6091 :
6092 942 : *isForInp = tt == TOK_IN;
6093 942 : *isForOfp = tt == TOK_OF;
6094 942 : if (!*isForInp && !*isForOfp)
6095 441 : tokenStream.ungetToken();
6096 :
6097 942 : MOZ_ASSERT_IF(*isForInp || *isForOfp, *isForInp != *isForOfp);
6098 942 : return true;
6099 : }
6100 :
6101 : template <class ParseHandler, typename CharT>
6102 : bool
6103 991 : Parser<ParseHandler, CharT>::forHeadStart(YieldHandling yieldHandling,
6104 : IteratorKind iterKind,
6105 : ParseNodeKind* forHeadKind,
6106 : Node* forInitialPart,
6107 : Maybe<ParseContext::Scope>& forLoopLexicalScope,
6108 : Node* forInOrOfExpression)
6109 : {
6110 991 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP));
6111 :
6112 : TokenKind tt;
6113 991 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
6114 0 : return null();
6115 :
6116 : // Super-duper easy case: |for (;| is a C-style for-loop with no init
6117 : // component.
6118 991 : if (tt == TOK_SEMI) {
6119 49 : *forInitialPart = null();
6120 49 : *forHeadKind = PNK_FORHEAD;
6121 49 : return true;
6122 : }
6123 :
6124 : // Parsing after |for (var| is also relatively simple (from this method's
6125 : // point of view). No block-related work complicates matters, so delegate
6126 : // to Parser::declaration.
6127 942 : if (tt == TOK_VAR) {
6128 263 : tokenStream.consumeKnownToken(tt, TokenStream::Operand);
6129 :
6130 : // Pass null for block object because |var| declarations don't use one.
6131 263 : *forInitialPart = declarationList(yieldHandling, PNK_VAR, forHeadKind,
6132 : forInOrOfExpression);
6133 263 : return *forInitialPart != null();
6134 : }
6135 :
6136 : // Otherwise we have a lexical declaration or an expression.
6137 :
6138 : // For-in loop backwards compatibility requires that |let| starting a
6139 : // for-loop that's not a (new to ES6) for-of loop, in non-strict mode code,
6140 : // parse as an identifier. (|let| in for-of is always a declaration.)
6141 679 : bool parsingLexicalDeclaration = false;
6142 679 : bool letIsIdentifier = false;
6143 679 : if (tt == TOK_CONST) {
6144 9 : parsingLexicalDeclaration = true;
6145 9 : tokenStream.consumeKnownToken(tt, TokenStream::Operand);
6146 670 : } else if (tt == TOK_LET) {
6147 : // We could have a {For,Lexical}Declaration, or we could have a
6148 : // LeftHandSideExpression with lookahead restrictions so it's not
6149 : // ambiguous with the former. Check for a continuation of the former
6150 : // to decide which we have.
6151 641 : tokenStream.consumeKnownToken(TOK_LET, TokenStream::Operand);
6152 :
6153 : TokenKind next;
6154 641 : if (!tokenStream.peekToken(&next))
6155 0 : return false;
6156 :
6157 641 : parsingLexicalDeclaration = nextTokenContinuesLetDeclaration(next, yieldHandling);
6158 641 : if (!parsingLexicalDeclaration) {
6159 0 : tokenStream.ungetToken();
6160 0 : letIsIdentifier = true;
6161 : }
6162 : }
6163 :
6164 679 : if (parsingLexicalDeclaration) {
6165 650 : forLoopLexicalScope.emplace(this);
6166 650 : if (!forLoopLexicalScope->init(pc))
6167 0 : return null();
6168 :
6169 : // Push a temporary ForLoopLexicalHead Statement that allows for
6170 : // lexical declarations, as they are usually allowed only in braced
6171 : // statements.
6172 1300 : ParseContext::Statement forHeadStmt(pc, StatementKind::ForLoopLexicalHead);
6173 :
6174 650 : *forInitialPart = declarationList(yieldHandling, tt == TOK_CONST ? PNK_CONST : PNK_LET,
6175 : forHeadKind, forInOrOfExpression);
6176 650 : return *forInitialPart != null();
6177 : }
6178 :
6179 : uint32_t exprOffset;
6180 29 : if (!tokenStream.peekOffset(&exprOffset, TokenStream::Operand))
6181 0 : return false;
6182 :
6183 : // Finally, handle for-loops that start with expressions. Pass
6184 : // |InProhibited| so that |in| isn't parsed in a RelationalExpression as a
6185 : // binary operator. |in| makes it a for-in loop, *not* an |in| expression.
6186 29 : PossibleError possibleError(*this);
6187 29 : *forInitialPart = expr(InProhibited, yieldHandling, TripledotProhibited, &possibleError);
6188 29 : if (!*forInitialPart)
6189 0 : return false;
6190 :
6191 : bool isForIn, isForOf;
6192 29 : if (!matchInOrOf(&isForIn, &isForOf))
6193 0 : return false;
6194 :
6195 : // If we don't encounter 'in'/'of', we have a for(;;) loop. We've handled
6196 : // the init expression; the caller handles the rest. Allow the Operand
6197 : // modifier when regetting: Operand must be used to examine the ';' in
6198 : // |for (;|, and our caller handles this case and that.
6199 29 : if (!isForIn && !isForOf) {
6200 29 : if (!possibleError.checkForExpressionError())
6201 0 : return false;
6202 29 : *forHeadKind = PNK_FORHEAD;
6203 29 : tokenStream.addModifierException(TokenStream::OperandIsNone);
6204 29 : return true;
6205 : }
6206 :
6207 0 : MOZ_ASSERT(isForIn != isForOf);
6208 :
6209 : // In a for-of loop, 'let' that starts the loop head is a |let| keyword,
6210 : // per the [lookahead ≠let] restriction on the LeftHandSideExpression
6211 : // variant of such loops. Expressions that start with |let| can't be used
6212 : // here.
6213 : //
6214 : // var let = {};
6215 : // for (let.prop of [1]) // BAD
6216 : // break;
6217 : //
6218 : // See ES6 13.7.
6219 0 : if (isForOf && letIsIdentifier) {
6220 0 : errorAt(exprOffset, JSMSG_LET_STARTING_FOROF_LHS);
6221 0 : return false;
6222 : }
6223 :
6224 0 : *forHeadKind = isForIn ? PNK_FORIN : PNK_FOROF;
6225 :
6226 : // Verify the left-hand side expression doesn't have a forbidden form.
6227 0 : if (handler.isUnparenthesizedDestructuringPattern(*forInitialPart)) {
6228 0 : if (!possibleError.checkForDestructuringErrorOrWarning())
6229 0 : return false;
6230 0 : } else if (handler.isNameAnyParentheses(*forInitialPart)) {
6231 0 : const char* chars = handler.nameIsArgumentsEvalAnyParentheses(*forInitialPart, context);
6232 0 : if (chars) {
6233 : // |chars| is "arguments" or "eval" here.
6234 0 : if (!strictModeErrorAt(exprOffset, JSMSG_BAD_STRICT_ASSIGN, chars))
6235 0 : return false;
6236 : }
6237 :
6238 0 : handler.adjustGetToSet(*forInitialPart);
6239 0 : } else if (handler.isPropertyAccess(*forInitialPart)) {
6240 : // Permitted: no additional testing/fixup needed.
6241 0 : } else if (handler.isFunctionCall(*forInitialPart)) {
6242 0 : if (!strictModeErrorAt(exprOffset, JSMSG_BAD_FOR_LEFTSIDE))
6243 0 : return false;
6244 : } else {
6245 0 : errorAt(exprOffset, JSMSG_BAD_FOR_LEFTSIDE);
6246 0 : return false;
6247 : }
6248 :
6249 0 : if (!possibleError.checkForExpressionError())
6250 0 : return false;
6251 :
6252 : // Finally, parse the iterated expression, making the for-loop's closing
6253 : // ')' the next token.
6254 0 : *forInOrOfExpression = expressionAfterForInOrOf(*forHeadKind, yieldHandling);
6255 0 : return *forInOrOfExpression != null();
6256 : }
6257 :
6258 : template <class ParseHandler, typename CharT>
6259 : typename ParseHandler::Node
6260 991 : Parser<ParseHandler, CharT>::forStatement(YieldHandling yieldHandling)
6261 : {
6262 991 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FOR));
6263 991 : uint32_t begin = pos().begin;
6264 :
6265 1982 : ParseContext::Statement stmt(pc, StatementKind::ForLoop);
6266 :
6267 991 : bool isForEach = false;
6268 991 : IteratorKind iterKind = IteratorKind::Sync;
6269 991 : unsigned iflags = 0;
6270 :
6271 991 : if (allowsForEachIn()) {
6272 : bool matched;
6273 0 : if (!tokenStream.matchToken(&matched, TOK_EACH))
6274 0 : return null();
6275 0 : if (matched) {
6276 0 : iflags = JSITER_FOREACH;
6277 0 : isForEach = true;
6278 0 : addTelemetry(DeprecatedLanguageExtension::ForEach);
6279 0 : if (!warnOnceAboutForEach())
6280 0 : return null();
6281 : }
6282 : }
6283 :
6284 991 : if (asyncIterationSupported()) {
6285 147 : if (pc->isAsync()) {
6286 : bool matched;
6287 2 : if (!tokenStream.matchToken(&matched, TOK_AWAIT))
6288 0 : return null();
6289 :
6290 2 : if (matched) {
6291 0 : iflags |= JSITER_FORAWAITOF;
6292 0 : iterKind = IteratorKind::Async;
6293 : }
6294 : }
6295 : }
6296 :
6297 991 : MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
6298 :
6299 : // PNK_FORHEAD, PNK_FORIN, or PNK_FOROF depending on the loop type.
6300 : ParseNodeKind headKind;
6301 :
6302 : // |x| in either |for (x; ...; ...)| or |for (x in/of ...)|.
6303 : Node startNode;
6304 :
6305 : // The next two variables are used to implement `for (let/const ...)`.
6306 : //
6307 : // We generate an implicit block, wrapping the whole loop, to store loop
6308 : // variables declared this way. Note that if the loop uses `for (var...)`
6309 : // instead, those variables go on some existing enclosing scope, so no
6310 : // implicit block scope is created.
6311 : //
6312 : // Both variables remain null/none if the loop is any other form.
6313 :
6314 : // The static block scope for the implicit block scope.
6315 1982 : Maybe<ParseContext::Scope> forLoopLexicalScope;
6316 :
6317 : // The expression being iterated over, for for-in/of loops only. Unused
6318 : // for for(;;) loops.
6319 : Node iteratedExpr;
6320 :
6321 : // Parse the entirety of the loop-head for a for-in/of loop (so the next
6322 : // token is the closing ')'):
6323 : //
6324 : // for (... in/of ...) ...
6325 : // ^next token
6326 : //
6327 : // ...OR, parse up to the first ';' in a C-style for-loop:
6328 : //
6329 : // for (...; ...; ...) ...
6330 : // ^next token
6331 : //
6332 : // In either case the subsequent token can be consistently accessed using
6333 : // TokenStream::None semantics.
6334 991 : if (!forHeadStart(yieldHandling, iterKind, &headKind, &startNode, forLoopLexicalScope,
6335 : &iteratedExpr))
6336 : {
6337 0 : return null();
6338 : }
6339 :
6340 991 : MOZ_ASSERT(headKind == PNK_FORIN || headKind == PNK_FOROF || headKind == PNK_FORHEAD);
6341 :
6342 991 : if (iterKind == IteratorKind::Async && headKind != PNK_FOROF) {
6343 0 : errorAt(begin, JSMSG_FOR_AWAIT_NOT_OF);
6344 0 : return null();
6345 : }
6346 991 : if (isForEach && headKind != PNK_FORIN) {
6347 0 : errorAt(begin, JSMSG_BAD_FOR_EACH_LOOP);
6348 0 : return null();
6349 : }
6350 :
6351 : Node forHead;
6352 991 : if (headKind == PNK_FORHEAD) {
6353 490 : Node init = startNode;
6354 :
6355 : // Look for an operand: |for (;| means we might have already examined
6356 : // this semicolon with that modifier.
6357 490 : MUST_MATCH_TOKEN_MOD(TOK_SEMI, TokenStream::Operand, JSMSG_SEMI_AFTER_FOR_INIT);
6358 :
6359 : TokenKind tt;
6360 490 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
6361 0 : return null();
6362 :
6363 : Node test;
6364 : TokenStream::Modifier mod;
6365 490 : if (tt == TOK_SEMI) {
6366 9 : test = null();
6367 9 : mod = TokenStream::Operand;
6368 : } else {
6369 481 : test = expr(InAllowed, yieldHandling, TripledotProhibited);
6370 481 : if (!test)
6371 0 : return null();
6372 481 : mod = TokenStream::None;
6373 : }
6374 :
6375 490 : MUST_MATCH_TOKEN_MOD(TOK_SEMI, mod, JSMSG_SEMI_AFTER_FOR_COND);
6376 :
6377 490 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
6378 0 : return null();
6379 :
6380 : Node update;
6381 490 : if (tt == TOK_RP) {
6382 9 : update = null();
6383 9 : mod = TokenStream::Operand;
6384 : } else {
6385 481 : update = expr(InAllowed, yieldHandling, TripledotProhibited);
6386 481 : if (!update)
6387 0 : return null();
6388 481 : mod = TokenStream::None;
6389 : }
6390 :
6391 490 : MUST_MATCH_TOKEN_MOD(TOK_RP, mod, JSMSG_PAREN_AFTER_FOR_CTRL);
6392 :
6393 490 : TokenPos headPos(begin, pos().end);
6394 490 : forHead = handler.newForHead(init, test, update, headPos);
6395 490 : if (!forHead)
6396 0 : return null();
6397 : } else {
6398 501 : MOZ_ASSERT(headKind == PNK_FORIN || headKind == PNK_FOROF);
6399 :
6400 : // |target| is the LeftHandSideExpression or declaration to which the
6401 : // per-iteration value (an arbitrary value exposed by the iteration
6402 : // protocol, or a string naming a property) is assigned.
6403 501 : Node target = startNode;
6404 :
6405 : // Parse the rest of the for-in/of head.
6406 501 : if (headKind == PNK_FORIN) {
6407 64 : stmt.refineForKind(StatementKind::ForInLoop);
6408 64 : iflags |= JSITER_ENUMERATE;
6409 : } else {
6410 437 : stmt.refineForKind(StatementKind::ForOfLoop);
6411 : }
6412 :
6413 : // Parser::declaration consumed everything up to the closing ')'. That
6414 : // token follows an {Assignment,}Expression, so the next token must be
6415 : // consumed as if an operator continued the expression, i.e. as None.
6416 501 : MUST_MATCH_TOKEN_MOD(TOK_RP, TokenStream::None, JSMSG_PAREN_AFTER_FOR_CTRL);
6417 :
6418 501 : TokenPos headPos(begin, pos().end);
6419 501 : forHead = handler.newForInOrOfHead(headKind, target, iteratedExpr, headPos);
6420 501 : if (!forHead)
6421 0 : return null();
6422 : }
6423 :
6424 991 : Node body = statement(yieldHandling);
6425 991 : if (!body)
6426 0 : return null();
6427 :
6428 991 : Node forLoop = handler.newForStatement(begin, forHead, body, iflags);
6429 991 : if (!forLoop)
6430 0 : return null();
6431 :
6432 991 : if (forLoopLexicalScope)
6433 650 : return finishLexicalScope(*forLoopLexicalScope, forLoop);
6434 :
6435 341 : return forLoop;
6436 : }
6437 :
6438 : template <class ParseHandler, typename CharT>
6439 : typename ParseHandler::Node
6440 275 : Parser<ParseHandler, CharT>::switchStatement(YieldHandling yieldHandling)
6441 : {
6442 275 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_SWITCH));
6443 275 : uint32_t begin = pos().begin;
6444 :
6445 275 : MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_SWITCH);
6446 :
6447 275 : Node discriminant = exprInParens(InAllowed, yieldHandling, TripledotProhibited);
6448 275 : if (!discriminant)
6449 0 : return null();
6450 :
6451 275 : MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_SWITCH);
6452 275 : MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_SWITCH);
6453 :
6454 550 : ParseContext::Statement stmt(pc, StatementKind::Switch);
6455 550 : ParseContext::Scope scope(this);
6456 275 : if (!scope.init(pc))
6457 0 : return null();
6458 :
6459 275 : Node caseList = handler.newStatementList(pos());
6460 275 : if (!caseList)
6461 0 : return null();
6462 :
6463 275 : bool seenDefault = false;
6464 : TokenKind tt;
6465 1365 : while (true) {
6466 1640 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
6467 0 : return null();
6468 1640 : if (tt == TOK_RC)
6469 275 : break;
6470 1365 : uint32_t caseBegin = pos().begin;
6471 :
6472 : Node caseExpr;
6473 1365 : switch (tt) {
6474 : case TOK_DEFAULT:
6475 72 : if (seenDefault) {
6476 0 : error(JSMSG_TOO_MANY_DEFAULTS);
6477 0 : return null();
6478 : }
6479 72 : seenDefault = true;
6480 72 : caseExpr = null(); // The default case has pn_left == nullptr.
6481 72 : break;
6482 :
6483 : case TOK_CASE:
6484 1293 : caseExpr = expr(InAllowed, yieldHandling, TripledotProhibited);
6485 1293 : if (!caseExpr)
6486 0 : return null();
6487 1293 : break;
6488 :
6489 : default:
6490 0 : error(JSMSG_BAD_SWITCH);
6491 0 : return null();
6492 : }
6493 :
6494 1365 : MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
6495 :
6496 1365 : Node body = handler.newStatementList(pos());
6497 1365 : if (!body)
6498 0 : return null();
6499 :
6500 1365 : bool afterReturn = false;
6501 1365 : bool warnedAboutStatementsAfterReturn = false;
6502 1365 : uint32_t statementBegin = 0;
6503 2315 : while (true) {
6504 3680 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
6505 0 : return null();
6506 3680 : if (tt == TOK_RC || tt == TOK_CASE || tt == TOK_DEFAULT)
6507 : break;
6508 2315 : if (afterReturn) {
6509 0 : if (!tokenStream.peekOffset(&statementBegin, TokenStream::Operand))
6510 0 : return null();
6511 : }
6512 2315 : Node stmt = statementListItem(yieldHandling);
6513 2315 : if (!stmt)
6514 0 : return null();
6515 2315 : if (!warnedAboutStatementsAfterReturn) {
6516 2315 : if (afterReturn) {
6517 0 : if (!handler.isStatementPermittedAfterReturnStatement(stmt)) {
6518 0 : if (!warningAt(statementBegin, JSMSG_STMT_AFTER_RETURN))
6519 0 : return null();
6520 :
6521 0 : warnedAboutStatementsAfterReturn = true;
6522 : }
6523 2315 : } else if (handler.isReturnStatement(stmt)) {
6524 601 : afterReturn = true;
6525 : }
6526 : }
6527 2315 : handler.addStatementToList(body, stmt);
6528 : }
6529 :
6530 1365 : Node casepn = handler.newCaseOrDefault(caseBegin, caseExpr, body);
6531 1365 : if (!casepn)
6532 0 : return null();
6533 1365 : handler.addCaseStatementToList(caseList, casepn);
6534 : }
6535 :
6536 275 : caseList = finishLexicalScope(scope, caseList);
6537 275 : if (!caseList)
6538 0 : return null();
6539 :
6540 275 : handler.setEndPosition(caseList, pos().end);
6541 :
6542 275 : return handler.newSwitchStatement(begin, discriminant, caseList);
6543 : }
6544 :
6545 : template <class ParseHandler, typename CharT>
6546 : typename ParseHandler::Node
6547 165 : Parser<ParseHandler, CharT>::continueStatement(YieldHandling yieldHandling)
6548 : {
6549 165 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CONTINUE));
6550 165 : uint32_t begin = pos().begin;
6551 :
6552 330 : RootedPropertyName label(context);
6553 165 : if (!matchLabel(yieldHandling, &label))
6554 0 : return null();
6555 :
6556 : // Labeled 'continue' statements target the nearest labeled loop
6557 : // statements with the same label. Unlabeled 'continue' statements target
6558 : // the innermost loop statement.
6559 643 : auto isLoop = [](ParseContext::Statement* stmt) {
6560 643 : return StatementKindIsLoop(stmt->kind());
6561 643 : };
6562 :
6563 165 : if (label) {
6564 0 : ParseContext::Statement* stmt = pc->innermostStatement();
6565 0 : bool foundLoop = false;
6566 :
6567 0 : for (;;) {
6568 0 : stmt = ParseContext::Statement::findNearest(stmt, isLoop);
6569 0 : if (!stmt) {
6570 0 : if (foundLoop)
6571 0 : error(JSMSG_LABEL_NOT_FOUND);
6572 : else
6573 0 : errorAt(begin, JSMSG_BAD_CONTINUE);
6574 0 : return null();
6575 : }
6576 :
6577 0 : foundLoop = true;
6578 :
6579 : // Is it labeled by our label?
6580 0 : bool foundTarget = false;
6581 0 : stmt = stmt->enclosing();
6582 0 : while (stmt && stmt->is<ParseContext::LabelStatement>()) {
6583 0 : if (stmt->as<ParseContext::LabelStatement>().label() == label) {
6584 0 : foundTarget = true;
6585 0 : break;
6586 : }
6587 0 : stmt = stmt->enclosing();
6588 : }
6589 0 : if (foundTarget)
6590 0 : break;
6591 : }
6592 165 : } else if (!pc->findInnermostStatement(isLoop)) {
6593 0 : error(JSMSG_BAD_CONTINUE);
6594 0 : return null();
6595 : }
6596 :
6597 165 : if (!matchOrInsertSemicolonAfterNonExpression())
6598 0 : return null();
6599 :
6600 165 : return handler.newContinueStatement(label, TokenPos(begin, pos().end));
6601 : }
6602 :
6603 : template <class ParseHandler, typename CharT>
6604 : typename ParseHandler::Node
6605 676 : Parser<ParseHandler, CharT>::breakStatement(YieldHandling yieldHandling)
6606 : {
6607 676 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_BREAK));
6608 676 : uint32_t begin = pos().begin;
6609 :
6610 1352 : RootedPropertyName label(context);
6611 676 : if (!matchLabel(yieldHandling, &label))
6612 0 : return null();
6613 :
6614 : // Labeled 'break' statements target the nearest labeled statements (could
6615 : // be any kind) with the same label. Unlabeled 'break' statements target
6616 : // the innermost loop or switch statement.
6617 676 : if (label) {
6618 0 : auto hasSameLabel = [&label](ParseContext::LabelStatement* stmt) {
6619 0 : return stmt->label() == label;
6620 0 : };
6621 :
6622 0 : if (!pc->findInnermostStatement<ParseContext::LabelStatement>(hasSameLabel)) {
6623 0 : error(JSMSG_LABEL_NOT_FOUND);
6624 0 : return null();
6625 : }
6626 : } else {
6627 1194 : auto isBreakTarget = [](ParseContext::Statement* stmt) {
6628 1194 : return StatementKindIsUnlabeledBreakTarget(stmt->kind());
6629 1194 : };
6630 :
6631 676 : if (!pc->findInnermostStatement(isBreakTarget)) {
6632 0 : errorAt(begin, JSMSG_TOUGH_BREAK);
6633 0 : return null();
6634 : }
6635 : }
6636 :
6637 676 : if (!matchOrInsertSemicolonAfterNonExpression())
6638 0 : return null();
6639 :
6640 676 : return handler.newBreakStatement(label, TokenPos(begin, pos().end));
6641 : }
6642 :
6643 : template <class ParseHandler, typename CharT>
6644 : typename ParseHandler::Node
6645 7312 : Parser<ParseHandler, CharT>::returnStatement(YieldHandling yieldHandling)
6646 : {
6647 7312 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_RETURN));
6648 7312 : uint32_t begin = pos().begin;
6649 :
6650 7312 : MOZ_ASSERT(pc->isFunctionBox());
6651 7312 : pc->functionBox()->usesReturn = true;
6652 :
6653 : // Parse an optional operand.
6654 : //
6655 : // This is ugly, but we don't want to require a semicolon.
6656 : Node exprNode;
6657 7312 : TokenKind tt = TOK_EOF;
6658 7312 : if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
6659 0 : return null();
6660 7312 : switch (tt) {
6661 : case TOK_EOL:
6662 : case TOK_EOF:
6663 : case TOK_SEMI:
6664 : case TOK_RC:
6665 746 : exprNode = null();
6666 746 : pc->funHasReturnVoid = true;
6667 746 : break;
6668 : default: {
6669 6566 : exprNode = expr(InAllowed, yieldHandling, TripledotProhibited);
6670 6566 : if (!exprNode)
6671 0 : return null();
6672 6566 : pc->funHasReturnExpr = true;
6673 : }
6674 : }
6675 :
6676 7312 : if (exprNode) {
6677 6566 : if (!matchOrInsertSemicolonAfterExpression())
6678 0 : return null();
6679 : } else {
6680 746 : if (!matchOrInsertSemicolonAfterNonExpression())
6681 0 : return null();
6682 : }
6683 :
6684 7312 : Node pn = handler.newReturnStatement(exprNode, TokenPos(begin, pos().end));
6685 7312 : if (!pn)
6686 0 : return null();
6687 :
6688 : /* Disallow "return v;" in legacy generators. */
6689 7312 : if (pc->isLegacyGenerator() && exprNode) {
6690 0 : errorAt(begin, JSMSG_BAD_GENERATOR_RETURN);
6691 0 : return null();
6692 : }
6693 :
6694 7312 : return pn;
6695 : }
6696 :
6697 : template <class ParseHandler, typename CharT>
6698 : typename ParseHandler::Node
6699 24 : Parser<ParseHandler, CharT>::yieldExpression(InHandling inHandling)
6700 : {
6701 24 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_YIELD));
6702 24 : uint32_t begin = pos().begin;
6703 :
6704 24 : switch (pc->generatorKind()) {
6705 : case StarGenerator:
6706 : {
6707 24 : MOZ_ASSERT(pc->isFunctionBox());
6708 :
6709 24 : pc->lastYieldOffset = begin;
6710 :
6711 : Node exprNode;
6712 24 : ParseNodeKind kind = PNK_YIELD;
6713 24 : TokenKind tt = TOK_EOF;
6714 24 : if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
6715 0 : return null();
6716 24 : switch (tt) {
6717 : // TOK_EOL is special; it implements the [no LineTerminator here]
6718 : // quirk in the grammar.
6719 : case TOK_EOL:
6720 : // The rest of these make up the complete set of tokens that can
6721 : // appear after any of the places where AssignmentExpression is used
6722 : // throughout the grammar. Conveniently, none of them can also be the
6723 : // start an expression.
6724 : case TOK_EOF:
6725 : case TOK_SEMI:
6726 : case TOK_RC:
6727 : case TOK_RB:
6728 : case TOK_RP:
6729 : case TOK_COLON:
6730 : case TOK_COMMA:
6731 : case TOK_IN:
6732 : // No value.
6733 0 : exprNode = null();
6734 0 : tokenStream.addModifierException(TokenStream::NoneIsOperand);
6735 0 : break;
6736 : case TOK_MUL:
6737 3 : kind = PNK_YIELD_STAR;
6738 3 : tokenStream.consumeKnownToken(TOK_MUL, TokenStream::Operand);
6739 : MOZ_FALLTHROUGH;
6740 : default:
6741 24 : exprNode = assignExpr(inHandling, YieldIsKeyword, TripledotProhibited);
6742 24 : if (!exprNode)
6743 0 : return null();
6744 : }
6745 24 : if (kind == PNK_YIELD_STAR)
6746 3 : return handler.newYieldStarExpression(begin, exprNode);
6747 21 : return handler.newYieldExpression(begin, exprNode);
6748 : }
6749 :
6750 : case NotGenerator:
6751 : // We are in code that has not seen a yield, but we are in JS 1.7 or
6752 : // later. Try to transition to being a legacy generator.
6753 0 : MOZ_ASSERT(tokenStream.versionNumber() >= JSVERSION_1_7);
6754 0 : MOZ_ASSERT(pc->lastYieldOffset == ParseContext::NoYieldOffset);
6755 :
6756 0 : if (!abortIfSyntaxParser())
6757 0 : return null();
6758 :
6759 0 : if (!pc->isFunctionBox()) {
6760 0 : error(JSMSG_BAD_RETURN_OR_YIELD, js_yield_str);
6761 0 : return null();
6762 : }
6763 :
6764 0 : if (pc->functionBox()->isArrow()) {
6765 0 : errorAt(begin, JSMSG_YIELD_IN_ARROW, js_yield_str);
6766 0 : return null();
6767 : }
6768 :
6769 0 : if (pc->functionBox()->function()->isMethod() ||
6770 0 : pc->functionBox()->function()->isGetter() ||
6771 0 : pc->functionBox()->function()->isSetter())
6772 : {
6773 0 : errorAt(begin, JSMSG_YIELD_IN_METHOD, js_yield_str);
6774 0 : return null();
6775 : }
6776 :
6777 0 : if (pc->funHasReturnExpr
6778 : #if JS_HAS_EXPR_CLOSURES
6779 0 : || pc->functionBox()->isExprBody()
6780 : #endif
6781 : )
6782 : {
6783 : /* As in Python (see PEP-255), disallow return v; in generators. */
6784 0 : errorAt(begin, JSMSG_BAD_FUNCTION_YIELD);
6785 0 : return null();
6786 : }
6787 :
6788 0 : pc->functionBox()->setGeneratorKind(LegacyGenerator);
6789 0 : addTelemetry(DeprecatedLanguageExtension::LegacyGenerator);
6790 :
6791 : MOZ_FALLTHROUGH;
6792 :
6793 : case LegacyGenerator:
6794 : {
6795 : // We are in a legacy generator: a function that has already seen a
6796 : // yield.
6797 0 : MOZ_ASSERT(pc->isFunctionBox());
6798 :
6799 0 : pc->lastYieldOffset = begin;
6800 :
6801 : // Legacy generators do not require a value.
6802 : Node exprNode;
6803 0 : TokenKind tt = TOK_EOF;
6804 0 : if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
6805 0 : return null();
6806 0 : switch (tt) {
6807 : case TOK_EOF:
6808 : case TOK_EOL:
6809 : case TOK_SEMI:
6810 : case TOK_RC:
6811 : case TOK_RB:
6812 : case TOK_RP:
6813 : case TOK_COLON:
6814 : case TOK_COMMA:
6815 : // No value.
6816 0 : exprNode = null();
6817 0 : tokenStream.addModifierException(TokenStream::NoneIsOperand);
6818 0 : break;
6819 : default:
6820 0 : exprNode = assignExpr(inHandling, YieldIsKeyword, TripledotProhibited);
6821 0 : if (!exprNode)
6822 0 : return null();
6823 : }
6824 :
6825 0 : return handler.newYieldExpression(begin, exprNode);
6826 : }
6827 : }
6828 :
6829 0 : MOZ_CRASH("yieldExpr");
6830 : }
6831 :
6832 : template <class ParseHandler, typename CharT>
6833 : typename ParseHandler::Node
6834 0 : Parser<ParseHandler, CharT>::withStatement(YieldHandling yieldHandling)
6835 : {
6836 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_WITH));
6837 0 : uint32_t begin = pos().begin;
6838 :
6839 : // Usually we want the constructs forbidden in strict mode code to be a
6840 : // subset of those that ContextOptions::extraWarnings() warns about, and we
6841 : // use strictModeError directly. But while 'with' is forbidden in strict
6842 : // mode code, it doesn't even merit a warning in non-strict code. See
6843 : // https://bugzilla.mozilla.org/show_bug.cgi?id=514576#c1.
6844 0 : if (pc->sc()->strict()) {
6845 0 : if (!strictModeError(JSMSG_STRICT_CODE_WITH))
6846 0 : return null();
6847 : }
6848 :
6849 0 : MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH);
6850 0 : Node objectExpr = exprInParens(InAllowed, yieldHandling, TripledotProhibited);
6851 0 : if (!objectExpr)
6852 0 : return null();
6853 0 : MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH);
6854 :
6855 : Node innerBlock;
6856 : {
6857 0 : ParseContext::Statement stmt(pc, StatementKind::With);
6858 0 : innerBlock = statement(yieldHandling);
6859 0 : if (!innerBlock)
6860 0 : return null();
6861 : }
6862 :
6863 0 : pc->sc()->setBindingsAccessedDynamically();
6864 :
6865 0 : return handler.newWithStatement(begin, objectExpr, innerBlock);
6866 : }
6867 :
6868 : template <class ParseHandler, typename CharT>
6869 : typename ParseHandler::Node
6870 0 : Parser<ParseHandler, CharT>::labeledItem(YieldHandling yieldHandling)
6871 : {
6872 : TokenKind tt;
6873 0 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
6874 0 : return null();
6875 :
6876 0 : if (tt == TOK_FUNCTION) {
6877 : TokenKind next;
6878 0 : if (!tokenStream.peekToken(&next))
6879 0 : return null();
6880 :
6881 : // GeneratorDeclaration is only matched by HoistableDeclaration in
6882 : // StatementListItem, so generators can't be inside labels.
6883 0 : if (next == TOK_MUL) {
6884 0 : error(JSMSG_GENERATOR_LABEL);
6885 0 : return null();
6886 : }
6887 :
6888 : // Per 13.13.1 it's a syntax error if LabelledItem: FunctionDeclaration
6889 : // is ever matched. Per Annex B.3.2 that modifies this text, this
6890 : // applies only to strict mode code.
6891 0 : if (pc->sc()->strict()) {
6892 0 : error(JSMSG_FUNCTION_LABEL);
6893 0 : return null();
6894 : }
6895 :
6896 0 : return functionStmt(pos().begin, yieldHandling, NameRequired);
6897 : }
6898 :
6899 0 : tokenStream.ungetToken();
6900 0 : return statement(yieldHandling);
6901 : }
6902 :
6903 : template <class ParseHandler, typename CharT>
6904 : typename ParseHandler::Node
6905 0 : Parser<ParseHandler, CharT>::labeledStatement(YieldHandling yieldHandling)
6906 : {
6907 0 : RootedPropertyName label(context, labelIdentifier(yieldHandling));
6908 0 : if (!label)
6909 0 : return null();
6910 :
6911 0 : auto hasSameLabel = [&label](ParseContext::LabelStatement* stmt) {
6912 0 : return stmt->label() == label;
6913 0 : };
6914 :
6915 0 : uint32_t begin = pos().begin;
6916 :
6917 0 : if (pc->findInnermostStatement<ParseContext::LabelStatement>(hasSameLabel)) {
6918 0 : errorAt(begin, JSMSG_DUPLICATE_LABEL);
6919 0 : return null();
6920 : }
6921 :
6922 0 : tokenStream.consumeKnownToken(TOK_COLON);
6923 :
6924 : /* Push a label struct and parse the statement. */
6925 0 : ParseContext::LabelStatement stmt(pc, label);
6926 0 : Node pn = labeledItem(yieldHandling);
6927 0 : if (!pn)
6928 0 : return null();
6929 :
6930 0 : return handler.newLabeledStatement(label, pn, begin);
6931 : }
6932 :
6933 : template <class ParseHandler, typename CharT>
6934 : typename ParseHandler::Node
6935 579 : Parser<ParseHandler, CharT>::throwStatement(YieldHandling yieldHandling)
6936 : {
6937 579 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_THROW));
6938 579 : uint32_t begin = pos().begin;
6939 :
6940 : /* ECMA-262 Edition 3 says 'throw [no LineTerminator here] Expr'. */
6941 579 : TokenKind tt = TOK_EOF;
6942 579 : if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
6943 0 : return null();
6944 579 : if (tt == TOK_EOF || tt == TOK_SEMI || tt == TOK_RC) {
6945 0 : error(JSMSG_MISSING_EXPR_AFTER_THROW);
6946 0 : return null();
6947 : }
6948 579 : if (tt == TOK_EOL) {
6949 0 : error(JSMSG_LINE_BREAK_AFTER_THROW);
6950 0 : return null();
6951 : }
6952 :
6953 579 : Node throwExpr = expr(InAllowed, yieldHandling, TripledotProhibited);
6954 579 : if (!throwExpr)
6955 0 : return null();
6956 :
6957 579 : if (!matchOrInsertSemicolonAfterExpression())
6958 0 : return null();
6959 :
6960 579 : return handler.newThrowStatement(throwExpr, TokenPos(begin, pos().end));
6961 : }
6962 :
6963 : template <class ParseHandler, typename CharT>
6964 : typename ParseHandler::Node
6965 684 : Parser<ParseHandler, CharT>::tryStatement(YieldHandling yieldHandling)
6966 : {
6967 684 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_TRY));
6968 684 : uint32_t begin = pos().begin;
6969 :
6970 : /*
6971 : * try nodes are ternary.
6972 : * kid1 is the try statement
6973 : * kid2 is the catch node list or null
6974 : * kid3 is the finally statement
6975 : *
6976 : * catch nodes are ternary.
6977 : * kid1 is the lvalue (possible identifier, TOK_LB, or TOK_LC)
6978 : * kid2 is the catch guard or null if no guard
6979 : * kid3 is the catch block
6980 : *
6981 : * catch lvalue nodes are either:
6982 : * a single identifier
6983 : * TOK_RB or TOK_RC for a destructuring left-hand side
6984 : *
6985 : * finally nodes are TOK_LC statement lists.
6986 : */
6987 :
6988 : Node innerBlock;
6989 : {
6990 684 : MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY);
6991 :
6992 684 : uint32_t openedPos = pos().begin;
6993 :
6994 1368 : ParseContext::Statement stmt(pc, StatementKind::Try);
6995 1368 : ParseContext::Scope scope(this);
6996 684 : if (!scope.init(pc))
6997 0 : return null();
6998 :
6999 684 : innerBlock = statementList(yieldHandling);
7000 684 : if (!innerBlock)
7001 0 : return null();
7002 :
7003 684 : innerBlock = finishLexicalScope(scope, innerBlock);
7004 684 : if (!innerBlock)
7005 0 : return null();
7006 :
7007 684 : MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
7008 : reportMissingClosing(JSMSG_CURLY_AFTER_TRY,
7009 : JSMSG_CURLY_OPENED, openedPos));
7010 : }
7011 :
7012 684 : bool hasUnconditionalCatch = false;
7013 684 : Node catchList = null();
7014 : TokenKind tt;
7015 684 : if (!tokenStream.getToken(&tt))
7016 0 : return null();
7017 684 : if (tt == TOK_CATCH) {
7018 655 : catchList = handler.newCatchList(pos());
7019 655 : if (!catchList)
7020 0 : return null();
7021 :
7022 0 : do {
7023 : Node pnblock;
7024 :
7025 : /* Check for another catch after unconditional catch. */
7026 655 : if (hasUnconditionalCatch) {
7027 0 : error(JSMSG_CATCH_AFTER_GENERAL);
7028 0 : return null();
7029 : }
7030 :
7031 : /*
7032 : * Create a lexical scope node around the whole catch clause,
7033 : * including the head.
7034 : */
7035 1310 : ParseContext::Statement stmt(pc, StatementKind::Catch);
7036 1310 : ParseContext::Scope scope(this);
7037 655 : if (!scope.init(pc))
7038 0 : return null();
7039 :
7040 : /*
7041 : * Legal catch forms are:
7042 : * catch (lhs)
7043 : * catch (lhs if <boolean_expression>)
7044 : * where lhs is a name or a destructuring left-hand side.
7045 : * (the latter is legal only #ifdef JS_HAS_CATCH_GUARD)
7046 : */
7047 655 : MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_CATCH);
7048 :
7049 655 : if (!tokenStream.getToken(&tt))
7050 0 : return null();
7051 : Node catchName;
7052 655 : switch (tt) {
7053 : case TOK_LB:
7054 : case TOK_LC:
7055 0 : catchName = destructuringDeclaration(DeclarationKind::CatchParameter,
7056 : yieldHandling, tt);
7057 0 : if (!catchName)
7058 0 : return null();
7059 0 : break;
7060 :
7061 : default: {
7062 655 : if (!TokenKindIsPossibleIdentifierName(tt)) {
7063 0 : error(JSMSG_CATCH_IDENTIFIER);
7064 0 : return null();
7065 : }
7066 :
7067 655 : catchName = bindingIdentifier(DeclarationKind::SimpleCatchParameter,
7068 : yieldHandling);
7069 655 : if (!catchName)
7070 0 : return null();
7071 655 : break;
7072 : }
7073 : }
7074 :
7075 655 : Node catchGuard = null();
7076 : #if JS_HAS_CATCH_GUARD
7077 : /*
7078 : * We use 'catch (x if x === 5)' (not 'catch (x : x === 5)')
7079 : * to avoid conflicting with the JS2/ECMAv4 type annotation
7080 : * catchguard syntax.
7081 : */
7082 : bool matched;
7083 655 : if (!tokenStream.matchToken(&matched, TOK_IF))
7084 0 : return null();
7085 655 : if (matched) {
7086 0 : catchGuard = expr(InAllowed, yieldHandling, TripledotProhibited);
7087 0 : if (!catchGuard)
7088 0 : return null();
7089 : }
7090 : #endif
7091 655 : MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_CATCH);
7092 :
7093 655 : MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CATCH);
7094 :
7095 655 : Node catchBody = catchBlockStatement(yieldHandling, scope);
7096 655 : if (!catchBody)
7097 0 : return null();
7098 :
7099 655 : if (!catchGuard)
7100 655 : hasUnconditionalCatch = true;
7101 :
7102 655 : pnblock = finishLexicalScope(scope, catchBody);
7103 655 : if (!pnblock)
7104 0 : return null();
7105 :
7106 655 : if (!handler.addCatchBlock(catchList, pnblock, catchName, catchGuard, catchBody))
7107 0 : return null();
7108 655 : handler.setEndPosition(catchList, pos().end);
7109 655 : handler.setEndPosition(pnblock, pos().end);
7110 :
7111 655 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
7112 0 : return null();
7113 655 : } while (tt == TOK_CATCH);
7114 : }
7115 :
7116 684 : Node finallyBlock = null();
7117 :
7118 684 : if (tt == TOK_FINALLY) {
7119 58 : MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY);
7120 :
7121 58 : uint32_t openedPos = pos().begin;
7122 :
7123 116 : ParseContext::Statement stmt(pc, StatementKind::Finally);
7124 116 : ParseContext::Scope scope(this);
7125 58 : if (!scope.init(pc))
7126 0 : return null();
7127 :
7128 58 : finallyBlock = statementList(yieldHandling);
7129 58 : if (!finallyBlock)
7130 0 : return null();
7131 :
7132 58 : finallyBlock = finishLexicalScope(scope, finallyBlock);
7133 58 : if (!finallyBlock)
7134 0 : return null();
7135 :
7136 58 : MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
7137 : reportMissingClosing(JSMSG_CURLY_AFTER_FINALLY,
7138 : JSMSG_CURLY_OPENED, openedPos));
7139 : } else {
7140 626 : tokenStream.ungetToken();
7141 : }
7142 684 : if (!catchList && !finallyBlock) {
7143 0 : error(JSMSG_CATCH_OR_FINALLY);
7144 0 : return null();
7145 : }
7146 :
7147 684 : return handler.newTryStatement(begin, innerBlock, catchList, finallyBlock);
7148 : }
7149 :
7150 : template <class ParseHandler, typename CharT>
7151 : typename ParseHandler::Node
7152 655 : Parser<ParseHandler, CharT>::catchBlockStatement(YieldHandling yieldHandling,
7153 : ParseContext::Scope& catchParamScope)
7154 : {
7155 655 : uint32_t openedPos = pos().begin;
7156 :
7157 1310 : ParseContext::Statement stmt(pc, StatementKind::Block);
7158 :
7159 : // ES 13.15.7 CatchClauseEvaluation
7160 : //
7161 : // Step 8 means that the body of a catch block always has an additional
7162 : // lexical scope.
7163 1310 : ParseContext::Scope scope(this);
7164 655 : if (!scope.init(pc))
7165 0 : return null();
7166 :
7167 : // The catch parameter names cannot be redeclared inside the catch
7168 : // block, so declare the name in the inner scope.
7169 655 : if (!scope.addCatchParameters(pc, catchParamScope))
7170 0 : return null();
7171 :
7172 655 : Node list = statementList(yieldHandling);
7173 655 : if (!list)
7174 0 : return null();
7175 :
7176 655 : MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
7177 : reportMissingClosing(JSMSG_CURLY_AFTER_CATCH,
7178 : JSMSG_CURLY_OPENED, openedPos));
7179 :
7180 : // The catch parameter names are not bound in the body scope, so remove
7181 : // them before generating bindings.
7182 655 : scope.removeCatchParameters(pc, catchParamScope);
7183 655 : return finishLexicalScope(scope, list);
7184 : }
7185 :
7186 : template <class ParseHandler, typename CharT>
7187 : typename ParseHandler::Node
7188 0 : Parser<ParseHandler, CharT>::debuggerStatement()
7189 : {
7190 0 : TokenPos p;
7191 0 : p.begin = pos().begin;
7192 0 : if (!matchOrInsertSemicolonAfterNonExpression())
7193 0 : return null();
7194 0 : p.end = pos().end;
7195 :
7196 0 : pc->sc()->setBindingsAccessedDynamically();
7197 0 : pc->sc()->setHasDebuggerStatement();
7198 :
7199 0 : return handler.newDebuggerStatement(p);
7200 : }
7201 :
7202 : static JSOp
7203 2177 : JSOpFromPropertyType(PropertyType propType)
7204 : {
7205 2177 : switch (propType) {
7206 : case PropertyType::Getter:
7207 : case PropertyType::GetterNoExpressionClosure:
7208 313 : return JSOP_INITPROP_GETTER;
7209 : case PropertyType::Setter:
7210 : case PropertyType::SetterNoExpressionClosure:
7211 42 : return JSOP_INITPROP_SETTER;
7212 : case PropertyType::Normal:
7213 : case PropertyType::Method:
7214 : case PropertyType::GeneratorMethod:
7215 : case PropertyType::AsyncMethod:
7216 : case PropertyType::AsyncGeneratorMethod:
7217 : case PropertyType::Constructor:
7218 : case PropertyType::DerivedConstructor:
7219 1822 : return JSOP_INITPROP;
7220 : default:
7221 0 : MOZ_CRASH("unexpected property type");
7222 : }
7223 : }
7224 :
7225 : template <class ParseHandler, typename CharT>
7226 : typename ParseHandler::Node
7227 32 : Parser<ParseHandler, CharT>::classDefinition(YieldHandling yieldHandling,
7228 : ClassContext classContext,
7229 : DefaultHandling defaultHandling)
7230 : {
7231 32 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS));
7232 :
7233 32 : uint32_t classStartOffset = pos().begin;
7234 32 : bool savedStrictness = setLocalStrictMode(true);
7235 :
7236 : TokenKind tt;
7237 32 : if (!tokenStream.getToken(&tt))
7238 0 : return null();
7239 :
7240 64 : RootedPropertyName name(context);
7241 32 : if (TokenKindIsPossibleIdentifier(tt)) {
7242 26 : name = bindingIdentifier(yieldHandling);
7243 26 : if (!name)
7244 0 : return null();
7245 6 : } else if (classContext == ClassStatement) {
7246 0 : if (defaultHandling == AllowDefaultName) {
7247 0 : name = context->names().starDefaultStar;
7248 0 : tokenStream.ungetToken();
7249 : } else {
7250 : // Class statements must have a bound name
7251 0 : error(JSMSG_UNNAMED_CLASS_STMT);
7252 0 : return null();
7253 : }
7254 : } else {
7255 : // Make sure to put it back, whatever it was
7256 6 : tokenStream.ungetToken();
7257 : }
7258 :
7259 : // Push a ParseContext::ClassStatement to keep track of the constructor
7260 : // funbox.
7261 64 : ParseContext::ClassStatement classStmt(pc);
7262 :
7263 64 : RootedAtom propAtom(context);
7264 :
7265 : // A named class creates a new lexical scope with a const binding of the
7266 : // class name for the "inner name".
7267 64 : Maybe<ParseContext::Statement> innerScopeStmt;
7268 64 : Maybe<ParseContext::Scope> innerScope;
7269 32 : if (name) {
7270 26 : innerScopeStmt.emplace(pc, StatementKind::Block);
7271 26 : innerScope.emplace(this);
7272 26 : if (!innerScope->init(pc))
7273 0 : return null();
7274 : }
7275 :
7276 : // Because the binding definitions keep track of their blockId, we need to
7277 : // create at least the inner binding later. Keep track of the name's position
7278 : // in order to provide it for the nodes created later.
7279 32 : TokenPos namePos = pos();
7280 :
7281 32 : Node classHeritage = null();
7282 : bool hasHeritage;
7283 32 : if (!tokenStream.matchToken(&hasHeritage, TOK_EXTENDS))
7284 0 : return null();
7285 32 : if (hasHeritage) {
7286 16 : if (!tokenStream.getToken(&tt))
7287 0 : return null();
7288 16 : classHeritage = memberExpr(yieldHandling, TripledotProhibited, tt);
7289 16 : if (!classHeritage)
7290 0 : return null();
7291 : }
7292 :
7293 32 : MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CLASS);
7294 :
7295 32 : Node classMethods = handler.newClassMethodList(pos().begin);
7296 32 : if (!classMethods)
7297 0 : return null();
7298 :
7299 64 : Maybe<DeclarationKind> declKind = Nothing();
7300 156 : for (;;) {
7301 : TokenKind tt;
7302 188 : if (!tokenStream.getToken(&tt))
7303 0 : return null();
7304 188 : if (tt == TOK_RC)
7305 32 : break;
7306 :
7307 156 : if (tt == TOK_SEMI)
7308 0 : continue;
7309 :
7310 156 : bool isStatic = false;
7311 156 : if (tt == TOK_STATIC) {
7312 4 : if (!tokenStream.peekToken(&tt))
7313 0 : return null();
7314 4 : if (tt == TOK_RC) {
7315 0 : tokenStream.consumeKnownToken(tt);
7316 0 : error(JSMSG_UNEXPECTED_TOKEN, "property name", TokenKindToDesc(tt));
7317 0 : return null();
7318 : }
7319 :
7320 4 : if (tt != TOK_LP)
7321 4 : isStatic = true;
7322 : else
7323 0 : tokenStream.ungetToken();
7324 : } else {
7325 152 : tokenStream.ungetToken();
7326 : }
7327 :
7328 : uint32_t nameOffset;
7329 156 : if (!tokenStream.peekOffset(&nameOffset))
7330 0 : return null();
7331 :
7332 : PropertyType propType;
7333 156 : Node propName = propertyName(yieldHandling, declKind, classMethods, &propType, &propAtom);
7334 156 : if (!propName)
7335 0 : return null();
7336 :
7337 298 : if (propType != PropertyType::Getter && propType != PropertyType::Setter &&
7338 150 : propType != PropertyType::Method && propType != PropertyType::GeneratorMethod &&
7339 3 : propType != PropertyType::AsyncMethod &&
7340 0 : propType != PropertyType::AsyncGeneratorMethod)
7341 : {
7342 0 : errorAt(nameOffset, JSMSG_BAD_METHOD_DEF);
7343 0 : return null();
7344 : }
7345 :
7346 156 : if (propType == PropertyType::Getter)
7347 13 : propType = PropertyType::GetterNoExpressionClosure;
7348 156 : if (propType == PropertyType::Setter)
7349 1 : propType = PropertyType::SetterNoExpressionClosure;
7350 :
7351 156 : bool isConstructor = !isStatic && propAtom == context->names().constructor;
7352 156 : if (isConstructor) {
7353 31 : if (propType != PropertyType::Method) {
7354 0 : errorAt(nameOffset, JSMSG_BAD_METHOD_DEF);
7355 0 : return null();
7356 : }
7357 31 : if (classStmt.constructorBox) {
7358 0 : errorAt(nameOffset, JSMSG_DUPLICATE_PROPERTY, "constructor");
7359 0 : return null();
7360 : }
7361 31 : propType = hasHeritage ? PropertyType::DerivedConstructor : PropertyType::Constructor;
7362 125 : } else if (isStatic && propAtom == context->names().prototype) {
7363 0 : errorAt(nameOffset, JSMSG_BAD_METHOD_DEF);
7364 0 : return null();
7365 : }
7366 :
7367 312 : RootedAtom funName(context);
7368 156 : switch (propType) {
7369 : case PropertyType::GetterNoExpressionClosure:
7370 : case PropertyType::SetterNoExpressionClosure:
7371 14 : if (!tokenStream.isCurrentTokenType(TOK_RB)) {
7372 14 : funName = prefixAccessorName(propType, propAtom);
7373 14 : if (!funName)
7374 0 : return null();
7375 : }
7376 14 : break;
7377 : case PropertyType::Constructor:
7378 : case PropertyType::DerivedConstructor:
7379 31 : funName = name;
7380 31 : break;
7381 : default:
7382 111 : if (!tokenStream.isCurrentTokenType(TOK_RB))
7383 111 : funName = propAtom;
7384 : }
7385 :
7386 : // Calling toString on constructors need to return the source text for
7387 : // the entire class. The end offset is unknown at this point in
7388 : // parsing and will be amended when class parsing finishes below.
7389 312 : Node fn = methodDefinition(isConstructor ? classStartOffset : nameOffset,
7390 156 : propType, funName);
7391 156 : if (!fn)
7392 0 : return null();
7393 :
7394 156 : handler.checkAndSetIsDirectRHSAnonFunction(fn);
7395 :
7396 156 : JSOp op = JSOpFromPropertyType(propType);
7397 156 : if (!handler.addClassMethodDefinition(classMethods, propName, fn, op, isStatic))
7398 0 : return null();
7399 : }
7400 :
7401 : // Amend the toStringEnd offset for the constructor now that we've
7402 : // finished parsing the class.
7403 32 : uint32_t classEndOffset = pos().end;
7404 32 : if (FunctionBox* ctorbox = classStmt.constructorBox) {
7405 31 : if (ctorbox->function()->isInterpretedLazy())
7406 10 : ctorbox->function()->lazyScript()->setToStringEnd(classEndOffset);
7407 31 : ctorbox->toStringEnd = classEndOffset;
7408 : }
7409 :
7410 32 : Node nameNode = null();
7411 32 : Node methodsOrBlock = classMethods;
7412 32 : if (name) {
7413 : // The inner name is immutable.
7414 26 : if (!noteDeclaredName(name, DeclarationKind::Const, namePos))
7415 0 : return null();
7416 :
7417 26 : Node innerName = newName(name, namePos);
7418 26 : if (!innerName)
7419 0 : return null();
7420 :
7421 26 : Node classBlock = finishLexicalScope(*innerScope, classMethods);
7422 26 : if (!classBlock)
7423 0 : return null();
7424 :
7425 26 : methodsOrBlock = classBlock;
7426 :
7427 : // Pop the inner scope.
7428 26 : innerScope.reset();
7429 26 : innerScopeStmt.reset();
7430 :
7431 26 : Node outerName = null();
7432 26 : if (classContext == ClassStatement) {
7433 : // The outer name is mutable.
7434 26 : if (!noteDeclaredName(name, DeclarationKind::Let, namePos))
7435 0 : return null();
7436 :
7437 26 : outerName = newName(name, namePos);
7438 26 : if (!outerName)
7439 0 : return null();
7440 : }
7441 :
7442 26 : nameNode = handler.newClassNames(outerName, innerName, namePos);
7443 26 : if (!nameNode)
7444 0 : return null();
7445 : }
7446 :
7447 32 : MOZ_ALWAYS_TRUE(setLocalStrictMode(savedStrictness));
7448 :
7449 : return handler.newClass(nameNode, classHeritage, methodsOrBlock,
7450 32 : TokenPos(classStartOffset, classEndOffset));
7451 : }
7452 :
7453 : template <class ParseHandler, typename CharT>
7454 : bool
7455 5256 : Parser<ParseHandler, CharT>::nextTokenContinuesLetDeclaration(TokenKind next,
7456 : YieldHandling yieldHandling)
7457 : {
7458 5256 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LET));
7459 :
7460 : #ifdef DEBUG
7461 : TokenKind verify;
7462 5256 : MOZ_ALWAYS_TRUE(tokenStream.peekToken(&verify));
7463 5256 : MOZ_ASSERT(next == verify);
7464 : #endif
7465 :
7466 : // Destructuring is (for once) the easy case.
7467 5256 : if (next == TOK_LB || next == TOK_LC)
7468 125 : return true;
7469 :
7470 : // If we have the name "yield", the grammar parameter exactly states
7471 : // whether this is okay. (This wasn't true for SpiderMonkey's ancient
7472 : // legacy generator syntax, but that's dead now.) If YieldIsName,
7473 : // declaration-parsing code will (if necessary) enforce a strict mode
7474 : // restriction on defining "yield". If YieldIsKeyword, consider this the
7475 : // end of the declaration, in case ASI induces a semicolon that makes the
7476 : // "yield" valid.
7477 5131 : if (next == TOK_YIELD)
7478 0 : return yieldHandling == YieldIsName;
7479 :
7480 : // Somewhat similar logic applies for "await", except that it's not tracked
7481 : // with an AwaitHandling argument.
7482 5131 : if (next == TOK_AWAIT)
7483 0 : return !awaitIsKeyword();
7484 :
7485 : // Otherwise a let declaration must have a name.
7486 5131 : if (TokenKindIsPossibleIdentifier(next)) {
7487 : // A "let" edge case deserves special comment. Consider this:
7488 : //
7489 : // let // not an ASI opportunity
7490 : // let;
7491 : //
7492 : // Static semantics in §13.3.1.1 turn a LexicalDeclaration that binds
7493 : // "let" into an early error. Does this retroactively permit ASI so
7494 : // that we should parse this as two ExpressionStatements? No. ASI
7495 : // resolves during parsing. Static semantics only apply to the full
7496 : // parse tree with ASI applied. No backsies!
7497 5131 : return true;
7498 : }
7499 :
7500 : // Otherwise not a let declaration.
7501 0 : return false;
7502 : }
7503 :
7504 : template <class ParseHandler, typename CharT>
7505 : typename ParseHandler::Node
7506 4920 : Parser<ParseHandler, CharT>::variableStatement(YieldHandling yieldHandling)
7507 : {
7508 4920 : Node vars = declarationList(yieldHandling, PNK_VAR);
7509 4920 : if (!vars)
7510 0 : return null();
7511 4920 : if (!matchOrInsertSemicolonAfterExpression())
7512 0 : return null();
7513 4920 : return vars;
7514 : }
7515 :
7516 : template <class ParseHandler, typename CharT>
7517 : typename ParseHandler::Node
7518 10809 : Parser<ParseHandler, CharT>::statement(YieldHandling yieldHandling)
7519 : {
7520 10809 : MOZ_ASSERT(checkOptionsCalled);
7521 :
7522 10809 : if (!CheckRecursionLimit(context))
7523 0 : return null();
7524 :
7525 : TokenKind tt;
7526 10809 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
7527 0 : return null();
7528 :
7529 10809 : switch (tt) {
7530 : // BlockStatement[?Yield, ?Return]
7531 : case TOK_LC:
7532 7052 : return blockStatement(yieldHandling);
7533 :
7534 : // VariableStatement[?Yield]
7535 : case TOK_VAR:
7536 1 : return variableStatement(yieldHandling);
7537 :
7538 : // EmptyStatement
7539 : case TOK_SEMI:
7540 1 : return handler.newEmptyStatement(pos());
7541 :
7542 : // ExpressionStatement[?Yield].
7543 :
7544 : case TOK_YIELD: {
7545 : // Don't use a ternary operator here due to obscure linker issues
7546 : // around using static consts in the arms of a ternary.
7547 : TokenStream::Modifier modifier;
7548 6 : if (yieldExpressionsSupported())
7549 6 : modifier = TokenStream::Operand;
7550 : else
7551 0 : modifier = TokenStream::None;
7552 :
7553 : TokenKind next;
7554 6 : if (!tokenStream.peekToken(&next, modifier))
7555 0 : return null();
7556 :
7557 6 : if (next == TOK_COLON)
7558 0 : return labeledStatement(yieldHandling);
7559 :
7560 6 : return expressionStatement(yieldHandling);
7561 : }
7562 :
7563 : default: {
7564 : // Avoid getting next token with None.
7565 2355 : if (tt == TOK_AWAIT && pc->isAsync())
7566 0 : return expressionStatement(yieldHandling);
7567 :
7568 2355 : if (!TokenKindIsPossibleIdentifier(tt))
7569 144 : return expressionStatement(yieldHandling);
7570 :
7571 : TokenKind next;
7572 2211 : if (!tokenStream.peekToken(&next))
7573 0 : return null();
7574 :
7575 : // |let| here can only be an Identifier, not a declaration. Give nicer
7576 : // errors for declaration-looking typos.
7577 2211 : if (tt == TOK_LET) {
7578 0 : bool forbiddenLetDeclaration = false;
7579 :
7580 0 : if (next == TOK_LB) {
7581 : // Enforce ExpressionStatement's 'let [' lookahead restriction.
7582 0 : forbiddenLetDeclaration = true;
7583 0 : } else if (next == TOK_LC || TokenKindIsPossibleIdentifier(next)) {
7584 : // 'let {' and 'let foo' aren't completely forbidden, if ASI
7585 : // causes 'let' to be the entire Statement. But if they're
7586 : // same-line, we can aggressively give a better error message.
7587 : //
7588 : // Note that this ignores 'yield' as TOK_YIELD: we'll handle it
7589 : // correctly but with a worse error message.
7590 : TokenKind nextSameLine;
7591 0 : if (!tokenStream.peekTokenSameLine(&nextSameLine))
7592 0 : return null();
7593 :
7594 0 : MOZ_ASSERT(TokenKindIsPossibleIdentifier(nextSameLine) ||
7595 : nextSameLine == TOK_LC ||
7596 : nextSameLine == TOK_EOL);
7597 :
7598 0 : forbiddenLetDeclaration = nextSameLine != TOK_EOL;
7599 : }
7600 :
7601 0 : if (forbiddenLetDeclaration) {
7602 0 : error(JSMSG_FORBIDDEN_AS_STATEMENT, "lexical declarations");
7603 0 : return null();
7604 : }
7605 2211 : } else if (tt == TOK_ASYNC) {
7606 : // Peek only on the same line: ExpressionStatement's lookahead
7607 : // restriction is phrased as
7608 : //
7609 : // [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]
7610 : //
7611 : // meaning that code like this is valid:
7612 : //
7613 : // if (true)
7614 : // async // ASI opportunity
7615 : // function clownshoes() {}
7616 : TokenKind maybeFunction;
7617 0 : if (!tokenStream.peekTokenSameLine(&maybeFunction))
7618 0 : return null();
7619 :
7620 0 : if (maybeFunction == TOK_FUNCTION) {
7621 0 : error(JSMSG_FORBIDDEN_AS_STATEMENT, "async function declarations");
7622 0 : return null();
7623 : }
7624 :
7625 : // Otherwise this |async| begins an ExpressionStatement or is a
7626 : // label name.
7627 : }
7628 :
7629 : // NOTE: It's unfortunately allowed to have a label named 'let' in
7630 : // non-strict code. 💯
7631 2211 : if (next == TOK_COLON)
7632 0 : return labeledStatement(yieldHandling);
7633 :
7634 2211 : return expressionStatement(yieldHandling);
7635 : }
7636 :
7637 : case TOK_NEW:
7638 0 : return expressionStatement(yieldHandling, PredictInvoked);
7639 :
7640 : // IfStatement[?Yield, ?Return]
7641 : case TOK_IF:
7642 3 : return ifStatement(yieldHandling);
7643 :
7644 : // BreakableStatement[?Yield, ?Return]
7645 : //
7646 : // BreakableStatement[Yield, Return]:
7647 : // IterationStatement[?Yield, ?Return]
7648 : // SwitchStatement[?Yield, ?Return]
7649 : case TOK_DO:
7650 0 : return doWhileStatement(yieldHandling);
7651 :
7652 : case TOK_WHILE:
7653 0 : return whileStatement(yieldHandling);
7654 :
7655 : case TOK_FOR:
7656 0 : return forStatement(yieldHandling);
7657 :
7658 : case TOK_SWITCH:
7659 0 : return switchStatement(yieldHandling);
7660 :
7661 : // ContinueStatement[?Yield]
7662 : case TOK_CONTINUE:
7663 53 : return continueStatement(yieldHandling);
7664 :
7665 : // BreakStatement[?Yield]
7666 : case TOK_BREAK:
7667 83 : return breakStatement(yieldHandling);
7668 :
7669 : // [+Return] ReturnStatement[?Yield]
7670 : case TOK_RETURN:
7671 : // The Return parameter is only used here, and the effect is easily
7672 : // detected this way, so don't bother passing around an extra parameter
7673 : // everywhere.
7674 1100 : if (!pc->isFunctionBox()) {
7675 0 : error(JSMSG_BAD_RETURN_OR_YIELD, js_return_str);
7676 0 : return null();
7677 : }
7678 1100 : return returnStatement(yieldHandling);
7679 :
7680 : // WithStatement[?Yield, ?Return]
7681 : case TOK_WITH:
7682 0 : return withStatement(yieldHandling);
7683 :
7684 : // LabelledStatement[?Yield, ?Return]
7685 : // This is really handled by default and TOK_YIELD cases above.
7686 :
7687 : // ThrowStatement[?Yield]
7688 : case TOK_THROW:
7689 155 : return throwStatement(yieldHandling);
7690 :
7691 : // TryStatement[?Yield, ?Return]
7692 : case TOK_TRY:
7693 0 : return tryStatement(yieldHandling);
7694 :
7695 : // DebuggerStatement
7696 : case TOK_DEBUGGER:
7697 0 : return debuggerStatement();
7698 :
7699 : // |function| is forbidden by lookahead restriction (unless as child
7700 : // statement of |if| or |else|, but Parser::consequentOrAlternative
7701 : // handles that).
7702 : case TOK_FUNCTION:
7703 0 : error(JSMSG_FORBIDDEN_AS_STATEMENT, "function declarations");
7704 0 : return null();
7705 :
7706 : // |class| is also forbidden by lookahead restriction.
7707 : case TOK_CLASS:
7708 0 : error(JSMSG_FORBIDDEN_AS_STATEMENT, "classes");
7709 0 : return null();
7710 :
7711 : // ImportDeclaration (only inside modules)
7712 : case TOK_IMPORT:
7713 0 : return importDeclaration();
7714 :
7715 : // ExportDeclaration (only inside modules)
7716 : case TOK_EXPORT:
7717 0 : return exportDeclaration();
7718 :
7719 : // Miscellaneous error cases arguably better caught here than elsewhere.
7720 :
7721 : case TOK_CATCH:
7722 0 : error(JSMSG_CATCH_WITHOUT_TRY);
7723 0 : return null();
7724 :
7725 : case TOK_FINALLY:
7726 0 : error(JSMSG_FINALLY_WITHOUT_TRY);
7727 0 : return null();
7728 :
7729 : // NOTE: default case handled in the ExpressionStatement section.
7730 : }
7731 : }
7732 :
7733 : template <class ParseHandler, typename CharT>
7734 : typename ParseHandler::Node
7735 47031 : Parser<ParseHandler, CharT>::statementListItem(YieldHandling yieldHandling,
7736 : bool canHaveDirectives /* = false */)
7737 : {
7738 47031 : MOZ_ASSERT(checkOptionsCalled);
7739 :
7740 47031 : if (!CheckRecursionLimit(context))
7741 0 : return null();
7742 :
7743 : TokenKind tt;
7744 47031 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
7745 0 : return null();
7746 :
7747 47031 : switch (tt) {
7748 : // BlockStatement[?Yield, ?Return]
7749 : case TOK_LC:
7750 154 : return blockStatement(yieldHandling);
7751 :
7752 : // VariableStatement[?Yield]
7753 : case TOK_VAR:
7754 4919 : return variableStatement(yieldHandling);
7755 :
7756 : // EmptyStatement
7757 : case TOK_SEMI:
7758 11 : return handler.newEmptyStatement(pos());
7759 :
7760 : // ExpressionStatement[?Yield].
7761 : //
7762 : // These should probably be handled by a single ExpressionStatement
7763 : // function in a default, not split up this way.
7764 : case TOK_STRING:
7765 112 : if (!canHaveDirectives && tokenStream.currentToken().atom() == context->names().useAsm) {
7766 0 : if (!abortIfSyntaxParser())
7767 0 : return null();
7768 0 : if (!warning(JSMSG_USE_ASM_DIRECTIVE_FAIL))
7769 0 : return null();
7770 : }
7771 112 : return expressionStatement(yieldHandling);
7772 :
7773 : case TOK_YIELD: {
7774 : // Don't use a ternary operator here due to obscure linker issues
7775 : // around using static consts in the arms of a ternary.
7776 : TokenStream::Modifier modifier;
7777 18 : if (yieldExpressionsSupported())
7778 18 : modifier = TokenStream::Operand;
7779 : else
7780 0 : modifier = TokenStream::None;
7781 :
7782 : TokenKind next;
7783 18 : if (!tokenStream.peekToken(&next, modifier))
7784 0 : return null();
7785 :
7786 18 : if (next == TOK_COLON)
7787 0 : return labeledStatement(yieldHandling);
7788 :
7789 18 : return expressionStatement(yieldHandling);
7790 : }
7791 :
7792 : default: {
7793 : // Avoid getting next token with None.
7794 20569 : if (tt == TOK_AWAIT && pc->isAsync())
7795 206 : return expressionStatement(yieldHandling);
7796 :
7797 20363 : if (!TokenKindIsPossibleIdentifier(tt))
7798 4181 : return expressionStatement(yieldHandling);
7799 :
7800 : TokenKind next;
7801 16182 : if (!tokenStream.peekToken(&next))
7802 0 : return null();
7803 :
7804 16182 : if (tt == TOK_LET && nextTokenContinuesLetDeclaration(next, yieldHandling))
7805 4615 : return lexicalDeclaration(yieldHandling, DeclarationKind::Let);
7806 :
7807 11567 : if (tt == TOK_ASYNC) {
7808 6 : TokenKind nextSameLine = TOK_EOF;
7809 6 : if (!tokenStream.peekTokenSameLine(&nextSameLine))
7810 6 : return null();
7811 6 : if (nextSameLine == TOK_FUNCTION) {
7812 6 : uint32_t toStringStart = pos().begin;
7813 6 : tokenStream.consumeKnownToken(TOK_FUNCTION);
7814 6 : return functionStmt(toStringStart, yieldHandling, NameRequired, AsyncFunction);
7815 : }
7816 : }
7817 :
7818 11561 : if (next == TOK_COLON)
7819 0 : return labeledStatement(yieldHandling);
7820 :
7821 11561 : return expressionStatement(yieldHandling);
7822 : }
7823 :
7824 : case TOK_NEW:
7825 21 : return expressionStatement(yieldHandling, PredictInvoked);
7826 :
7827 : // IfStatement[?Yield, ?Return]
7828 : case TOK_IF:
7829 8442 : return ifStatement(yieldHandling);
7830 :
7831 : // BreakableStatement[?Yield, ?Return]
7832 : //
7833 : // BreakableStatement[Yield, Return]:
7834 : // IterationStatement[?Yield, ?Return]
7835 : // SwitchStatement[?Yield, ?Return]
7836 : case TOK_DO:
7837 20 : return doWhileStatement(yieldHandling);
7838 :
7839 : case TOK_WHILE:
7840 204 : return whileStatement(yieldHandling);
7841 :
7842 : case TOK_FOR:
7843 991 : return forStatement(yieldHandling);
7844 :
7845 : case TOK_SWITCH:
7846 275 : return switchStatement(yieldHandling);
7847 :
7848 : // ContinueStatement[?Yield]
7849 : case TOK_CONTINUE:
7850 112 : return continueStatement(yieldHandling);
7851 :
7852 : // BreakStatement[?Yield]
7853 : case TOK_BREAK:
7854 593 : return breakStatement(yieldHandling);
7855 :
7856 : // [+Return] ReturnStatement[?Yield]
7857 : case TOK_RETURN:
7858 : // The Return parameter is only used here, and the effect is easily
7859 : // detected this way, so don't bother passing around an extra parameter
7860 : // everywhere.
7861 6212 : if (!pc->isFunctionBox()) {
7862 0 : error(JSMSG_BAD_RETURN_OR_YIELD, js_return_str);
7863 0 : return null();
7864 : }
7865 6212 : return returnStatement(yieldHandling);
7866 :
7867 : // WithStatement[?Yield, ?Return]
7868 : case TOK_WITH:
7869 0 : return withStatement(yieldHandling);
7870 :
7871 : // LabelledStatement[?Yield, ?Return]
7872 : // This is really handled by default and TOK_YIELD cases above.
7873 :
7874 : // ThrowStatement[?Yield]
7875 : case TOK_THROW:
7876 424 : return throwStatement(yieldHandling);
7877 :
7878 : // TryStatement[?Yield, ?Return]
7879 : case TOK_TRY:
7880 684 : return tryStatement(yieldHandling);
7881 :
7882 : // DebuggerStatement
7883 : case TOK_DEBUGGER:
7884 0 : return debuggerStatement();
7885 :
7886 : // Declaration[Yield]:
7887 :
7888 : // HoistableDeclaration[?Yield, ~Default]
7889 : case TOK_FUNCTION:
7890 1825 : return functionStmt(pos().begin, yieldHandling, NameRequired);
7891 :
7892 : // ClassDeclaration[?Yield, ~Default]
7893 : case TOK_CLASS:
7894 26 : return classDefinition(yieldHandling, ClassStatement, NameRequired);
7895 :
7896 : // LexicalDeclaration[In, ?Yield]
7897 : // LetOrConst BindingList[?In, ?Yield]
7898 : case TOK_CONST:
7899 : // [In] is the default behavior, because for-loops specially parse
7900 : // their heads to handle |in| in this situation.
7901 1419 : return lexicalDeclaration(yieldHandling, DeclarationKind::Const);
7902 :
7903 : // ImportDeclaration (only inside modules)
7904 : case TOK_IMPORT:
7905 0 : return importDeclaration();
7906 :
7907 : // ExportDeclaration (only inside modules)
7908 : case TOK_EXPORT:
7909 0 : return exportDeclaration();
7910 :
7911 : // Miscellaneous error cases arguably better caught here than elsewhere.
7912 :
7913 : case TOK_CATCH:
7914 0 : error(JSMSG_CATCH_WITHOUT_TRY);
7915 0 : return null();
7916 :
7917 : case TOK_FINALLY:
7918 0 : error(JSMSG_FINALLY_WITHOUT_TRY);
7919 0 : return null();
7920 :
7921 : // NOTE: default case handled in the ExpressionStatement section.
7922 : }
7923 : }
7924 :
7925 : template <class ParseHandler, typename CharT>
7926 : typename ParseHandler::Node
7927 43617 : Parser<ParseHandler, CharT>::expr(InHandling inHandling, YieldHandling yieldHandling,
7928 : TripledotHandling tripledotHandling,
7929 : PossibleError* possibleError /* = nullptr */,
7930 : InvokedPrediction invoked /* = PredictUninvoked */)
7931 : {
7932 : Node pn = assignExpr(inHandling, yieldHandling, tripledotHandling,
7933 43617 : possibleError, invoked);
7934 43617 : if (!pn)
7935 0 : return null();
7936 :
7937 : bool matched;
7938 43617 : if (!tokenStream.matchToken(&matched, TOK_COMMA))
7939 0 : return null();
7940 43617 : if (!matched)
7941 43475 : return pn;
7942 :
7943 142 : Node seq = handler.newCommaExpressionList(pn);
7944 142 : if (!seq)
7945 0 : return null();
7946 44 : while (true) {
7947 : // Trailing comma before the closing parenthesis is valid in an arrow
7948 : // function parameters list: `(a, b, ) => body`. Check if we are
7949 : // directly under CoverParenthesizedExpressionAndArrowParameterList,
7950 : // and the next two tokens are closing parenthesis and arrow. If all
7951 : // are present allow the trailing comma.
7952 186 : if (tripledotHandling == TripledotAllowed) {
7953 : TokenKind tt;
7954 172 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
7955 0 : return null();
7956 :
7957 172 : if (tt == TOK_RP) {
7958 0 : tokenStream.consumeKnownToken(TOK_RP, TokenStream::Operand);
7959 :
7960 0 : if (!tokenStream.peekToken(&tt))
7961 0 : return null();
7962 0 : if (tt != TOK_ARROW) {
7963 0 : error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(TOK_RP));
7964 0 : return null();
7965 : }
7966 :
7967 0 : tokenStream.ungetToken(); // put back right paren
7968 0 : tokenStream.addModifierException(TokenStream::NoneIsOperand);
7969 0 : break;
7970 : }
7971 : }
7972 :
7973 : // Additional calls to assignExpr should not reuse the possibleError
7974 : // which had been passed into the function. Otherwise we would lose
7975 : // information needed to determine whether or not we're dealing with
7976 : // a non-recoverable situation.
7977 186 : PossibleError possibleErrorInner(*this);
7978 186 : pn = assignExpr(inHandling, yieldHandling, tripledotHandling,
7979 : &possibleErrorInner);
7980 186 : if (!pn)
7981 0 : return null();
7982 :
7983 186 : if (!possibleError) {
7984 : // Report any pending expression error.
7985 14 : if (!possibleErrorInner.checkForExpressionError())
7986 0 : return null();
7987 : } else {
7988 172 : possibleErrorInner.transferErrorsTo(possibleError);
7989 : }
7990 :
7991 186 : handler.addList(seq, pn);
7992 :
7993 186 : if (!tokenStream.matchToken(&matched, TOK_COMMA))
7994 0 : return null();
7995 186 : if (!matched)
7996 142 : break;
7997 : }
7998 142 : return seq;
7999 : }
8000 :
8001 : static const JSOp ParseNodeKindToJSOp[] = {
8002 : JSOP_OR,
8003 : JSOP_AND,
8004 : JSOP_BITOR,
8005 : JSOP_BITXOR,
8006 : JSOP_BITAND,
8007 : JSOP_STRICTEQ,
8008 : JSOP_EQ,
8009 : JSOP_STRICTNE,
8010 : JSOP_NE,
8011 : JSOP_LT,
8012 : JSOP_LE,
8013 : JSOP_GT,
8014 : JSOP_GE,
8015 : JSOP_INSTANCEOF,
8016 : JSOP_IN,
8017 : JSOP_LSH,
8018 : JSOP_RSH,
8019 : JSOP_URSH,
8020 : JSOP_ADD,
8021 : JSOP_SUB,
8022 : JSOP_MUL,
8023 : JSOP_DIV,
8024 : JSOP_MOD,
8025 : JSOP_POW
8026 : };
8027 :
8028 : static inline JSOp
8029 16399 : BinaryOpParseNodeKindToJSOp(ParseNodeKind pnk)
8030 : {
8031 16399 : MOZ_ASSERT(pnk >= PNK_BINOP_FIRST);
8032 16399 : MOZ_ASSERT(pnk <= PNK_BINOP_LAST);
8033 16399 : return ParseNodeKindToJSOp[pnk - PNK_BINOP_FIRST];
8034 : }
8035 :
8036 : static ParseNodeKind
8037 16399 : BinaryOpTokenKindToParseNodeKind(TokenKind tok)
8038 : {
8039 16399 : MOZ_ASSERT(TokenKindIsBinaryOp(tok));
8040 16399 : return ParseNodeKind(PNK_BINOP_FIRST + (tok - TOK_BINOP_FIRST));
8041 : }
8042 :
8043 : static const int PrecedenceTable[] = {
8044 : 1, /* PNK_OR */
8045 : 2, /* PNK_AND */
8046 : 3, /* PNK_BITOR */
8047 : 4, /* PNK_BITXOR */
8048 : 5, /* PNK_BITAND */
8049 : 6, /* PNK_STRICTEQ */
8050 : 6, /* PNK_EQ */
8051 : 6, /* PNK_STRICTNE */
8052 : 6, /* PNK_NE */
8053 : 7, /* PNK_LT */
8054 : 7, /* PNK_LE */
8055 : 7, /* PNK_GT */
8056 : 7, /* PNK_GE */
8057 : 7, /* PNK_INSTANCEOF */
8058 : 7, /* PNK_IN */
8059 : 8, /* PNK_LSH */
8060 : 8, /* PNK_RSH */
8061 : 8, /* PNK_URSH */
8062 : 9, /* PNK_ADD */
8063 : 9, /* PNK_SUB */
8064 : 10, /* PNK_STAR */
8065 : 10, /* PNK_DIV */
8066 : 10, /* PNK_MOD */
8067 : 11 /* PNK_POW */
8068 : };
8069 :
8070 : static const int PRECEDENCE_CLASSES = 11;
8071 :
8072 : static int
8073 35440 : Precedence(ParseNodeKind pnk) {
8074 : // Everything binds tighter than PNK_LIMIT, because we want to reduce all
8075 : // nodes to a single node when we reach a token that is not another binary
8076 : // operator.
8077 35440 : if (pnk == PNK_LIMIT)
8078 11795 : return 0;
8079 :
8080 23645 : MOZ_ASSERT(pnk >= PNK_BINOP_FIRST);
8081 23645 : MOZ_ASSERT(pnk <= PNK_BINOP_LAST);
8082 23645 : return PrecedenceTable[pnk - PNK_BINOP_FIRST];
8083 : }
8084 :
8085 : template <class ParseHandler, typename CharT>
8086 : MOZ_ALWAYS_INLINE typename ParseHandler::Node
8087 72187 : Parser<ParseHandler, CharT>::orExpr1(InHandling inHandling, YieldHandling yieldHandling,
8088 : TripledotHandling tripledotHandling,
8089 : PossibleError* possibleError,
8090 : InvokedPrediction invoked /* = PredictUninvoked */)
8091 : {
8092 : // Shift-reduce parser for the binary operator part of the JS expression
8093 : // syntax.
8094 :
8095 : // Conceptually there's just one stack, a stack of pairs (lhs, op).
8096 : // It's implemented using two separate arrays, though.
8097 : Node nodeStack[PRECEDENCE_CLASSES];
8098 : ParseNodeKind kindStack[PRECEDENCE_CLASSES];
8099 72187 : int depth = 0;
8100 : Node pn;
8101 16399 : for (;;) {
8102 88586 : pn = unaryExpr(yieldHandling, tripledotHandling, possibleError, invoked);
8103 88586 : if (!pn)
8104 0 : return pn;
8105 :
8106 : // If a binary operator follows, consume it and compute the
8107 : // corresponding operator.
8108 : TokenKind tok;
8109 88586 : if (!tokenStream.getToken(&tok))
8110 0 : return null();
8111 :
8112 : ParseNodeKind pnk;
8113 88586 : if (tok == TOK_IN ? inHandling == InAllowed : TokenKindIsBinaryOp(tok)) {
8114 : // We're definitely not in a destructuring context, so report any
8115 : // pending expression error now.
8116 16399 : if (possibleError && !possibleError->checkForExpressionError())
8117 0 : return null();
8118 : // Report an error for unary expressions on the LHS of **.
8119 16399 : if (tok == TOK_POW && handler.isUnparenthesizedUnaryExpression(pn)) {
8120 0 : error(JSMSG_BAD_POW_LEFTSIDE);
8121 0 : return null();
8122 : }
8123 16399 : pnk = BinaryOpTokenKindToParseNodeKind(tok);
8124 : } else {
8125 72187 : tok = TOK_EOF;
8126 72187 : pnk = PNK_LIMIT;
8127 : }
8128 :
8129 : // From this point on, destructuring defaults are definitely an error.
8130 88586 : possibleError = nullptr;
8131 :
8132 : // If pnk has precedence less than or equal to another operator on the
8133 : // stack, reduce. This combines nodes on the stack until we form the
8134 : // actual lhs of pnk.
8135 : //
8136 : // The >= in this condition works because it is appendOrCreateList's
8137 : // job to decide if the operator in question is left- or
8138 : // right-associative, and build the corresponding tree.
8139 121384 : while (depth > 0 && Precedence(kindStack[depth - 1]) >= Precedence(pnk)) {
8140 16399 : depth--;
8141 16399 : ParseNodeKind combiningPnk = kindStack[depth];
8142 16399 : JSOp combiningOp = BinaryOpParseNodeKindToJSOp(combiningPnk);
8143 16399 : pn = handler.appendOrCreateList(combiningPnk, nodeStack[depth], pn, pc, combiningOp);
8144 16399 : if (!pn)
8145 0 : return pn;
8146 : }
8147 :
8148 88586 : if (pnk == PNK_LIMIT)
8149 72187 : break;
8150 :
8151 16399 : nodeStack[depth] = pn;
8152 16399 : kindStack[depth] = pnk;
8153 16399 : depth++;
8154 16399 : MOZ_ASSERT(depth <= PRECEDENCE_CLASSES);
8155 : }
8156 :
8157 72187 : MOZ_ASSERT(depth == 0);
8158 72187 : return pn;
8159 : }
8160 :
8161 : template <class ParseHandler, typename CharT>
8162 : MOZ_ALWAYS_INLINE typename ParseHandler::Node
8163 72187 : Parser<ParseHandler, CharT>::condExpr1(InHandling inHandling, YieldHandling yieldHandling,
8164 : TripledotHandling tripledotHandling,
8165 : PossibleError* possibleError,
8166 : InvokedPrediction invoked /* = PredictUninvoked */)
8167 : {
8168 72187 : Node condition = orExpr1(inHandling, yieldHandling, tripledotHandling, possibleError, invoked);
8169 :
8170 72187 : if (!condition || !tokenStream.isCurrentTokenType(TOK_HOOK))
8171 71449 : return condition;
8172 :
8173 738 : Node thenExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
8174 738 : if (!thenExpr)
8175 0 : return null();
8176 :
8177 738 : MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_IN_COND);
8178 :
8179 738 : Node elseExpr = assignExpr(inHandling, yieldHandling, TripledotProhibited);
8180 738 : if (!elseExpr)
8181 0 : return null();
8182 :
8183 : // Advance to the next token; the caller is responsible for interpreting it.
8184 : TokenKind ignored;
8185 738 : if (!tokenStream.getToken(&ignored))
8186 0 : return null();
8187 738 : return handler.newConditional(condition, thenExpr, elseExpr);
8188 : }
8189 :
8190 : template <class ParseHandler, typename CharT>
8191 : typename ParseHandler::Node
8192 119431 : Parser<ParseHandler, CharT>::assignExpr(InHandling inHandling, YieldHandling yieldHandling,
8193 : TripledotHandling tripledotHandling,
8194 : PossibleError* possibleError /* = nullptr */,
8195 : InvokedPrediction invoked /* = PredictUninvoked */)
8196 : {
8197 119431 : if (!CheckRecursionLimit(context))
8198 0 : return null();
8199 :
8200 : // It's very common at this point to have a "detectably simple" expression,
8201 : // i.e. a name/number/string token followed by one of the following tokens
8202 : // that obviously isn't part of an expression: , ; : ) ] }
8203 : //
8204 : // (In Parsemark this happens 81.4% of the time; in code with large
8205 : // numeric arrays, such as some Kraken benchmarks, it happens more often.)
8206 : //
8207 : // In such cases, we can avoid the full expression parsing route through
8208 : // assignExpr(), condExpr1(), orExpr1(), unaryExpr(), memberExpr(), and
8209 : // primaryExpr().
8210 :
8211 : TokenKind tt;
8212 119431 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
8213 0 : return null();
8214 :
8215 119431 : TokenPos exprPos = pos();
8216 :
8217 : bool endsExpr;
8218 :
8219 : // This only handles identifiers that *never* have special meaning anywhere
8220 : // in the language. Contextual keywords, reserved words in strict mode,
8221 : // and other hard cases are handled outside this fast path.
8222 119431 : if (tt == TOK_NAME) {
8223 70154 : if (!tokenStream.nextTokenEndsExpr(&endsExpr))
8224 0 : return null();
8225 70154 : if (endsExpr) {
8226 54750 : Rooted<PropertyName*> name(context, identifierReference(yieldHandling));
8227 27375 : if (!name)
8228 0 : return null();
8229 :
8230 27375 : return identifierReference(name);
8231 : }
8232 : }
8233 :
8234 92056 : if (tt == TOK_NUMBER) {
8235 6208 : if (!tokenStream.nextTokenEndsExpr(&endsExpr))
8236 0 : return null();
8237 6208 : if (endsExpr)
8238 6027 : return newNumber(tokenStream.currentToken());
8239 : }
8240 :
8241 86029 : if (tt == TOK_STRING) {
8242 15360 : if (!tokenStream.nextTokenEndsExpr(&endsExpr))
8243 0 : return null();
8244 15360 : if (endsExpr)
8245 13818 : return stringLiteral();
8246 : }
8247 :
8248 72211 : if (tt == TOK_YIELD && yieldExpressionsSupported())
8249 24 : return yieldExpression(inHandling);
8250 :
8251 72187 : bool maybeAsyncArrow = false;
8252 72187 : if (tt == TOK_ASYNC) {
8253 48 : TokenKind nextSameLine = TOK_EOF;
8254 48 : if (!tokenStream.peekTokenSameLine(&nextSameLine))
8255 0 : return null();
8256 :
8257 48 : if (TokenKindIsPossibleIdentifier(nextSameLine))
8258 0 : maybeAsyncArrow = true;
8259 : }
8260 :
8261 72187 : tokenStream.ungetToken();
8262 :
8263 : // Save the tokenizer state in case we find an arrow function and have to
8264 : // rewind.
8265 72187 : TokenStream::Position start(keepAtoms);
8266 72187 : tokenStream.tell(&start);
8267 :
8268 72187 : PossibleError possibleErrorInner(*this);
8269 : Node lhs;
8270 72187 : if (maybeAsyncArrow) {
8271 0 : tokenStream.consumeKnownToken(TOK_ASYNC, TokenStream::Operand);
8272 :
8273 : TokenKind tt;
8274 0 : if (!tokenStream.getToken(&tt))
8275 0 : return null();
8276 0 : MOZ_ASSERT(TokenKindIsPossibleIdentifier(tt));
8277 :
8278 : // Check yield validity here.
8279 0 : RootedPropertyName name(context, bindingIdentifier(yieldHandling));
8280 0 : if (!name)
8281 0 : return null();
8282 :
8283 0 : if (!tokenStream.getToken(&tt))
8284 0 : return null();
8285 0 : if (tt != TOK_ARROW) {
8286 0 : error(JSMSG_UNEXPECTED_TOKEN, "'=>' after argument list", TokenKindToDesc(tt));
8287 :
8288 0 : return null();
8289 : }
8290 : } else {
8291 72187 : lhs = condExpr1(inHandling, yieldHandling, tripledotHandling, &possibleErrorInner, invoked);
8292 72187 : if (!lhs) {
8293 0 : return null();
8294 : }
8295 : }
8296 :
8297 : ParseNodeKind kind;
8298 : JSOp op;
8299 72187 : switch (tokenStream.currentToken().type) {
8300 6783 : case TOK_ASSIGN: kind = PNK_ASSIGN; op = JSOP_NOP; break;
8301 385 : case TOK_ADDASSIGN: kind = PNK_ADDASSIGN; op = JSOP_ADD; break;
8302 19 : case TOK_SUBASSIGN: kind = PNK_SUBASSIGN; op = JSOP_SUB; break;
8303 33 : case TOK_BITORASSIGN: kind = PNK_BITORASSIGN; op = JSOP_BITOR; break;
8304 18 : case TOK_BITXORASSIGN: kind = PNK_BITXORASSIGN; op = JSOP_BITXOR; break;
8305 0 : case TOK_BITANDASSIGN: kind = PNK_BITANDASSIGN; op = JSOP_BITAND; break;
8306 0 : case TOK_LSHASSIGN: kind = PNK_LSHASSIGN; op = JSOP_LSH; break;
8307 3 : case TOK_RSHASSIGN: kind = PNK_RSHASSIGN; op = JSOP_RSH; break;
8308 0 : case TOK_URSHASSIGN: kind = PNK_URSHASSIGN; op = JSOP_URSH; break;
8309 10 : case TOK_MULASSIGN: kind = PNK_MULASSIGN; op = JSOP_MUL; break;
8310 2 : case TOK_DIVASSIGN: kind = PNK_DIVASSIGN; op = JSOP_DIV; break;
8311 0 : case TOK_MODASSIGN: kind = PNK_MODASSIGN; op = JSOP_MOD; break;
8312 0 : case TOK_POWASSIGN: kind = PNK_POWASSIGN; op = JSOP_POW; break;
8313 :
8314 : case TOK_ARROW: {
8315 :
8316 : // A line terminator between ArrowParameters and the => should trigger a SyntaxError.
8317 1014 : tokenStream.ungetToken();
8318 : TokenKind next;
8319 1014 : if (!tokenStream.peekTokenSameLine(&next))
8320 0 : return null();
8321 1014 : MOZ_ASSERT(next == TOK_ARROW || next == TOK_EOL);
8322 :
8323 1014 : if (next != TOK_ARROW) {
8324 0 : error(JSMSG_LINE_BREAK_BEFORE_ARROW);
8325 0 : return null();
8326 : }
8327 1014 : tokenStream.consumeKnownToken(TOK_ARROW);
8328 :
8329 1014 : bool isBlock = false;
8330 1014 : if (!tokenStream.peekToken(&next, TokenStream::Operand))
8331 0 : return null();
8332 1014 : if (next == TOK_LC)
8333 518 : isBlock = true;
8334 :
8335 1014 : tokenStream.seek(start);
8336 :
8337 1014 : if (!tokenStream.getToken(&next, TokenStream::Operand))
8338 0 : return null();
8339 1014 : uint32_t toStringStart = pos().begin;
8340 1014 : tokenStream.ungetToken();
8341 :
8342 1014 : FunctionAsyncKind asyncKind = SyncFunction;
8343 :
8344 1014 : if (next == TOK_ASYNC) {
8345 40 : tokenStream.consumeKnownToken(next, TokenStream::Operand);
8346 :
8347 40 : TokenKind nextSameLine = TOK_EOF;
8348 40 : if (!tokenStream.peekTokenSameLine(&nextSameLine))
8349 0 : return null();
8350 :
8351 : // The AsyncArrowFunction production are
8352 : // async [no LineTerminator here] AsyncArrowBindingIdentifier ...
8353 : // async [no LineTerminator here] ArrowFormalParameters ...
8354 40 : if (TokenKindIsPossibleIdentifier(nextSameLine) || nextSameLine == TOK_LP)
8355 40 : asyncKind = AsyncFunction;
8356 : else
8357 0 : tokenStream.ungetToken();
8358 : }
8359 :
8360 1014 : Node pn = handler.newArrowFunction(pos());
8361 1014 : if (!pn)
8362 0 : return null();
8363 :
8364 2028 : Node arrowFunc = functionDefinition(pn, toStringStart, inHandling, yieldHandling, nullptr,
8365 1014 : Arrow, NotGenerator, asyncKind);
8366 1014 : if (!arrowFunc)
8367 0 : return null();
8368 :
8369 1014 : if (isBlock) {
8370 : // This arrow function could be a non-trailing member of a comma
8371 : // expression or a semicolon terminating a full expression. If so,
8372 : // the next token is that comma/semicolon, gotten with None:
8373 : //
8374 : // a => {}, b; // as if (a => {}), b;
8375 : // a => {};
8376 : //
8377 : // But if this arrow function ends a statement, ASI permits the
8378 : // next token to start an expression statement. In that case the
8379 : // next token must be gotten as Operand:
8380 : //
8381 : // a => {} // complete expression statement
8382 : // /x/g; // regular expression as a statement, *not* division
8383 : //
8384 : // Getting the second case right requires the first token-peek
8385 : // after the arrow function use Operand, and that peek must occur
8386 : // before Parser::expr() looks for a comma. Do so here, then
8387 : // immediately add the modifier exception needed for the first
8388 : // case.
8389 : //
8390 : // Note that the second case occurs *only* if the arrow function
8391 : // has block body. An arrow function not ending in such, ends in
8392 : // another AssignmentExpression that we can inductively assume was
8393 : // peeked consistently.
8394 : TokenKind ignored;
8395 518 : if (!tokenStream.peekToken(&ignored, TokenStream::Operand))
8396 0 : return null();
8397 518 : tokenStream.addModifierException(TokenStream::NoneIsOperand);
8398 : }
8399 1014 : return arrowFunc;
8400 : }
8401 :
8402 : default:
8403 63920 : MOZ_ASSERT(!tokenStream.isCurrentTokenAssignment());
8404 63920 : if (!possibleError) {
8405 58861 : if (!possibleErrorInner.checkForExpressionError())
8406 0 : return null();
8407 : } else {
8408 5059 : possibleErrorInner.transferErrorsTo(possibleError);
8409 : }
8410 63920 : tokenStream.ungetToken();
8411 63920 : return lhs;
8412 : }
8413 :
8414 : // Verify the left-hand side expression doesn't have a forbidden form.
8415 7253 : if (handler.isUnparenthesizedDestructuringPattern(lhs)) {
8416 13 : if (kind != PNK_ASSIGN) {
8417 0 : error(JSMSG_BAD_DESTRUCT_ASS);
8418 0 : return null();
8419 : }
8420 :
8421 13 : if (!possibleErrorInner.checkForDestructuringErrorOrWarning())
8422 0 : return null();
8423 7240 : } else if (handler.isNameAnyParentheses(lhs)) {
8424 3002 : if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(lhs, context)) {
8425 : // |chars| is "arguments" or "eval" here.
8426 0 : if (!strictModeErrorAt(exprPos.begin, JSMSG_BAD_STRICT_ASSIGN, chars))
8427 0 : return null();
8428 : }
8429 :
8430 3002 : handler.adjustGetToSet(lhs);
8431 4238 : } else if (handler.isPropertyAccess(lhs)) {
8432 : // Permitted: no additional testing/fixup needed.
8433 0 : } else if (handler.isFunctionCall(lhs)) {
8434 0 : if (!strictModeErrorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS))
8435 0 : return null();
8436 :
8437 0 : if (possibleError)
8438 0 : possibleError->setPendingDestructuringErrorAt(exprPos, JSMSG_BAD_DESTRUCT_TARGET);
8439 : } else {
8440 0 : errorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS);
8441 0 : return null();
8442 : }
8443 :
8444 7253 : if (!possibleErrorInner.checkForExpressionError())
8445 0 : return null();
8446 :
8447 7253 : Node rhs = assignExpr(inHandling, yieldHandling, TripledotProhibited);
8448 7253 : if (!rhs)
8449 0 : return null();
8450 :
8451 7253 : if (kind == PNK_ASSIGN)
8452 6783 : handler.checkAndSetIsDirectRHSAnonFunction(rhs);
8453 :
8454 7253 : return handler.newAssignment(kind, lhs, rhs, op);
8455 : }
8456 :
8457 : template <class ParseHandler, typename CharT>
8458 : bool
8459 2274 : Parser<ParseHandler, CharT>::isValidSimpleAssignmentTarget(Node node,
8460 : FunctionCallBehavior behavior /* = ForbidAssignmentToFunctionCalls */)
8461 : {
8462 : // Note that this method implements *only* a boolean test. Reporting an
8463 : // error for the various syntaxes that fail this, and warning for the
8464 : // various syntaxes that "pass" this but should not, occurs elsewhere.
8465 :
8466 2274 : if (handler.isNameAnyParentheses(node)) {
8467 2152 : if (!pc->sc()->strict())
8468 269 : return true;
8469 :
8470 1883 : return !handler.nameIsArgumentsEvalAnyParentheses(node, context);
8471 : }
8472 :
8473 122 : if (handler.isPropertyAccess(node))
8474 122 : return true;
8475 :
8476 0 : if (behavior == PermitAssignmentToFunctionCalls) {
8477 0 : if (handler.isFunctionCall(node))
8478 0 : return true;
8479 : }
8480 :
8481 0 : return false;
8482 : }
8483 :
8484 : template <class ParseHandler, typename CharT>
8485 : bool
8486 784 : Parser<ParseHandler, CharT>::checkIncDecOperand(Node operand, uint32_t operandOffset)
8487 : {
8488 784 : if (handler.isNameAnyParentheses(operand)) {
8489 736 : if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(operand, context)) {
8490 0 : if (!strictModeErrorAt(operandOffset, JSMSG_BAD_STRICT_ASSIGN, chars))
8491 0 : return false;
8492 : }
8493 48 : } else if (handler.isPropertyAccess(operand)) {
8494 : // Permitted: no additional testing/fixup needed.
8495 0 : } else if (handler.isFunctionCall(operand)) {
8496 : // Assignment to function calls is forbidden in ES6. We're still
8497 : // somewhat concerned about sites using this in dead code, so forbid it
8498 : // only in strict mode code (or if the werror option has been set), and
8499 : // otherwise warn.
8500 0 : if (!strictModeErrorAt(operandOffset, JSMSG_BAD_INCOP_OPERAND))
8501 0 : return false;
8502 : } else {
8503 0 : errorAt(operandOffset, JSMSG_BAD_INCOP_OPERAND);
8504 0 : return false;
8505 : }
8506 :
8507 784 : MOZ_ASSERT(isValidSimpleAssignmentTarget(operand, PermitAssignmentToFunctionCalls),
8508 : "inconsistent increment/decrement operand validation");
8509 784 : return true;
8510 : }
8511 :
8512 : template <class ParseHandler, typename CharT>
8513 : typename ParseHandler::Node
8514 3990 : Parser<ParseHandler, CharT>::unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op,
8515 : uint32_t begin)
8516 : {
8517 3990 : Node kid = unaryExpr(yieldHandling, TripledotProhibited);
8518 3990 : if (!kid)
8519 0 : return null();
8520 3990 : return handler.newUnary(kind, op, begin, kid);
8521 : }
8522 :
8523 : template <class ParseHandler, typename CharT>
8524 : typename ParseHandler::Node
8525 93630 : Parser<ParseHandler, CharT>::unaryExpr(YieldHandling yieldHandling,
8526 : TripledotHandling tripledotHandling,
8527 : PossibleError* possibleError /* = nullptr */,
8528 : InvokedPrediction invoked /* = PredictUninvoked */)
8529 : {
8530 93630 : if (!CheckRecursionLimit(context))
8531 0 : return null();
8532 :
8533 : TokenKind tt;
8534 93630 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
8535 0 : return null();
8536 93630 : uint32_t begin = pos().begin;
8537 93630 : switch (tt) {
8538 : case TOK_VOID:
8539 74 : return unaryOpExpr(yieldHandling, PNK_VOID, JSOP_VOID, begin);
8540 : case TOK_NOT:
8541 3580 : return unaryOpExpr(yieldHandling, PNK_NOT, JSOP_NOT, begin);
8542 : case TOK_BITNOT:
8543 7 : return unaryOpExpr(yieldHandling, PNK_BITNOT, JSOP_BITNOT, begin);
8544 : case TOK_ADD:
8545 13 : return unaryOpExpr(yieldHandling, PNK_POS, JSOP_POS, begin);
8546 : case TOK_SUB:
8547 316 : return unaryOpExpr(yieldHandling, PNK_NEG, JSOP_NEG, begin);
8548 :
8549 : case TOK_TYPEOF: {
8550 : // The |typeof| operator is specially parsed to distinguish its
8551 : // application to a name, from its application to a non-name
8552 : // expression:
8553 : //
8554 : // // Looks up the name, doesn't find it and so evaluates to
8555 : // // "undefined".
8556 : // assertEq(typeof nonExistentName, "undefined");
8557 : //
8558 : // // Evaluates expression, triggering a runtime ReferenceError for
8559 : // // the undefined name.
8560 : // typeof (1, nonExistentName);
8561 619 : Node kid = unaryExpr(yieldHandling, TripledotProhibited);
8562 619 : if (!kid)
8563 0 : return null();
8564 :
8565 619 : return handler.newTypeof(begin, kid);
8566 : }
8567 :
8568 : case TOK_INC:
8569 : case TOK_DEC:
8570 : {
8571 : TokenKind tt2;
8572 64 : if (!tokenStream.getToken(&tt2, TokenStream::Operand))
8573 0 : return null();
8574 :
8575 64 : uint32_t operandOffset = pos().begin;
8576 64 : Node operand = memberExpr(yieldHandling, TripledotProhibited, tt2);
8577 64 : if (!operand || !checkIncDecOperand(operand, operandOffset))
8578 0 : return null();
8579 :
8580 64 : return handler.newUpdate((tt == TOK_INC) ? PNK_PREINCREMENT : PNK_PREDECREMENT,
8581 64 : begin, operand);
8582 : }
8583 :
8584 : case TOK_DELETE: {
8585 : uint32_t exprOffset;
8586 117 : if (!tokenStream.peekOffset(&exprOffset, TokenStream::Operand))
8587 0 : return null();
8588 :
8589 117 : Node expr = unaryExpr(yieldHandling, TripledotProhibited);
8590 117 : if (!expr)
8591 0 : return null();
8592 :
8593 : // Per spec, deleting any unary expression is valid -- it simply
8594 : // returns true -- except for one case that is illegal in strict mode.
8595 117 : if (handler.isNameAnyParentheses(expr)) {
8596 0 : if (!strictModeErrorAt(exprOffset, JSMSG_DEPRECATED_DELETE_OPERAND))
8597 0 : return null();
8598 :
8599 0 : pc->sc()->setBindingsAccessedDynamically();
8600 : }
8601 :
8602 117 : return handler.newDelete(begin, expr);
8603 : }
8604 :
8605 : case TOK_AWAIT: {
8606 318 : if (pc->isAsync()) {
8607 318 : Node kid = unaryExpr(yieldHandling, tripledotHandling, possibleError, invoked);
8608 318 : if (!kid)
8609 0 : return null();
8610 318 : pc->lastAwaitOffset = begin;
8611 318 : return handler.newAwaitExpression(begin, kid);
8612 : }
8613 : }
8614 :
8615 : MOZ_FALLTHROUGH;
8616 :
8617 : default: {
8618 88522 : Node expr = memberExpr(yieldHandling, tripledotHandling, tt, /* allowCallSyntax = */ true,
8619 88522 : possibleError, invoked);
8620 88522 : if (!expr)
8621 0 : return null();
8622 :
8623 : /* Don't look across a newline boundary for a postfix incop. */
8624 88522 : if (!tokenStream.peekTokenSameLine(&tt))
8625 0 : return null();
8626 :
8627 88522 : if (tt != TOK_INC && tt != TOK_DEC)
8628 87802 : return expr;
8629 :
8630 720 : tokenStream.consumeKnownToken(tt);
8631 720 : if (!checkIncDecOperand(expr, begin))
8632 0 : return null();
8633 720 : return handler.newUpdate((tt == TOK_INC) ? PNK_POSTINCREMENT : PNK_POSTDECREMENT,
8634 720 : begin, expr);
8635 : }
8636 : }
8637 : }
8638 :
8639 :
8640 : /*** Comprehensions *******************************************************************************
8641 : *
8642 : * We currently support two flavors of comprehensions, all deprecated:
8643 : *
8644 : * [for (V of OBJ) if (COND) EXPR] // ES6-era array comprehension
8645 : * (for (V of OBJ) if (COND) EXPR) // ES6-era generator expression
8646 : *
8647 : * (These flavors are called "ES6-era" because they were in ES6 draft
8648 : * specifications for a while. Shortly after this syntax was implemented in SM,
8649 : * TC39 decided to drop it.)
8650 : */
8651 :
8652 : template <class ParseHandler, typename CharT>
8653 : typename ParseHandler::Node
8654 0 : Parser<ParseHandler, CharT>::generatorComprehensionLambda(unsigned begin)
8655 : {
8656 0 : Node genfn = handler.newFunctionExpression(pos());
8657 0 : if (!genfn)
8658 0 : return null();
8659 :
8660 0 : ParseContext* outerpc = pc;
8661 :
8662 : // If we are off thread, the generator meta-objects have
8663 : // already been created by js::StartOffThreadParseScript, so cx will not
8664 : // be necessary.
8665 0 : RootedObject proto(context);
8666 0 : JSContext* cx = context->helperThread() ? nullptr : context;
8667 0 : proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, context->global());
8668 0 : if (!proto)
8669 0 : return null();
8670 :
8671 : RootedFunction fun(context, newFunction(/* atom = */ nullptr, Expression,
8672 0 : StarGenerator, SyncFunction, proto));
8673 0 : if (!fun)
8674 0 : return null();
8675 :
8676 : // Create box for fun->object early to root it.
8677 0 : Directives directives(/* strict = */ outerpc->sc()->strict());
8678 0 : FunctionBox* genFunbox = newFunctionBox(genfn, fun, /* toStringStart = */ 0, directives,
8679 0 : StarGenerator, SyncFunction);
8680 0 : if (!genFunbox)
8681 0 : return null();
8682 0 : genFunbox->isGenexpLambda = true;
8683 0 : genFunbox->initWithEnclosingParseContext(outerpc, Expression);
8684 :
8685 0 : ParseContext genpc(this, genFunbox, /* newDirectives = */ nullptr);
8686 0 : if (!genpc.init())
8687 0 : return null();
8688 0 : genpc.functionScope().useAsVarScope(&genpc);
8689 :
8690 : /*
8691 : * We assume conservatively that any deoptimization flags in pc->sc()
8692 : * come from the kid. So we propagate these flags into genfn. For code
8693 : * simplicity we also do not detect if the flags were only set in the
8694 : * kid and could be removed from pc->sc().
8695 : */
8696 0 : genFunbox->anyCxFlags = outerpc->sc()->anyCxFlags;
8697 :
8698 0 : if (!declareDotGeneratorName())
8699 0 : return null();
8700 :
8701 0 : Node body = handler.newStatementList(TokenPos(begin, pos().end));
8702 0 : if (!body)
8703 0 : return null();
8704 :
8705 0 : Node comp = comprehension(StarGenerator);
8706 0 : if (!comp)
8707 0 : return null();
8708 :
8709 0 : MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
8710 :
8711 0 : uint32_t end = pos().end;
8712 0 : handler.setBeginPosition(comp, begin);
8713 0 : handler.setEndPosition(comp, end);
8714 0 : genFunbox->setEnd(tokenStream);
8715 0 : handler.addStatementToList(body, comp);
8716 0 : handler.setEndPosition(body, end);
8717 0 : handler.setBeginPosition(genfn, begin);
8718 0 : handler.setEndPosition(genfn, end);
8719 :
8720 0 : Node generator = newDotGeneratorName();
8721 0 : if (!generator)
8722 0 : return null();
8723 0 : if (!handler.prependInitialYield(body, generator))
8724 0 : return null();
8725 :
8726 0 : if (!propagateFreeNamesAndMarkClosedOverBindings(pc->varScope()))
8727 0 : return null();
8728 0 : if (!finishFunction())
8729 0 : return null();
8730 0 : if (!leaveInnerFunction(outerpc))
8731 0 : return null();
8732 :
8733 : // Note that if we ever start syntax-parsing generators, we will also
8734 : // need to propagate the closed-over variable set to the inner
8735 : // lazyscript.
8736 0 : if (!handler.setComprehensionLambdaBody(genfn, body))
8737 0 : return null();
8738 :
8739 0 : return genfn;
8740 : }
8741 :
8742 : template <class ParseHandler, typename CharT>
8743 : typename ParseHandler::Node
8744 0 : Parser<ParseHandler, CharT>::comprehensionFor(GeneratorKind comprehensionKind)
8745 : {
8746 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FOR));
8747 :
8748 0 : uint32_t begin = pos().begin;
8749 :
8750 0 : MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
8751 :
8752 : // FIXME: Destructuring binding (bug 980828).
8753 :
8754 0 : MUST_MATCH_TOKEN_FUNC(TokenKindIsPossibleIdentifier, JSMSG_NO_VARIABLE_NAME);
8755 0 : RootedPropertyName name(context, bindingIdentifier(YieldIsKeyword));
8756 0 : if (!name)
8757 0 : return null();
8758 0 : if (name == context->names().let) {
8759 0 : error(JSMSG_LET_COMP_BINDING);
8760 0 : return null();
8761 : }
8762 0 : TokenPos namePos = pos();
8763 0 : Node lhs = newName(name);
8764 0 : if (!lhs)
8765 0 : return null();
8766 : bool matched;
8767 0 : if (!tokenStream.matchToken(&matched, TOK_OF))
8768 0 : return null();
8769 0 : if (!matched) {
8770 0 : error(JSMSG_OF_AFTER_FOR_NAME);
8771 0 : return null();
8772 : }
8773 :
8774 0 : Node rhs = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited);
8775 0 : if (!rhs)
8776 0 : return null();
8777 :
8778 0 : MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_OF_ITERABLE);
8779 :
8780 0 : TokenPos headPos(begin, pos().end);
8781 :
8782 0 : ParseContext::Scope scope(this);
8783 0 : if (!scope.init(pc))
8784 0 : return null();
8785 :
8786 : {
8787 : // Push a temporary ForLoopLexicalHead Statement that allows for
8788 : // lexical declarations, as they are usually allowed only in braced
8789 : // statements.
8790 0 : ParseContext::Statement forHeadStmt(pc, StatementKind::ForLoopLexicalHead);
8791 0 : if (!noteDeclaredName(name, DeclarationKind::Let, namePos))
8792 0 : return null();
8793 : }
8794 :
8795 0 : Node decls = handler.newComprehensionBinding(lhs);
8796 0 : if (!decls)
8797 0 : return null();
8798 :
8799 0 : Node tail = comprehensionTail(comprehensionKind);
8800 0 : if (!tail)
8801 0 : return null();
8802 :
8803 : // Finish the lexical scope after parsing the tail.
8804 0 : Node lexicalScope = finishLexicalScope(scope, decls);
8805 0 : if (!lexicalScope)
8806 0 : return null();
8807 :
8808 0 : Node head = handler.newForInOrOfHead(PNK_FOROF, lexicalScope, rhs, headPos);
8809 0 : if (!head)
8810 0 : return null();
8811 :
8812 0 : return handler.newComprehensionFor(begin, head, tail);
8813 : }
8814 :
8815 : template <class ParseHandler, typename CharT>
8816 : typename ParseHandler::Node
8817 0 : Parser<ParseHandler, CharT>::comprehensionIf(GeneratorKind comprehensionKind)
8818 : {
8819 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_IF));
8820 :
8821 0 : uint32_t begin = pos().begin;
8822 :
8823 0 : MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND);
8824 0 : Node cond = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited);
8825 0 : if (!cond)
8826 0 : return null();
8827 0 : MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);
8828 :
8829 : /* Check for (a = b) and warn about possible (a == b) mistype. */
8830 0 : if (handler.isUnparenthesizedAssignment(cond)) {
8831 0 : if (!extraWarning(JSMSG_EQUAL_AS_ASSIGN))
8832 0 : return null();
8833 : }
8834 :
8835 0 : Node then = comprehensionTail(comprehensionKind);
8836 0 : if (!then)
8837 0 : return null();
8838 :
8839 0 : return handler.newIfStatement(begin, cond, then, null());
8840 : }
8841 :
8842 : template <class ParseHandler, typename CharT>
8843 : typename ParseHandler::Node
8844 0 : Parser<ParseHandler, CharT>::comprehensionTail(GeneratorKind comprehensionKind)
8845 : {
8846 0 : if (!CheckRecursionLimit(context))
8847 0 : return null();
8848 :
8849 : bool matched;
8850 0 : if (!tokenStream.matchToken(&matched, TOK_FOR, TokenStream::Operand))
8851 0 : return null();
8852 0 : if (matched)
8853 0 : return comprehensionFor(comprehensionKind);
8854 :
8855 0 : if (!tokenStream.matchToken(&matched, TOK_IF, TokenStream::Operand))
8856 0 : return null();
8857 0 : if (matched)
8858 0 : return comprehensionIf(comprehensionKind);
8859 :
8860 0 : uint32_t begin = pos().begin;
8861 :
8862 0 : Node bodyExpr = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited);
8863 0 : if (!bodyExpr)
8864 0 : return null();
8865 :
8866 0 : if (comprehensionKind == NotGenerator)
8867 0 : return handler.newArrayPush(begin, bodyExpr);
8868 :
8869 0 : MOZ_ASSERT(comprehensionKind == StarGenerator);
8870 0 : Node yieldExpr = handler.newYieldExpression(begin, bodyExpr);
8871 0 : if (!yieldExpr)
8872 0 : return null();
8873 0 : yieldExpr = handler.parenthesize(yieldExpr);
8874 :
8875 0 : return handler.newExprStatement(yieldExpr, pos().end);
8876 : }
8877 :
8878 : // Parse an ES6-era generator or array comprehension, starting at the first
8879 : // `for`. The caller is responsible for matching the ending TOK_RP or TOK_RB.
8880 : template <class ParseHandler, typename CharT>
8881 : typename ParseHandler::Node
8882 0 : Parser<ParseHandler, CharT>::comprehension(GeneratorKind comprehensionKind)
8883 : {
8884 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FOR));
8885 :
8886 0 : uint32_t startYieldOffset = pc->lastYieldOffset;
8887 :
8888 0 : Node body = comprehensionFor(comprehensionKind);
8889 0 : if (!body)
8890 0 : return null();
8891 :
8892 0 : if (comprehensionKind != NotGenerator && pc->lastYieldOffset != startYieldOffset) {
8893 0 : errorAt(pc->lastYieldOffset, JSMSG_BAD_GENEXP_BODY, js_yield_str);
8894 0 : return null();
8895 : }
8896 :
8897 0 : return body;
8898 : }
8899 :
8900 : template <class ParseHandler, typename CharT>
8901 : typename ParseHandler::Node
8902 0 : Parser<ParseHandler, CharT>::arrayComprehension(uint32_t begin)
8903 : {
8904 0 : Node inner = comprehension(NotGenerator);
8905 0 : if (!inner)
8906 0 : return null();
8907 :
8908 0 : MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_ARRAY_COMPREHENSION);
8909 :
8910 0 : Node comp = handler.newList(PNK_ARRAYCOMP, inner);
8911 0 : if (!comp)
8912 0 : return null();
8913 :
8914 0 : handler.setBeginPosition(comp, begin);
8915 0 : handler.setEndPosition(comp, pos().end);
8916 :
8917 0 : return comp;
8918 : }
8919 :
8920 : template <class ParseHandler, typename CharT>
8921 : typename ParseHandler::Node
8922 0 : Parser<ParseHandler, CharT>::generatorComprehension(uint32_t begin)
8923 : {
8924 0 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FOR));
8925 :
8926 : // We have no problem parsing generator comprehensions inside lazy
8927 : // functions, but the bytecode emitter currently can't handle them that way,
8928 : // because when it goes to emit the code for the inner generator function,
8929 : // it expects outer functions to have non-lazy scripts.
8930 0 : if (!abortIfSyntaxParser())
8931 0 : return null();
8932 :
8933 0 : Node genfn = generatorComprehensionLambda(begin);
8934 0 : if (!genfn)
8935 0 : return null();
8936 :
8937 0 : Node result = handler.newList(PNK_GENEXP, genfn, JSOP_CALL);
8938 0 : if (!result)
8939 0 : return null();
8940 0 : handler.setBeginPosition(result, begin);
8941 0 : handler.setEndPosition(result, pos().end);
8942 :
8943 0 : return result;
8944 : }
8945 :
8946 : template <class ParseHandler, typename CharT>
8947 : typename ParseHandler::Node
8948 307 : Parser<ParseHandler, CharT>::assignExprWithoutYieldOrAwait(YieldHandling yieldHandling)
8949 : {
8950 307 : uint32_t startYieldOffset = pc->lastYieldOffset;
8951 307 : uint32_t startAwaitOffset = pc->lastAwaitOffset;
8952 307 : Node res = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
8953 307 : if (res) {
8954 307 : if (pc->lastYieldOffset != startYieldOffset) {
8955 0 : errorAt(pc->lastYieldOffset, JSMSG_YIELD_IN_DEFAULT);
8956 0 : return null();
8957 : }
8958 307 : if (pc->lastAwaitOffset != startAwaitOffset) {
8959 0 : errorAt(pc->lastAwaitOffset, JSMSG_AWAIT_IN_DEFAULT);
8960 0 : return null();
8961 : }
8962 : }
8963 307 : return res;
8964 : }
8965 :
8966 : template <class ParseHandler, typename CharT>
8967 : bool
8968 27970 : Parser<ParseHandler, CharT>::argumentList(YieldHandling yieldHandling, Node listNode,
8969 : bool* isSpread,
8970 : PossibleError* possibleError /* = nullptr */)
8971 : {
8972 : bool matched;
8973 27970 : if (!tokenStream.matchToken(&matched, TOK_RP, TokenStream::Operand))
8974 0 : return false;
8975 27970 : if (matched) {
8976 3267 : handler.setEndPosition(listNode, pos().end);
8977 3267 : return true;
8978 : }
8979 :
8980 19672 : while (true) {
8981 44375 : bool spread = false;
8982 44375 : uint32_t begin = 0;
8983 44375 : if (!tokenStream.matchToken(&matched, TOK_TRIPLEDOT, TokenStream::Operand))
8984 0 : return false;
8985 44375 : if (matched) {
8986 58 : spread = true;
8987 58 : begin = pos().begin;
8988 58 : *isSpread = true;
8989 : }
8990 :
8991 44375 : Node argNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited, possibleError);
8992 44375 : if (!argNode)
8993 0 : return false;
8994 44375 : if (spread) {
8995 58 : argNode = handler.newSpread(begin, argNode);
8996 58 : if (!argNode)
8997 0 : return false;
8998 : }
8999 :
9000 44375 : handler.addList(listNode, argNode);
9001 :
9002 : bool matched;
9003 44375 : if (!tokenStream.matchToken(&matched, TOK_COMMA))
9004 0 : return false;
9005 44375 : if (!matched)
9006 49406 : break;
9007 :
9008 : TokenKind tt;
9009 19672 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
9010 0 : return null();
9011 19672 : if (tt == TOK_RP) {
9012 0 : tokenStream.addModifierException(TokenStream::NoneIsOperand);
9013 0 : break;
9014 : }
9015 : }
9016 :
9017 24703 : MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_ARGS);
9018 :
9019 24703 : handler.setEndPosition(listNode, pos().end);
9020 24703 : return true;
9021 : }
9022 :
9023 : template <class ParseHandler, typename CharT>
9024 : bool
9025 15 : Parser<ParseHandler, CharT>::checkAndMarkSuperScope()
9026 : {
9027 15 : if (!pc->sc()->allowSuperProperty())
9028 2 : return false;
9029 13 : pc->setSuperScopeNeedsHomeObject();
9030 13 : return true;
9031 : }
9032 :
9033 : template <class ParseHandler, typename CharT>
9034 : typename ParseHandler::Node
9035 89934 : Parser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
9036 : TripledotHandling tripledotHandling,
9037 : TokenKind tt, bool allowCallSyntax /* = true */,
9038 : PossibleError* possibleError /* = nullptr */,
9039 : InvokedPrediction invoked /* = PredictUninvoked */)
9040 : {
9041 89934 : MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
9042 :
9043 : Node lhs;
9044 :
9045 89934 : if (!CheckRecursionLimit(context))
9046 0 : return null();
9047 :
9048 : /* Check for new expression first. */
9049 89934 : if (tt == TOK_NEW) {
9050 1344 : uint32_t newBegin = pos().begin;
9051 : // Make sure this wasn't a |new.target| in disguise.
9052 : Node newTarget;
9053 1344 : if (!tryNewTarget(newTarget))
9054 0 : return null();
9055 1344 : if (newTarget) {
9056 12 : lhs = newTarget;
9057 : } else {
9058 : // Gotten by tryNewTarget
9059 1332 : tt = tokenStream.currentToken().type;
9060 1332 : Node ctorExpr = memberExpr(yieldHandling, TripledotProhibited, tt,
9061 : /* allowCallSyntax = */ false,
9062 1332 : /* possibleError = */ nullptr, PredictInvoked);
9063 1332 : if (!ctorExpr)
9064 0 : return null();
9065 :
9066 1332 : lhs = handler.newNewExpression(newBegin, ctorExpr);
9067 1332 : if (!lhs)
9068 0 : return null();
9069 :
9070 : bool matched;
9071 1332 : if (!tokenStream.matchToken(&matched, TOK_LP))
9072 0 : return null();
9073 1332 : if (matched) {
9074 1329 : bool isSpread = false;
9075 1329 : if (!argumentList(yieldHandling, lhs, &isSpread))
9076 0 : return null();
9077 1329 : if (isSpread)
9078 0 : handler.setOp(lhs, JSOP_SPREADNEW);
9079 : }
9080 : }
9081 88590 : } else if (tt == TOK_SUPER) {
9082 30 : Node thisName = newThisName();
9083 30 : if (!thisName)
9084 0 : return null();
9085 30 : lhs = handler.newSuperBase(thisName, pos());
9086 30 : if (!lhs)
9087 0 : return null();
9088 : } else {
9089 88560 : lhs = primaryExpr(yieldHandling, tripledotHandling, tt, possibleError, invoked);
9090 88560 : if (!lhs)
9091 0 : return null();
9092 : }
9093 :
9094 89934 : MOZ_ASSERT_IF(handler.isSuperBase(lhs), tokenStream.isCurrentTokenType(TOK_SUPER));
9095 :
9096 70490 : while (true) {
9097 160424 : if (!tokenStream.getToken(&tt))
9098 0 : return null();
9099 160424 : if (tt == TOK_EOF)
9100 220 : break;
9101 :
9102 : Node nextMember;
9103 160204 : if (tt == TOK_DOT) {
9104 40291 : if (!tokenStream.getToken(&tt))
9105 0 : return null();
9106 40291 : if (TokenKindIsPossibleIdentifierName(tt)) {
9107 40291 : PropertyName* field = tokenStream.currentName();
9108 40291 : if (handler.isSuperBase(lhs) && !checkAndMarkSuperScope()) {
9109 0 : error(JSMSG_BAD_SUPERPROP, "property");
9110 0 : return null();
9111 : }
9112 40291 : nextMember = handler.newPropertyAccess(lhs, field, pos().end);
9113 40291 : if (!nextMember)
9114 0 : return null();
9115 : } else {
9116 0 : error(JSMSG_NAME_AFTER_DOT);
9117 0 : return null();
9118 : }
9119 119913 : } else if (tt == TOK_LB) {
9120 3557 : Node propExpr = expr(InAllowed, yieldHandling, TripledotProhibited);
9121 3557 : if (!propExpr)
9122 0 : return null();
9123 :
9124 3557 : MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
9125 :
9126 3557 : if (handler.isSuperBase(lhs) && !checkAndMarkSuperScope()) {
9127 0 : error(JSMSG_BAD_SUPERPROP, "member");
9128 0 : return null();
9129 : }
9130 3557 : nextMember = handler.newPropertyByValue(lhs, propExpr, pos().end);
9131 3557 : if (!nextMember)
9132 0 : return null();
9133 206071 : } else if ((allowCallSyntax && tt == TOK_LP) ||
9134 179429 : tt == TOK_TEMPLATE_HEAD ||
9135 89714 : tt == TOK_NO_SUBS_TEMPLATE)
9136 : {
9137 26642 : if (handler.isSuperBase(lhs)) {
9138 17 : if (!pc->sc()->allowSuperCall()) {
9139 0 : error(JSMSG_BAD_SUPERCALL);
9140 0 : return null();
9141 : }
9142 :
9143 17 : if (tt != TOK_LP) {
9144 0 : error(JSMSG_BAD_SUPER);
9145 0 : return null();
9146 : }
9147 :
9148 17 : nextMember = handler.newList(PNK_SUPERCALL, lhs, JSOP_SUPERCALL);
9149 17 : if (!nextMember)
9150 0 : return null();
9151 :
9152 : // Despite the fact that it's impossible to have |super()| in a
9153 : // generator, we still inherit the yieldHandling of the
9154 : // memberExpression, per spec. Curious.
9155 17 : bool isSpread = false;
9156 17 : if (!argumentList(yieldHandling, nextMember, &isSpread))
9157 0 : return null();
9158 :
9159 17 : if (isSpread)
9160 3 : handler.setOp(nextMember, JSOP_SPREADSUPERCALL);
9161 :
9162 17 : Node thisName = newThisName();
9163 17 : if (!thisName)
9164 0 : return null();
9165 :
9166 17 : nextMember = handler.newSetThis(thisName, nextMember);
9167 17 : if (!nextMember)
9168 0 : return null();
9169 : } else {
9170 26625 : if (options().selfHostingMode && handler.isPropertyAccess(lhs)) {
9171 0 : error(JSMSG_SELFHOSTED_METHOD_CALL);
9172 0 : return null();
9173 : }
9174 :
9175 26625 : TokenPos nextMemberPos = pos();
9176 53250 : nextMember = tt == TOK_LP
9177 26625 : ? handler.newCall(nextMemberPos)
9178 : : handler.newTaggedTemplate(nextMemberPos);
9179 26625 : if (!nextMember)
9180 0 : return null();
9181 :
9182 26625 : JSOp op = JSOP_CALL;
9183 26625 : bool maybeAsyncArrow = false;
9184 26625 : if (PropertyName* prop = handler.maybeDottedProperty(lhs)) {
9185 : // Use the JSOP_FUN{APPLY,CALL} optimizations given the
9186 : // right syntax.
9187 15636 : if (prop == context->names().apply) {
9188 52 : op = JSOP_FUNAPPLY;
9189 52 : if (pc->isFunctionBox())
9190 52 : pc->functionBox()->usesApply = true;
9191 15584 : } else if (prop == context->names().call) {
9192 83 : op = JSOP_FUNCALL;
9193 : }
9194 10989 : } else if (tt == TOK_LP) {
9195 10988 : if (handler.isAsyncKeyword(lhs, context)) {
9196 : // |async (| can be the start of an async arrow
9197 : // function, so we need to defer reporting possible
9198 : // errors from destructuring syntax. To give better
9199 : // error messages, we only allow the AsyncArrowHead
9200 : // part of the CoverCallExpressionAndAsyncArrowHead
9201 : // syntax when the initial name is "async".
9202 40 : maybeAsyncArrow = true;
9203 10948 : } else if (handler.isEvalAnyParentheses(lhs, context)) {
9204 : // Select the right EVAL op and flag pc as having a
9205 : // direct eval.
9206 2 : op = pc->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
9207 2 : pc->sc()->setBindingsAccessedDynamically();
9208 2 : pc->sc()->setHasDirectEval();
9209 :
9210 : // In non-strict mode code, direct calls to eval can
9211 : // add variables to the call object.
9212 2 : if (pc->isFunctionBox() && !pc->sc()->strict())
9213 2 : pc->functionBox()->setHasExtensibleScope();
9214 :
9215 : // If we're in a method, mark the method as requiring
9216 : // support for 'super', since direct eval code can use
9217 : // it. (If we're not in a method, that's fine, so
9218 : // ignore the return value.)
9219 2 : checkAndMarkSuperScope();
9220 : }
9221 : }
9222 :
9223 26625 : handler.setBeginPosition(nextMember, lhs);
9224 26625 : handler.addList(nextMember, lhs);
9225 :
9226 26625 : if (tt == TOK_LP) {
9227 26624 : bool isSpread = false;
9228 26624 : PossibleError* asyncPossibleError = maybeAsyncArrow ? possibleError : nullptr;
9229 26624 : if (!argumentList(yieldHandling, nextMember, &isSpread, asyncPossibleError))
9230 0 : return null();
9231 26624 : if (isSpread) {
9232 55 : if (op == JSOP_EVAL)
9233 0 : op = JSOP_SPREADEVAL;
9234 55 : else if (op == JSOP_STRICTEVAL)
9235 0 : op = JSOP_STRICTSPREADEVAL;
9236 : else
9237 55 : op = JSOP_SPREADCALL;
9238 : }
9239 : } else {
9240 1 : if (!taggedTemplate(yieldHandling, nextMember, tt))
9241 0 : return null();
9242 : }
9243 26625 : handler.setOp(nextMember, op);
9244 26642 : }
9245 : } else {
9246 89714 : tokenStream.ungetToken();
9247 89714 : if (handler.isSuperBase(lhs))
9248 0 : break;
9249 89714 : return lhs;
9250 : }
9251 :
9252 70490 : lhs = nextMember;
9253 : }
9254 :
9255 220 : if (handler.isSuperBase(lhs)) {
9256 0 : error(JSMSG_BAD_SUPER);
9257 0 : return null();
9258 : }
9259 :
9260 220 : return lhs;
9261 : }
9262 :
9263 : template <class ParseHandler, typename CharT>
9264 : typename ParseHandler::Node
9265 114007 : Parser<ParseHandler, CharT>::newName(PropertyName* name)
9266 : {
9267 114007 : return newName(name, pos());
9268 : }
9269 :
9270 : template <class ParseHandler, typename CharT>
9271 : typename ParseHandler::Node
9272 114059 : Parser<ParseHandler, CharT>::newName(PropertyName* name, TokenPos pos)
9273 : {
9274 114059 : return handler.newName(name, pos, context);
9275 : }
9276 :
9277 : template <class ParseHandler, typename CharT>
9278 : bool
9279 106016 : Parser<ParseHandler, CharT>::checkLabelOrIdentifierReference(PropertyName* ident,
9280 : uint32_t offset,
9281 : YieldHandling yieldHandling,
9282 : TokenKind hint /* = TOK_LIMIT */)
9283 : {
9284 : TokenKind tt;
9285 106016 : if (hint == TOK_LIMIT) {
9286 0 : tt = ReservedWordTokenKind(ident);
9287 : } else {
9288 106016 : MOZ_ASSERT(hint == ReservedWordTokenKind(ident), "hint doesn't match actual token kind");
9289 106016 : tt = hint;
9290 : }
9291 :
9292 106016 : if (tt == TOK_NAME)
9293 105360 : return true;
9294 656 : if (TokenKindIsContextualKeyword(tt)) {
9295 656 : if (tt == TOK_YIELD) {
9296 0 : if (yieldHandling == YieldIsKeyword || versionNumber() >= JSVERSION_1_7) {
9297 0 : errorAt(offset, JSMSG_RESERVED_ID, "yield");
9298 0 : return false;
9299 : }
9300 0 : if (pc->sc()->needStrictChecks()) {
9301 0 : if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "yield"))
9302 0 : return false;
9303 : }
9304 0 : return true;
9305 : }
9306 656 : if (tt == TOK_AWAIT) {
9307 0 : if (awaitIsKeyword()) {
9308 0 : errorAt(offset, JSMSG_RESERVED_ID, "await");
9309 0 : return false;
9310 : }
9311 0 : return true;
9312 : }
9313 656 : if (pc->sc()->needStrictChecks()) {
9314 586 : if (tt == TOK_LET) {
9315 0 : if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "let"))
9316 0 : return false;
9317 0 : return true;
9318 : }
9319 586 : if (tt == TOK_STATIC) {
9320 0 : if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "static"))
9321 0 : return false;
9322 0 : return true;
9323 : }
9324 : }
9325 656 : return true;
9326 : }
9327 0 : if (TokenKindIsStrictReservedWord(tt)) {
9328 0 : if (pc->sc()->needStrictChecks()) {
9329 0 : if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(tt)))
9330 0 : return false;
9331 : }
9332 0 : return true;
9333 : }
9334 0 : if (TokenKindIsKeyword(tt) || TokenKindIsReservedWordLiteral(tt)) {
9335 0 : errorAt(offset, JSMSG_INVALID_ID, ReservedWordToCharZ(tt));
9336 0 : return false;
9337 : }
9338 0 : if (TokenKindIsFutureReservedWord(tt)) {
9339 0 : errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(tt));
9340 0 : return false;
9341 : }
9342 0 : MOZ_ASSERT_UNREACHABLE("Unexpected reserved word kind.");
9343 : return false;
9344 : }
9345 :
9346 : template <class ParseHandler, typename CharT>
9347 : bool
9348 23943 : Parser<ParseHandler, CharT>::checkBindingIdentifier(PropertyName* ident,
9349 : uint32_t offset,
9350 : YieldHandling yieldHandling,
9351 : TokenKind hint /* = TOK_LIMIT */)
9352 : {
9353 23943 : if (pc->sc()->needStrictChecks()) {
9354 19661 : if (ident == context->names().arguments) {
9355 0 : if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "arguments"))
9356 0 : return false;
9357 0 : return true;
9358 : }
9359 :
9360 19661 : if (ident == context->names().eval) {
9361 0 : if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "eval"))
9362 0 : return false;
9363 0 : return true;
9364 : }
9365 : }
9366 :
9367 23943 : return checkLabelOrIdentifierReference(ident, offset, yieldHandling, hint);
9368 : }
9369 :
9370 : template <class ParseHandler, typename CharT>
9371 : PropertyName*
9372 82073 : Parser<ParseHandler, CharT>::labelOrIdentifierReference(YieldHandling yieldHandling)
9373 : {
9374 : // ES 2017 draft 12.1.1.
9375 : // StringValue of IdentifierName normalizes any Unicode escape sequences
9376 : // in IdentifierName hence such escapes cannot be used to write an
9377 : // Identifier whose code point sequence is the same as a ReservedWord.
9378 : //
9379 : // Use PropertyName* instead of TokenKind to reflect the normalization.
9380 :
9381 : // Unless the name contains escapes, we can reuse the current TokenKind
9382 : // to determine if the name is a restricted identifier.
9383 82073 : TokenKind hint = !tokenStream.currentNameHasEscapes()
9384 82073 : ? tokenStream.currentToken().type
9385 164146 : : TOK_LIMIT;
9386 164146 : RootedPropertyName ident(context, tokenStream.currentName());
9387 82073 : if (!checkLabelOrIdentifierReference(ident, pos().begin, yieldHandling, hint))
9388 0 : return nullptr;
9389 82073 : return ident;
9390 : }
9391 :
9392 : template <class ParseHandler, typename CharT>
9393 : PropertyName*
9394 23943 : Parser<ParseHandler, CharT>::bindingIdentifier(YieldHandling yieldHandling)
9395 : {
9396 23943 : TokenKind hint = !tokenStream.currentNameHasEscapes()
9397 23943 : ? tokenStream.currentToken().type
9398 47886 : : TOK_LIMIT;
9399 47886 : RootedPropertyName ident(context, tokenStream.currentName());
9400 23943 : if (!checkBindingIdentifier(ident, pos().begin, yieldHandling, hint))
9401 0 : return nullptr;
9402 23943 : return ident;
9403 : }
9404 :
9405 : template <class ParseHandler, typename CharT>
9406 : typename ParseHandler::Node
9407 82073 : Parser<ParseHandler, CharT>::identifierReference(Handle<PropertyName*> name)
9408 : {
9409 82073 : Node pn = newName(name);
9410 82073 : if (!pn)
9411 0 : return null();
9412 :
9413 82073 : if (!noteUsedName(name))
9414 0 : return null();
9415 :
9416 82073 : return pn;
9417 : }
9418 :
9419 : template <class ParseHandler, typename CharT>
9420 : typename ParseHandler::Node
9421 20852 : Parser<ParseHandler, CharT>::stringLiteral()
9422 : {
9423 20852 : return handler.newStringLiteral(tokenStream.currentToken().atom(), pos());
9424 : }
9425 :
9426 : template <class ParseHandler, typename CharT>
9427 : typename ParseHandler::Node
9428 3 : Parser<ParseHandler, CharT>::noSubstitutionTaggedTemplate()
9429 : {
9430 3 : if (tokenStream.hasInvalidTemplateEscape()) {
9431 0 : tokenStream.clearInvalidTemplateEscape();
9432 0 : return handler.newRawUndefinedLiteral(pos());
9433 : }
9434 :
9435 3 : return handler.newTemplateStringLiteral(tokenStream.currentToken().atom(), pos());
9436 : }
9437 :
9438 : template <class ParseHandler, typename CharT>
9439 : typename ParseHandler::Node
9440 973 : Parser<ParseHandler, CharT>::noSubstitutionUntaggedTemplate()
9441 : {
9442 973 : if (!tokenStream.checkForInvalidTemplateEscapeError())
9443 0 : return null();
9444 :
9445 973 : return handler.newTemplateStringLiteral(tokenStream.currentToken().atom(), pos());
9446 : }
9447 :
9448 : template <>
9449 : ParseNode*
9450 169 : Parser<FullParseHandler, char16_t>::newRegExp()
9451 : {
9452 169 : MOZ_ASSERT(!options().selfHostingMode);
9453 :
9454 : // Create the regexp and check its syntax.
9455 169 : const char16_t* chars = tokenStream.getTokenbuf().begin();
9456 169 : size_t length = tokenStream.getTokenbuf().length();
9457 169 : RegExpFlag flags = tokenStream.currentToken().regExpFlags();
9458 :
9459 338 : Rooted<RegExpObject*> reobj(context);
9460 338 : reobj = RegExpObject::create(context, chars, length, flags, nullptr, &tokenStream, alloc,
9461 169 : TenuredObject);
9462 169 : if (!reobj)
9463 0 : return null();
9464 :
9465 169 : return handler.newRegExp(reobj, pos(), *this);
9466 : }
9467 :
9468 : template <>
9469 : SyntaxParseHandler::Node
9470 41 : Parser<SyntaxParseHandler, char16_t>::newRegExp()
9471 : {
9472 41 : MOZ_ASSERT(!options().selfHostingMode);
9473 :
9474 : // Only check the regexp's syntax, but don't create a regexp object.
9475 41 : const char16_t* chars = tokenStream.getTokenbuf().begin();
9476 41 : size_t length = tokenStream.getTokenbuf().length();
9477 41 : RegExpFlag flags = tokenStream.currentToken().regExpFlags();
9478 :
9479 41 : mozilla::Range<const char16_t> source(chars, length);
9480 41 : if (!js::irregexp::ParsePatternSyntax(tokenStream, alloc, source, flags & UnicodeFlag))
9481 0 : return null();
9482 :
9483 41 : return handler.newRegExp(SyntaxParseHandler::NodeGeneric, pos(), *this);
9484 : }
9485 :
9486 : template <class ParseHandler, typename CharT>
9487 : void
9488 10906 : Parser<ParseHandler, CharT>::checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos,
9489 : PossibleError* possibleError)
9490 : {
9491 : // Return early if a pending destructuring error is already present.
9492 10906 : if (possibleError->hasPendingDestructuringError())
9493 6395 : return;
9494 :
9495 4511 : if (pc->sc()->needStrictChecks()) {
9496 3502 : if (handler.isArgumentsAnyParentheses(expr, context)) {
9497 0 : if (pc->sc()->strict()) {
9498 0 : possibleError->setPendingDestructuringErrorAt(exprPos,
9499 : JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS);
9500 : } else {
9501 0 : possibleError->setPendingDestructuringWarningAt(exprPos,
9502 : JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS);
9503 : }
9504 0 : return;
9505 : }
9506 :
9507 3502 : if (handler.isEvalAnyParentheses(expr, context)) {
9508 0 : if (pc->sc()->strict()) {
9509 0 : possibleError->setPendingDestructuringErrorAt(exprPos,
9510 : JSMSG_BAD_STRICT_ASSIGN_EVAL);
9511 : } else {
9512 0 : possibleError->setPendingDestructuringWarningAt(exprPos,
9513 : JSMSG_BAD_STRICT_ASSIGN_EVAL);
9514 : }
9515 0 : return;
9516 : }
9517 : }
9518 :
9519 : // The expression must be either a simple assignment target, i.e. a name
9520 : // or a property accessor, or a nested destructuring pattern.
9521 13405 : if (!handler.isUnparenthesizedDestructuringPattern(expr) &&
9522 7619 : !handler.isNameAnyParentheses(expr) &&
9523 3108 : !handler.isPropertyAccess(expr))
9524 : {
9525 : // Parentheses are forbidden around destructuring *patterns* (but
9526 : // allowed around names). Use our nicer error message for
9527 : // parenthesized, nested patterns.
9528 2336 : if (handler.isParenthesizedDestructuringPattern(expr))
9529 0 : possibleError->setPendingDestructuringErrorAt(exprPos, JSMSG_BAD_DESTRUCT_PARENS);
9530 : else
9531 2336 : possibleError->setPendingDestructuringErrorAt(exprPos, JSMSG_BAD_DESTRUCT_TARGET);
9532 : }
9533 : }
9534 :
9535 : template <class ParseHandler, typename CharT>
9536 : void
9537 10224 : Parser<ParseHandler, CharT>::checkDestructuringAssignmentElement(Node expr, TokenPos exprPos,
9538 : PossibleError* possibleError)
9539 : {
9540 : // ES2018 draft rev 0719f44aab93215ed9a626b2f45bd34f36916834
9541 : // 12.15.5 Destructuring Assignment
9542 : //
9543 : // AssignmentElement[Yield, Await]:
9544 : // DestructuringAssignmentTarget[?Yield, ?Await]
9545 : // DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]
9546 :
9547 : // If |expr| is an assignment element with an initializer expression, its
9548 : // destructuring assignment target was already validated in assignExpr().
9549 : // Otherwise we need to check that |expr| is a valid destructuring target.
9550 10224 : if (!handler.isUnparenthesizedAssignment(expr))
9551 10221 : checkDestructuringAssignmentTarget(expr, exprPos, possibleError);
9552 10224 : }
9553 :
9554 : template <class ParseHandler, typename CharT>
9555 : typename ParseHandler::Node
9556 1400 : Parser<ParseHandler, CharT>::arrayInitializer(YieldHandling yieldHandling,
9557 : PossibleError* possibleError)
9558 : {
9559 1400 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB));
9560 :
9561 1400 : uint32_t begin = pos().begin;
9562 1400 : Node literal = handler.newArrayLiteral(begin);
9563 1400 : if (!literal)
9564 0 : return null();
9565 :
9566 : TokenKind tt;
9567 1400 : if (!tokenStream.getToken(&tt, TokenStream::Operand))
9568 0 : return null();
9569 :
9570 : // Handle an ES6-era array comprehension first.
9571 1400 : if (tt == TOK_FOR)
9572 0 : return arrayComprehension(begin);
9573 :
9574 1400 : if (tt == TOK_RB) {
9575 : /*
9576 : * Mark empty arrays as non-constant, since we cannot easily
9577 : * determine their type.
9578 : */
9579 356 : handler.setListFlag(literal, PNX_NONCONST);
9580 : } else {
9581 1044 : tokenStream.ungetToken();
9582 :
9583 1044 : uint32_t index = 0;
9584 1044 : TokenStream::Modifier modifier = TokenStream::Operand;
9585 2171 : for (; ; index++) {
9586 3215 : if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) {
9587 0 : error(JSMSG_ARRAY_INIT_TOO_BIG);
9588 0 : return null();
9589 : }
9590 :
9591 : TokenKind tt;
9592 3215 : if (!tokenStream.peekToken(&tt, TokenStream::Operand))
9593 0 : return null();
9594 3215 : if (tt == TOK_RB)
9595 1098 : break;
9596 :
9597 3161 : if (tt == TOK_COMMA) {
9598 2 : tokenStream.consumeKnownToken(TOK_COMMA, TokenStream::Operand);
9599 2 : if (!handler.addElision(literal, pos()))
9600 0 : return null();
9601 3159 : } else if (tt == TOK_TRIPLEDOT) {
9602 17 : tokenStream.consumeKnownToken(TOK_TRIPLEDOT, TokenStream::Operand);
9603 17 : uint32_t begin = pos().begin;
9604 :
9605 17 : TokenPos innerPos;
9606 17 : if (!tokenStream.peekTokenPos(&innerPos, TokenStream::Operand))
9607 0 : return null();
9608 :
9609 : Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
9610 17 : possibleError);
9611 17 : if (!inner)
9612 0 : return null();
9613 17 : if (possibleError)
9614 17 : checkDestructuringAssignmentTarget(inner, innerPos, possibleError);
9615 17 : if (!handler.addSpreadElement(literal, begin, inner))
9616 0 : return null();
9617 : } else {
9618 3142 : TokenPos elementPos;
9619 3142 : if (!tokenStream.peekTokenPos(&elementPos, TokenStream::Operand))
9620 0 : return null();
9621 :
9622 3142 : Node element = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
9623 3142 : possibleError);
9624 3142 : if (!element)
9625 0 : return null();
9626 3142 : if (possibleError)
9627 3128 : checkDestructuringAssignmentElement(element, elementPos, possibleError);
9628 3142 : if (foldConstants && !FoldConstants(context, &element, this))
9629 0 : return null();
9630 3142 : handler.addArrayElement(literal, element);
9631 : }
9632 :
9633 3161 : if (tt != TOK_COMMA) {
9634 : /* If we didn't already match TOK_COMMA in above case. */
9635 : bool matched;
9636 3159 : if (!tokenStream.matchToken(&matched, TOK_COMMA))
9637 0 : return null();
9638 3159 : if (!matched) {
9639 990 : modifier = TokenStream::None;
9640 990 : break;
9641 : }
9642 2169 : if (tt == TOK_TRIPLEDOT && possibleError)
9643 2 : possibleError->setPendingDestructuringErrorAt(pos(), JSMSG_REST_WITH_COMMA);
9644 : }
9645 : }
9646 :
9647 1044 : MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RB, modifier,
9648 : reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
9649 : JSMSG_BRACKET_OPENED, begin));
9650 : }
9651 1400 : handler.setEndPosition(literal, pos().end);
9652 1400 : return literal;
9653 : }
9654 :
9655 : static JSAtom*
9656 25 : DoubleToAtom(JSContext* cx, double value)
9657 : {
9658 : // This is safe because doubles can not be moved.
9659 25 : Value tmp = DoubleValue(value);
9660 25 : return ToAtom<CanGC>(cx, HandleValue::fromMarkedLocation(&tmp));
9661 : }
9662 :
9663 : template <class ParseHandler, typename CharT>
9664 : typename ParseHandler::Node
9665 10437 : Parser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
9666 : const Maybe<DeclarationKind>& maybeDecl, Node propList,
9667 : PropertyType* propType, MutableHandleAtom propAtom)
9668 : {
9669 : TokenKind ltok;
9670 10437 : if (!tokenStream.getToken(<ok))
9671 0 : return null();
9672 :
9673 10437 : MOZ_ASSERT(ltok != TOK_RC, "caller should have handled TOK_RC");
9674 :
9675 10437 : bool isGenerator = false;
9676 10437 : bool isAsync = false;
9677 :
9678 10437 : if (ltok == TOK_ASYNC) {
9679 : // AsyncMethod[Yield, Await]:
9680 : // async [no LineTerminator here] PropertyName[?Yield, ?Await] ...
9681 : //
9682 : // AsyncGeneratorMethod[Yield, Await]:
9683 : // async [no LineTerminator here] * PropertyName[?Yield, ?Await] ...
9684 : //
9685 : // PropertyName:
9686 : // LiteralPropertyName
9687 : // ComputedPropertyName[?Yield, ?Await]
9688 : //
9689 : // LiteralPropertyName:
9690 : // IdentifierName
9691 : // StringLiteral
9692 : // NumericLiteral
9693 : //
9694 : // ComputedPropertyName[Yield, Await]:
9695 : // [ ...
9696 74 : TokenKind tt = TOK_EOF;
9697 74 : if (!tokenStream.peekTokenSameLine(&tt))
9698 0 : return null();
9699 296 : if (tt == TOK_STRING || tt == TOK_NUMBER || tt == TOK_LB ||
9700 148 : TokenKindIsPossibleIdentifierName(tt) || tt == TOK_MUL)
9701 : {
9702 74 : isAsync = true;
9703 74 : tokenStream.consumeKnownToken(tt);
9704 74 : ltok = tt;
9705 : }
9706 : }
9707 :
9708 10437 : if (ltok == TOK_MUL) {
9709 6 : if (!asyncIterationSupported()) {
9710 6 : if (isAsync) {
9711 0 : error(JSMSG_ASYNC_GENERATOR);
9712 0 : return null();
9713 : }
9714 : }
9715 6 : isGenerator = true;
9716 6 : if (!tokenStream.getToken(<ok))
9717 0 : return null();
9718 : }
9719 :
9720 10437 : propAtom.set(nullptr);
9721 : Node propName;
9722 10437 : switch (ltok) {
9723 : case TOK_NUMBER:
9724 25 : propAtom.set(DoubleToAtom(context, tokenStream.currentToken().number()));
9725 25 : if (!propAtom.get())
9726 0 : return null();
9727 25 : propName = newNumber(tokenStream.currentToken());
9728 25 : if (!propName)
9729 0 : return null();
9730 25 : break;
9731 :
9732 : case TOK_STRING: {
9733 1390 : propAtom.set(tokenStream.currentToken().atom());
9734 : uint32_t index;
9735 1390 : if (propAtom->isIndex(&index)) {
9736 1 : propName = handler.newNumber(index, NoDecimal, pos());
9737 1 : if (!propName)
9738 0 : return null();
9739 1391 : break;
9740 : }
9741 1389 : propName = stringLiteral();
9742 1389 : if (!propName)
9743 0 : return null();
9744 1389 : break;
9745 : }
9746 :
9747 : case TOK_LB:
9748 5 : propName = computedPropertyName(yieldHandling, maybeDecl, propList);
9749 5 : if (!propName)
9750 0 : return null();
9751 5 : break;
9752 :
9753 : default: {
9754 9017 : if (!TokenKindIsPossibleIdentifierName(ltok)) {
9755 0 : error(JSMSG_UNEXPECTED_TOKEN, "property name", TokenKindToDesc(ltok));
9756 355 : return null();
9757 : }
9758 :
9759 9017 : propAtom.set(tokenStream.currentName());
9760 : // Do not look for accessor syntax on generator or async methods.
9761 9017 : if (isGenerator || isAsync || !(ltok == TOK_GET || ltok == TOK_SET)) {
9762 8559 : propName = handler.newObjectLiteralPropertyName(propAtom, pos());
9763 8559 : if (!propName)
9764 0 : return null();
9765 17221 : break;
9766 : }
9767 :
9768 458 : *propType = ltok == TOK_GET ? PropertyType::Getter : PropertyType::Setter;
9769 :
9770 : // We have parsed |get| or |set|. Look for an accessor property
9771 : // name next.
9772 : TokenKind tt;
9773 458 : if (!tokenStream.peekToken(&tt))
9774 0 : return null();
9775 458 : if (TokenKindIsPossibleIdentifierName(tt)) {
9776 355 : tokenStream.consumeKnownToken(tt);
9777 :
9778 355 : propAtom.set(tokenStream.currentName());
9779 355 : return handler.newObjectLiteralPropertyName(propAtom, pos());
9780 : }
9781 103 : if (tt == TOK_STRING) {
9782 0 : tokenStream.consumeKnownToken(TOK_STRING);
9783 :
9784 0 : propAtom.set(tokenStream.currentToken().atom());
9785 :
9786 : uint32_t index;
9787 0 : if (propAtom->isIndex(&index)) {
9788 0 : propAtom.set(DoubleToAtom(context, index));
9789 0 : if (!propAtom.get())
9790 0 : return null();
9791 0 : return handler.newNumber(index, NoDecimal, pos());
9792 : }
9793 0 : return stringLiteral();
9794 : }
9795 103 : if (tt == TOK_NUMBER) {
9796 0 : tokenStream.consumeKnownToken(TOK_NUMBER);
9797 :
9798 0 : propAtom.set(DoubleToAtom(context, tokenStream.currentToken().number()));
9799 0 : if (!propAtom.get())
9800 0 : return null();
9801 0 : return newNumber(tokenStream.currentToken());
9802 : }
9803 103 : if (tt == TOK_LB) {
9804 0 : tokenStream.consumeKnownToken(TOK_LB);
9805 :
9806 0 : return computedPropertyName(yieldHandling, maybeDecl, propList);
9807 : }
9808 :
9809 : // Not an accessor property after all.
9810 103 : propName = handler.newObjectLiteralPropertyName(propAtom.get(), pos());
9811 103 : if (!propName)
9812 0 : return null();
9813 103 : break;
9814 : }
9815 : }
9816 :
9817 : TokenKind tt;
9818 10082 : if (!tokenStream.getToken(&tt))
9819 0 : return null();
9820 :
9821 10082 : if (tt == TOK_COLON) {
9822 7320 : if (isGenerator || isAsync) {
9823 0 : error(JSMSG_BAD_PROP_ID);
9824 0 : return null();
9825 : }
9826 7320 : *propType = PropertyType::Normal;
9827 7320 : return propName;
9828 : }
9829 :
9830 6464 : if (TokenKindIsPossibleIdentifierName(ltok) &&
9831 4848 : (tt == TOK_COMMA || tt == TOK_RC || tt == TOK_ASSIGN))
9832 : {
9833 940 : if (isGenerator || isAsync) {
9834 0 : error(JSMSG_BAD_PROP_ID);
9835 0 : return null();
9836 : }
9837 940 : tokenStream.ungetToken();
9838 940 : *propType = tt == TOK_ASSIGN ?
9839 : PropertyType::CoverInitializedName :
9840 : PropertyType::Shorthand;
9841 940 : return propName;
9842 : }
9843 :
9844 1822 : if (tt == TOK_LP) {
9845 1822 : tokenStream.ungetToken();
9846 1822 : if (isGenerator && isAsync)
9847 0 : *propType = PropertyType::AsyncGeneratorMethod;
9848 1822 : else if (isGenerator)
9849 6 : *propType = PropertyType::GeneratorMethod;
9850 1816 : else if (isAsync)
9851 74 : *propType = PropertyType::AsyncMethod;
9852 : else
9853 1742 : *propType = PropertyType::Method;
9854 1822 : return propName;
9855 : }
9856 :
9857 0 : error(JSMSG_COLON_AFTER_ID);
9858 0 : return null();
9859 : }
9860 :
9861 : template <class ParseHandler, typename CharT>
9862 : typename ParseHandler::Node
9863 5 : Parser<ParseHandler, CharT>::computedPropertyName(YieldHandling yieldHandling,
9864 : const Maybe<DeclarationKind>& maybeDecl,
9865 : Node literal)
9866 : {
9867 5 : uint32_t begin = pos().begin;
9868 :
9869 5 : if (maybeDecl) {
9870 0 : if (*maybeDecl == DeclarationKind::FormalParameter)
9871 0 : pc->functionBox()->hasParameterExprs = true;
9872 : } else {
9873 5 : handler.setListFlag(literal, PNX_NONCONST);
9874 : }
9875 :
9876 5 : Node assignNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
9877 5 : if (!assignNode)
9878 0 : return null();
9879 :
9880 5 : MUST_MATCH_TOKEN(TOK_RB, JSMSG_COMP_PROP_UNTERM_EXPR);
9881 5 : return handler.newComputedName(assignNode, begin, pos().end);
9882 : }
9883 :
9884 : template <class ParseHandler, typename CharT>
9885 : typename ParseHandler::Node
9886 2944 : Parser<ParseHandler, CharT>::objectLiteral(YieldHandling yieldHandling,
9887 : PossibleError* possibleError)
9888 : {
9889 2944 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC));
9890 :
9891 2944 : uint32_t openedPos = pos().begin;
9892 :
9893 2944 : Node literal = handler.newObjectLiteral(pos().begin);
9894 2944 : if (!literal)
9895 0 : return null();
9896 :
9897 2944 : bool seenPrototypeMutation = false;
9898 2944 : bool seenCoverInitializedName = false;
9899 5888 : Maybe<DeclarationKind> declKind = Nothing();
9900 5888 : RootedAtom propAtom(context);
9901 7964 : for (;;) {
9902 : TokenKind tt;
9903 10908 : if (!tokenStream.peekToken(&tt))
9904 0 : return null();
9905 10908 : if (tt == TOK_RC)
9906 4067 : break;
9907 :
9908 9785 : if (tt == TOK_TRIPLEDOT) {
9909 0 : tokenStream.consumeKnownToken(TOK_TRIPLEDOT);
9910 0 : uint32_t begin = pos().begin;
9911 :
9912 0 : TokenPos innerPos;
9913 0 : if (!tokenStream.peekTokenPos(&innerPos, TokenStream::Operand))
9914 0 : return null();
9915 :
9916 : Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
9917 0 : possibleError);
9918 0 : if (!inner)
9919 0 : return null();
9920 0 : if (possibleError)
9921 0 : checkDestructuringAssignmentTarget(inner, innerPos, possibleError);
9922 0 : if (!handler.addSpreadProperty(literal, begin, inner))
9923 0 : return null();
9924 : } else {
9925 9785 : TokenPos namePos = tokenStream.nextToken().pos;
9926 :
9927 : PropertyType propType;
9928 9785 : Node propName = propertyName(yieldHandling, declKind, literal, &propType, &propAtom);
9929 9785 : if (!propName)
9930 0 : return null();
9931 :
9932 9785 : if (propType == PropertyType::Normal) {
9933 7096 : TokenPos exprPos;
9934 7096 : if (!tokenStream.peekTokenPos(&exprPos, TokenStream::Operand))
9935 0 : return null();
9936 :
9937 7096 : Node propExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
9938 7096 : possibleError);
9939 7096 : if (!propExpr)
9940 0 : return null();
9941 :
9942 7096 : handler.checkAndSetIsDirectRHSAnonFunction(propExpr);
9943 :
9944 7096 : if (possibleError)
9945 7096 : checkDestructuringAssignmentElement(propExpr, exprPos, possibleError);
9946 :
9947 7096 : if (foldConstants && !FoldConstants(context, &propExpr, this))
9948 0 : return null();
9949 :
9950 7096 : if (propAtom == context->names().proto) {
9951 38 : if (seenPrototypeMutation) {
9952 : // Directly report the error when we're not in a
9953 : // destructuring context.
9954 0 : if (!possibleError) {
9955 0 : errorAt(namePos.begin, JSMSG_DUPLICATE_PROTO_PROPERTY);
9956 0 : return null();
9957 : }
9958 :
9959 : // Otherwise delay error reporting until we've
9960 : // determined whether or not we're destructuring.
9961 0 : possibleError->setPendingExpressionErrorAt(namePos,
9962 : JSMSG_DUPLICATE_PROTO_PROPERTY);
9963 : }
9964 38 : seenPrototypeMutation = true;
9965 :
9966 : // Note: this occurs *only* if we observe TOK_COLON! Only
9967 : // __proto__: v mutates [[Prototype]]. Getters, setters,
9968 : // method/generator definitions, computed property name
9969 : // versions of all of these, and shorthands do not.
9970 38 : if (!handler.addPrototypeMutation(literal, namePos.begin, propExpr))
9971 0 : return null();
9972 : } else {
9973 7058 : if (!handler.isConstant(propExpr))
9974 3000 : handler.setListFlag(literal, PNX_NONCONST);
9975 :
9976 7058 : if (!handler.addPropertyDefinition(literal, propName, propExpr))
9977 0 : return null();
9978 : }
9979 2689 : } else if (propType == PropertyType::Shorthand) {
9980 : /*
9981 : * Support, e.g., |({x, y} = o)| as destructuring shorthand
9982 : * for |({x: x, y: y} = o)|, and |var o = {x, y}| as
9983 : * initializer shorthand for |var o = {x: x, y: y}|.
9984 : */
9985 1336 : Rooted<PropertyName*> name(context, identifierReference(yieldHandling));
9986 668 : if (!name)
9987 0 : return null();
9988 :
9989 668 : Node nameExpr = identifierReference(name);
9990 668 : if (!nameExpr)
9991 0 : return null();
9992 :
9993 668 : if (possibleError)
9994 668 : checkDestructuringAssignmentTarget(nameExpr, namePos, possibleError);
9995 :
9996 668 : if (!handler.addShorthand(literal, propName, nameExpr))
9997 0 : return null();
9998 2021 : } else if (propType == PropertyType::CoverInitializedName) {
9999 : /*
10000 : * Support, e.g., |({x=1, y=2} = o)| as destructuring
10001 : * shorthand with default values, as per ES6 12.14.5
10002 : */
10003 0 : Rooted<PropertyName*> name(context, identifierReference(yieldHandling));
10004 0 : if (!name)
10005 0 : return null();
10006 :
10007 0 : Node lhs = identifierReference(name);
10008 0 : if (!lhs)
10009 0 : return null();
10010 :
10011 0 : tokenStream.consumeKnownToken(TOK_ASSIGN);
10012 :
10013 0 : if (!seenCoverInitializedName) {
10014 : // "shorthand default" or "CoverInitializedName" syntax is
10015 : // only valid in the case of destructuring.
10016 0 : seenCoverInitializedName = true;
10017 :
10018 0 : if (!possibleError) {
10019 : // Destructuring defaults are definitely not allowed
10020 : // in this object literal, because of something the
10021 : // caller knows about the preceding code. For example,
10022 : // maybe the preceding token is an operator:
10023 : // |x + {y=z}|.
10024 0 : error(JSMSG_COLON_AFTER_ID);
10025 0 : return null();
10026 : }
10027 :
10028 : // Here we set a pending error so that later in the parse,
10029 : // once we've determined whether or not we're
10030 : // destructuring, the error can be reported or ignored
10031 : // appropriately.
10032 0 : possibleError->setPendingExpressionErrorAt(pos(), JSMSG_COLON_AFTER_ID);
10033 : }
10034 :
10035 0 : if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(lhs, context)) {
10036 : // |chars| is "arguments" or "eval" here.
10037 0 : if (!strictModeErrorAt(namePos.begin, JSMSG_BAD_STRICT_ASSIGN, chars))
10038 0 : return null();
10039 : }
10040 :
10041 0 : Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
10042 0 : if (!rhs)
10043 0 : return null();
10044 :
10045 0 : handler.checkAndSetIsDirectRHSAnonFunction(rhs);
10046 :
10047 0 : Node propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP);
10048 0 : if (!propExpr)
10049 0 : return null();
10050 :
10051 0 : if (!handler.addPropertyDefinition(literal, propName, propExpr))
10052 0 : return null();
10053 : } else {
10054 4042 : RootedAtom funName(context);
10055 2021 : if (!tokenStream.isCurrentTokenType(TOK_RB)) {
10056 2021 : funName = propAtom;
10057 :
10058 2021 : if (propType == PropertyType::Getter || propType == PropertyType::Setter) {
10059 341 : funName = prefixAccessorName(propType, propAtom);
10060 341 : if (!funName)
10061 0 : return null();
10062 : }
10063 : }
10064 :
10065 2021 : Node fn = methodDefinition(namePos.begin, propType, funName);
10066 2021 : if (!fn)
10067 0 : return null();
10068 :
10069 2021 : handler.checkAndSetIsDirectRHSAnonFunction(fn);
10070 :
10071 2021 : JSOp op = JSOpFromPropertyType(propType);
10072 2021 : if (!handler.addObjectMethodDefinition(literal, propName, fn, op))
10073 0 : return null();
10074 :
10075 2021 : if (possibleError) {
10076 2021 : possibleError->setPendingDestructuringErrorAt(namePos,
10077 : JSMSG_BAD_DESTRUCT_TARGET);
10078 : }
10079 : }
10080 : }
10081 :
10082 : bool matched;
10083 9785 : if (!tokenStream.matchToken(&matched, TOK_COMMA))
10084 0 : return null();
10085 9785 : if (!matched)
10086 1821 : break;
10087 7964 : if (tt == TOK_TRIPLEDOT && possibleError)
10088 0 : possibleError->setPendingDestructuringErrorAt(pos(), JSMSG_REST_WITH_COMMA);
10089 : }
10090 :
10091 2944 : MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::None,
10092 : reportMissingClosing(JSMSG_CURLY_AFTER_LIST,
10093 : JSMSG_CURLY_OPENED, openedPos));
10094 :
10095 2944 : handler.setEndPosition(literal, pos().end);
10096 2944 : return literal;
10097 : }
10098 :
10099 : template <class ParseHandler, typename CharT>
10100 : typename ParseHandler::Node
10101 2177 : Parser<ParseHandler, CharT>::methodDefinition(uint32_t toStringStart, PropertyType propType,
10102 : HandleAtom funName)
10103 : {
10104 : FunctionSyntaxKind kind;
10105 2177 : switch (propType) {
10106 : case PropertyType::Getter:
10107 300 : kind = Getter;
10108 300 : break;
10109 :
10110 : case PropertyType::GetterNoExpressionClosure:
10111 13 : kind = GetterNoExpressionClosure;
10112 13 : break;
10113 :
10114 : case PropertyType::Setter:
10115 41 : kind = Setter;
10116 41 : break;
10117 :
10118 : case PropertyType::SetterNoExpressionClosure:
10119 1 : kind = SetterNoExpressionClosure;
10120 1 : break;
10121 :
10122 : case PropertyType::Method:
10123 : case PropertyType::GeneratorMethod:
10124 : case PropertyType::AsyncMethod:
10125 : case PropertyType::AsyncGeneratorMethod:
10126 1791 : kind = Method;
10127 1791 : break;
10128 :
10129 : case PropertyType::Constructor:
10130 16 : kind = ClassConstructor;
10131 16 : break;
10132 :
10133 : case PropertyType::DerivedConstructor:
10134 15 : kind = DerivedClassConstructor;
10135 15 : break;
10136 :
10137 : default:
10138 0 : MOZ_CRASH("unexpected property type");
10139 : }
10140 :
10141 2171 : GeneratorKind generatorKind = (propType == PropertyType::GeneratorMethod ||
10142 : propType == PropertyType::AsyncGeneratorMethod)
10143 : ? StarGenerator
10144 2183 : : NotGenerator;
10145 :
10146 2103 : FunctionAsyncKind asyncKind = (propType == PropertyType::AsyncMethod ||
10147 : propType == PropertyType::AsyncGeneratorMethod)
10148 : ? AsyncFunction
10149 2251 : : SyncFunction;
10150 :
10151 2177 : YieldHandling yieldHandling = GetYieldHandling(generatorKind);
10152 :
10153 2177 : Node pn = handler.newFunctionExpression(pos());
10154 2177 : if (!pn)
10155 0 : return null();
10156 :
10157 : return functionDefinition(pn, toStringStart, InAllowed, yieldHandling, funName, kind,
10158 2177 : generatorKind, asyncKind);
10159 : }
10160 :
10161 : template <class ParseHandler, typename CharT>
10162 : bool
10163 1344 : Parser<ParseHandler, CharT>::tryNewTarget(Node &newTarget)
10164 : {
10165 1344 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_NEW));
10166 :
10167 1344 : newTarget = null();
10168 :
10169 1344 : Node newHolder = handler.newPosHolder(pos());
10170 1344 : if (!newHolder)
10171 0 : return false;
10172 :
10173 1344 : uint32_t begin = pos().begin;
10174 :
10175 : // |new| expects to look for an operand, so we will honor that.
10176 : TokenKind next;
10177 1344 : if (!tokenStream.getToken(&next, TokenStream::Operand))
10178 0 : return false;
10179 :
10180 : // Don't unget the token, since lookahead cannot handle someone calling
10181 : // getToken() with a different modifier. Callers should inspect currentToken().
10182 1344 : if (next != TOK_DOT)
10183 1332 : return true;
10184 :
10185 12 : if (!tokenStream.getToken(&next))
10186 0 : return false;
10187 12 : if (next != TOK_TARGET) {
10188 0 : error(JSMSG_UNEXPECTED_TOKEN, "target", TokenKindToDesc(next));
10189 0 : return false;
10190 : }
10191 :
10192 12 : if (!pc->sc()->allowNewTarget()) {
10193 0 : errorAt(begin, JSMSG_BAD_NEWTARGET);
10194 0 : return false;
10195 : }
10196 :
10197 12 : Node targetHolder = handler.newPosHolder(pos());
10198 12 : if (!targetHolder)
10199 0 : return false;
10200 :
10201 12 : newTarget = handler.newNewTarget(newHolder, targetHolder);
10202 12 : return !!newTarget;
10203 : }
10204 :
10205 : template <class ParseHandler, typename CharT>
10206 : typename ParseHandler::Node
10207 88560 : Parser<ParseHandler, CharT>::primaryExpr(YieldHandling yieldHandling,
10208 : TripledotHandling tripledotHandling, TokenKind tt,
10209 : PossibleError* possibleError,
10210 : InvokedPrediction invoked /* = PredictUninvoked */)
10211 : {
10212 88560 : MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
10213 88560 : if (!CheckRecursionLimit(context))
10214 0 : return null();
10215 :
10216 88560 : switch (tt) {
10217 : case TOK_FUNCTION:
10218 1181 : return functionExpr(pos().begin, invoked);
10219 :
10220 : case TOK_CLASS:
10221 6 : return classDefinition(yieldHandling, ClassExpression, NameRequired);
10222 :
10223 : case TOK_LB:
10224 1400 : return arrayInitializer(yieldHandling, possibleError);
10225 :
10226 : case TOK_LC:
10227 2944 : return objectLiteral(yieldHandling, possibleError);
10228 :
10229 : case TOK_LP: {
10230 : TokenKind next;
10231 2526 : if (!tokenStream.peekToken(&next, TokenStream::Operand))
10232 0 : return null();
10233 :
10234 2526 : if (next == TOK_RP) {
10235 : // Not valid expression syntax, but this is valid in an arrow function
10236 : // with no params: `() => body`.
10237 373 : tokenStream.consumeKnownToken(next, TokenStream::Operand);
10238 :
10239 373 : if (!tokenStream.peekToken(&next))
10240 0 : return null();
10241 373 : if (next != TOK_ARROW) {
10242 0 : error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(TOK_RP));
10243 0 : return null();
10244 : }
10245 :
10246 : // Now just return something that will allow parsing to continue.
10247 : // It doesn't matter what; when we reach the =>, we will rewind and
10248 : // reparse the whole arrow function. See Parser::assignExpr.
10249 373 : return handler.newNullLiteral(pos());
10250 : }
10251 :
10252 2153 : if (next == TOK_FOR) {
10253 0 : uint32_t begin = pos().begin;
10254 0 : tokenStream.consumeKnownToken(next, TokenStream::Operand);
10255 0 : return generatorComprehension(begin);
10256 : }
10257 :
10258 : // Pass |possibleError| to support destructuring in arrow parameters.
10259 2153 : Node expr = exprInParens(InAllowed, yieldHandling, TripledotAllowed, possibleError);
10260 2153 : if (!expr)
10261 0 : return null();
10262 2153 : MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
10263 2153 : return handler.parenthesize(expr);
10264 : }
10265 :
10266 : case TOK_TEMPLATE_HEAD:
10267 292 : return templateLiteral(yieldHandling);
10268 :
10269 : case TOK_NO_SUBS_TEMPLATE:
10270 18 : return noSubstitutionUntaggedTemplate();
10271 :
10272 : case TOK_STRING:
10273 5645 : return stringLiteral();
10274 :
10275 : default: {
10276 54038 : if (!TokenKindIsPossibleIdentifier(tt)) {
10277 0 : error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt));
10278 0 : return null();
10279 : }
10280 :
10281 54038 : if (tt == TOK_ASYNC) {
10282 48 : TokenKind nextSameLine = TOK_EOF;
10283 48 : if (!tokenStream.peekTokenSameLine(&nextSameLine))
10284 8 : return null();
10285 :
10286 48 : if (nextSameLine == TOK_FUNCTION) {
10287 8 : uint32_t toStringStart = pos().begin;
10288 8 : tokenStream.consumeKnownToken(TOK_FUNCTION);
10289 8 : return functionExpr(toStringStart, PredictUninvoked, AsyncFunction);
10290 : }
10291 : }
10292 :
10293 108060 : Rooted<PropertyName*> name(context, identifierReference(yieldHandling));
10294 54030 : if (!name)
10295 0 : return null();
10296 :
10297 54030 : return identifierReference(name);
10298 : }
10299 :
10300 : case TOK_REGEXP:
10301 210 : return newRegExp();
10302 :
10303 : case TOK_NUMBER:
10304 3919 : return newNumber(tokenStream.currentToken());
10305 :
10306 : case TOK_TRUE:
10307 1546 : return handler.newBooleanLiteral(true, pos());
10308 : case TOK_FALSE:
10309 1553 : return handler.newBooleanLiteral(false, pos());
10310 : case TOK_THIS: {
10311 11019 : if (pc->isFunctionBox())
10312 10286 : pc->functionBox()->usesThis = true;
10313 11019 : Node thisName = null();
10314 11019 : if (pc->sc()->thisBinding() == ThisBinding::Function) {
10315 10278 : thisName = newThisName();
10316 10278 : if (!thisName)
10317 0 : return null();
10318 : }
10319 11019 : return handler.newThisLiteral(pos(), thisName);
10320 : }
10321 : case TOK_NULL:
10322 2259 : return handler.newNullLiteral(pos());
10323 :
10324 : case TOK_TRIPLEDOT: {
10325 : // This isn't valid expression syntax, but it's valid in an arrow
10326 : // function as a trailing rest param: `(a, b, ...rest) => body`. Check
10327 : // if it's directly under
10328 : // CoverParenthesizedExpressionAndArrowParameterList, and check for a
10329 : // name, closing parenthesis, and arrow, and allow it only if all are
10330 : // present.
10331 4 : if (tripledotHandling != TripledotAllowed) {
10332 0 : error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt));
10333 0 : return null();
10334 : }
10335 :
10336 : TokenKind next;
10337 4 : if (!tokenStream.getToken(&next))
10338 0 : return null();
10339 :
10340 4 : if (next == TOK_LB || next == TOK_LC) {
10341 : // Validate, but don't store the pattern right now. The whole arrow
10342 : // function is reparsed in functionFormalParametersAndBody().
10343 0 : if (!destructuringDeclaration(DeclarationKind::CoverArrowParameter, yieldHandling,
10344 : next))
10345 : {
10346 0 : return null();
10347 : }
10348 : } else {
10349 : // This doesn't check that the provided name is allowed, e.g. if
10350 : // the enclosing code is strict mode code, any of "let", "yield",
10351 : // or "arguments" should be prohibited. Argument-parsing code
10352 : // handles that.
10353 4 : if (!TokenKindIsPossibleIdentifier(next)) {
10354 0 : error(JSMSG_UNEXPECTED_TOKEN, "rest argument name", TokenKindToDesc(next));
10355 0 : return null();
10356 : }
10357 : }
10358 :
10359 4 : if (!tokenStream.getToken(&next))
10360 0 : return null();
10361 4 : if (next != TOK_RP) {
10362 0 : error(JSMSG_UNEXPECTED_TOKEN, "closing parenthesis", TokenKindToDesc(next));
10363 0 : return null();
10364 : }
10365 :
10366 4 : if (!tokenStream.peekToken(&next))
10367 0 : return null();
10368 4 : if (next != TOK_ARROW) {
10369 : // Advance the scanner for proper error location reporting.
10370 0 : tokenStream.consumeKnownToken(next);
10371 0 : error(JSMSG_UNEXPECTED_TOKEN, "'=>' after argument list", TokenKindToDesc(next));
10372 0 : return null();
10373 : }
10374 :
10375 4 : tokenStream.ungetToken(); // put back right paren
10376 :
10377 : // Return an arbitrary expression node. See case TOK_RP above.
10378 4 : return handler.newNullLiteral(pos());
10379 : }
10380 : }
10381 : }
10382 :
10383 : template <class ParseHandler, typename CharT>
10384 : typename ParseHandler::Node
10385 11442 : Parser<ParseHandler, CharT>::exprInParens(InHandling inHandling, YieldHandling yieldHandling,
10386 : TripledotHandling tripledotHandling,
10387 : PossibleError* possibleError /* = nullptr */)
10388 : {
10389 11442 : MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP));
10390 11442 : return expr(inHandling, yieldHandling, tripledotHandling, possibleError, PredictInvoked);
10391 : }
10392 :
10393 : void
10394 0 : ParserBase::addTelemetry(DeprecatedLanguageExtension e)
10395 : {
10396 0 : if (context->helperThread())
10397 0 : return;
10398 0 : context->compartment()->addTelemetry(getFilename(), e);
10399 : }
10400 :
10401 : bool
10402 0 : ParserBase::warnOnceAboutExprClosure()
10403 : {
10404 : #ifndef RELEASE_OR_BETA
10405 0 : if (context->helperThread())
10406 0 : return true;
10407 :
10408 0 : if (!context->compartment()->warnedAboutExprClosure) {
10409 0 : if (!warning(JSMSG_DEPRECATED_EXPR_CLOSURE))
10410 0 : return false;
10411 0 : context->compartment()->warnedAboutExprClosure = true;
10412 : }
10413 : #endif
10414 0 : return true;
10415 : }
10416 :
10417 : bool
10418 0 : ParserBase::warnOnceAboutForEach()
10419 : {
10420 0 : if (context->helperThread())
10421 0 : return true;
10422 :
10423 0 : if (!context->compartment()->warnedAboutForEach) {
10424 0 : if (!warning(JSMSG_DEPRECATED_FOR_EACH))
10425 0 : return false;
10426 0 : context->compartment()->warnedAboutForEach = true;
10427 : }
10428 0 : return true;
10429 : }
10430 :
10431 : template class Parser<FullParseHandler, char16_t>;
10432 : template class Parser<SyntaxParseHandler, char16_t>;
10433 :
10434 : } /* namespace frontend */
10435 : } /* namespace js */
|