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