1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "frontend/ParseContext-inl.h"
9 #include "frontend/CompilationStencil.h" // ScopeContext
10 #include "frontend/Parser.h" // ParserBase
11 #include "js/friend/ErrorMessages.h" // JSMSG_*
14 using mozilla::Nothing
;
20 using AddDeclaredNamePtr
= ParseContext::Scope::AddDeclaredNamePtr
;
21 using DeclaredNamePtr
= ParseContext::Scope::DeclaredNamePtr
;
23 const char* DeclarationKindString(DeclarationKind kind
) {
25 case DeclarationKind::PositionalFormalParameter
:
26 case DeclarationKind::FormalParameter
:
27 return "formal parameter";
28 case DeclarationKind::CoverArrowParameter
:
29 return "cover arrow parameter";
30 case DeclarationKind::Var
:
32 case DeclarationKind::Let
:
34 case DeclarationKind::Const
:
36 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
37 case DeclarationKind::Using
:
39 case DeclarationKind::AwaitUsing
:
42 case DeclarationKind::Class
:
44 case DeclarationKind::Import
:
46 case DeclarationKind::BodyLevelFunction
:
47 case DeclarationKind::ModuleBodyLevelFunction
:
48 case DeclarationKind::LexicalFunction
:
49 case DeclarationKind::SloppyLexicalFunction
:
51 case DeclarationKind::VarForAnnexBLexicalFunction
:
53 case DeclarationKind::SimpleCatchParameter
:
54 case DeclarationKind::CatchParameter
:
55 return "catch parameter";
56 case DeclarationKind::PrivateName
:
57 return "private name";
58 case DeclarationKind::Synthetic
:
60 case DeclarationKind::PrivateMethod
:
61 return "private method";
64 MOZ_CRASH("Bad DeclarationKind");
67 bool DeclarationKindIsVar(DeclarationKind kind
) {
68 return kind
== DeclarationKind::Var
||
69 kind
== DeclarationKind::BodyLevelFunction
||
70 kind
== DeclarationKind::VarForAnnexBLexicalFunction
;
73 bool DeclarationKindIsParameter(DeclarationKind kind
) {
74 return kind
== DeclarationKind::PositionalFormalParameter
||
75 kind
== DeclarationKind::FormalParameter
;
78 bool UsedNameTracker::noteUse(FrontendContext
* fc
, TaggedParserAtomIndex name
,
79 NameVisibility visibility
, uint32_t scriptId
,
81 mozilla::Maybe
<TokenPos
> tokenPosition
) {
82 if (UsedNameMap::AddPtr p
= map_
.lookupForAdd(name
)) {
83 p
->value().maybeUpdatePos(tokenPosition
);
85 if (!p
->value().noteUsedInScope(scriptId
, scopeId
)) {
89 // We need a token position precisely where we have private visibility.
90 MOZ_ASSERT(tokenPosition
.isSome() ==
91 (visibility
== NameVisibility::Private
));
93 if (visibility
== NameVisibility::Private
) {
94 // We have seen at least one private name
95 hasPrivateNames_
= true;
98 UsedNameInfo
info(fc
, visibility
, tokenPosition
);
100 if (!info
.noteUsedInScope(scriptId
, scopeId
)) {
103 if (!map_
.add(p
, name
, std::move(info
))) {
111 bool UsedNameTracker::getUnboundPrivateNames(
112 Vector
<UnboundPrivateName
, 8>& unboundPrivateNames
) {
113 // We never saw any private names, so can just return early
114 if (!hasPrivateNames_
) {
118 for (auto iter
= map_
.iter(); !iter
.done(); iter
.next()) {
119 // Don't care about public;
120 if (iter
.get().value().isPublic()) {
124 // empty list means all bound
125 if (iter
.get().value().empty()) {
129 if (!unboundPrivateNames
.emplaceBack(iter
.get().key(),
130 *iter
.get().value().pos())) {
135 // Return a sorted list in ascendng order of position.
136 auto comparePosition
= [](const auto& a
, const auto& b
) {
137 return a
.position
< b
.position
;
139 std::sort(unboundPrivateNames
.begin(), unboundPrivateNames
.end(),
145 bool UsedNameTracker::hasUnboundPrivateNames(
146 FrontendContext
* fc
, mozilla::Maybe
<UnboundPrivateName
>& maybeUnboundName
) {
147 // We never saw any private names, so can just return early
148 if (!hasPrivateNames_
) {
152 Vector
<UnboundPrivateName
, 8> unboundPrivateNames(fc
);
153 if (!getUnboundPrivateNames(unboundPrivateNames
)) {
157 if (unboundPrivateNames
.empty()) {
161 // GetUnboundPrivateNames returns the list sorted.
162 maybeUnboundName
.emplace(unboundPrivateNames
[0]);
166 void UsedNameTracker::UsedNameInfo::resetToScope(uint32_t scriptId
,
168 while (!uses_
.empty()) {
169 Use
& innermost
= uses_
.back();
170 if (innermost
.scopeId
< scopeId
) {
173 MOZ_ASSERT(innermost
.scriptId
>= scriptId
);
178 void UsedNameTracker::rewind(RewindToken token
) {
179 scriptCounter_
= token
.scriptId
;
180 scopeCounter_
= token
.scopeId
;
182 for (UsedNameMap::Range r
= map_
.all(); !r
.empty(); r
.popFront()) {
183 r
.front().value().resetToScope(token
.scriptId
, token
.scopeId
);
187 #if defined(DEBUG) || defined(JS_JITSPEW)
188 void UsedNameTracker::dump(ParserAtomsTable
& table
) {
189 js::Fprinter
out(stderr
);
191 out
.printf("Used names:\n");
193 for (UsedNameMap::Range r
= map_
.all(); !r
.empty(); r
.popFront()) {
194 const auto& item
= r
.front();
196 const auto& name
= item
.key();
197 const auto& nameInfo
= item
.value();
200 table
.dumpCharsNoQuote(out
, name
);
203 if (nameInfo
.visibility_
== NameVisibility::Private
) {
204 out
.put(" visibility: private\n");
207 if (nameInfo
.firstUsePos_
) {
208 const auto& pos
= *nameInfo
.firstUsePos_
;
209 out
.printf(" first use pos: %u\n", pos
.begin
);
212 out
.printf(" %zu user(s)", nameInfo
.uses_
.length());
214 for (const auto& use
: nameInfo
.uses_
) {
221 out
.printf("%u/%u", use
.scriptId
, use
.scopeId
);
231 void ParseContext::Scope::dump(ParseContext
* pc
, ParserBase
* parser
) {
232 fprintf(stdout
, "ParseScope %p", this);
234 fprintf(stdout
, "\n decls:\n");
235 for (DeclaredNameMap::Range r
= declared_
->all(); !r
.empty(); r
.popFront()) {
236 auto index
= r
.front().key();
237 UniqueChars bytes
= parser
->parserAtoms().toPrintableString(index
);
239 ReportOutOfMemory(pc
->sc()->fc_
);
242 DeclaredNameInfo
& info
= r
.front().value().wrapped
;
243 fprintf(stdout
, " %s %s%s\n", DeclarationKindString(info
.kind()),
244 bytes
.get(), info
.closedOver() ? " (closed over)" : "");
247 fprintf(stdout
, "\n");
250 bool ParseContext::Scope::addPossibleAnnexBFunctionBox(ParseContext
* pc
,
251 FunctionBox
* funbox
) {
252 if (!possibleAnnexBFunctionBoxes_
) {
253 if (!possibleAnnexBFunctionBoxes_
.acquire(pc
->sc()->fc_
)) {
258 return maybeReportOOM(pc
, possibleAnnexBFunctionBoxes_
->append(funbox
));
261 bool ParseContext::Scope::propagateAndMarkAnnexBFunctionBoxes(
262 ParseContext
* pc
, ParserBase
* parser
) {
263 // Strict mode doesn't have wack Annex B function semantics.
264 if (pc
->sc()->strict() || !possibleAnnexBFunctionBoxes_
||
265 possibleAnnexBFunctionBoxes_
->empty()) {
269 if (this == &pc
->varScope()) {
270 // Base case: actually declare the Annex B vars and mark applicable
271 // function boxes as Annex B.
272 Maybe
<DeclarationKind
> redeclaredKind
;
274 for (FunctionBox
* funbox
: *possibleAnnexBFunctionBoxes_
) {
276 if (!pc
->computeAnnexBAppliesToLexicalFunctionInInnermostScope(
277 funbox
, parser
, &annexBApplies
)) {
281 if (!pc
->tryDeclareVar(funbox
->explicitName(), parser
,
282 DeclarationKind::VarForAnnexBLexicalFunction
,
283 DeclaredNameInfo::npos
, &redeclaredKind
,
288 MOZ_ASSERT(!redeclaredKind
);
289 funbox
->isAnnexB
= true;
293 // Inner scope case: propagate still applicable function boxes to the
295 for (FunctionBox
* funbox
: *possibleAnnexBFunctionBoxes_
) {
297 if (!pc
->computeAnnexBAppliesToLexicalFunctionInInnermostScope(
298 funbox
, parser
, &annexBApplies
)) {
302 if (!enclosing()->addPossibleAnnexBFunctionBox(pc
, funbox
)) {
312 static bool DeclarationKindIsCatchParameter(DeclarationKind kind
) {
313 return kind
== DeclarationKind::SimpleCatchParameter
||
314 kind
== DeclarationKind::CatchParameter
;
317 bool ParseContext::Scope::addCatchParameters(ParseContext
* pc
,
318 Scope
& catchParamScope
) {
319 if (pc
->useAsmOrInsideUseAsm()) {
323 for (DeclaredNameMap::Range r
= catchParamScope
.declared_
->all(); !r
.empty();
325 DeclarationKind kind
= r
.front().value()->kind();
326 uint32_t pos
= r
.front().value()->pos();
327 MOZ_ASSERT(DeclarationKindIsCatchParameter(kind
));
328 auto name
= r
.front().key();
329 AddDeclaredNamePtr p
= lookupDeclaredNameForAdd(name
);
331 if (!addDeclaredName(pc
, p
, name
, kind
, pos
)) {
339 void ParseContext::Scope::removeCatchParameters(ParseContext
* pc
,
340 Scope
& catchParamScope
) {
341 if (pc
->useAsmOrInsideUseAsm()) {
345 for (DeclaredNameMap::Range r
= catchParamScope
.declared_
->all(); !r
.empty();
347 auto name
= r
.front().key();
348 DeclaredNamePtr p
= declared_
->lookup(name
);
351 // This check is needed because the catch body could have declared
352 // vars, which would have been added to catchParamScope.
353 if (DeclarationKindIsCatchParameter(r
.front().value()->kind())) {
354 declared_
->remove(p
);
359 ParseContext::ParseContext(FrontendContext
* fc
, ParseContext
*& parent
,
360 SharedContext
* sc
, ErrorReporter
& errorReporter
,
361 CompilationState
& compilationState
,
362 Directives
* newDirectives
, bool isFull
)
363 : Nestable
<ParseContext
>(&parent
),
365 errorReporter_(errorReporter
),
366 innermostStatement_(nullptr),
367 innermostScope_(nullptr),
369 positionalFormalParameterNames_(fc
->nameCollectionPool()),
370 closedOverBindingsForLazy_(fc
->nameCollectionPool()),
371 innerFunctionIndexesForLazy(sc
->fc_
),
372 newDirectives(newDirectives
),
373 lastYieldOffset(NoYieldOffset
),
374 lastAwaitOffset(NoAwaitOffset
),
375 scriptId_(compilationState
.usedNames
.nextScriptId()),
376 superScopeNeedsHomeObject_(false) {
377 if (isFunctionBox()) {
378 if (functionBox()->isNamedLambda()) {
379 namedLambdaScope_
.emplace(fc
, parent
, compilationState
.usedNames
);
381 functionScope_
.emplace(fc
, parent
, compilationState
.usedNames
);
385 bool ParseContext::init() {
386 if (scriptId_
== UINT32_MAX
) {
387 errorReporter_
.errorNoOffset(JSMSG_NEED_DIET
, "script");
391 FrontendContext
* fc
= sc()->fc_
;
393 if (isFunctionBox()) {
394 // Named lambdas always need a binding for their own name. If this
395 // binding is closed over when we finish parsing the function iNn
396 // finishFunctionScopes, the function box needs to be marked as
397 // needing a dynamic DeclEnv object.
398 if (functionBox()->isNamedLambda()) {
399 if (!namedLambdaScope_
->init(this)) {
402 AddDeclaredNamePtr p
= namedLambdaScope_
->lookupDeclaredNameForAdd(
403 functionBox()->explicitName());
405 if (!namedLambdaScope_
->addDeclaredName(
406 this, p
, functionBox()->explicitName(), DeclarationKind::Const
,
407 DeclaredNameInfo::npos
)) {
412 if (!functionScope_
->init(this)) {
416 if (!positionalFormalParameterNames_
.acquire(fc
)) {
421 if (!closedOverBindingsForLazy_
.acquire(fc
)) {
428 bool ParseContext::computeAnnexBAppliesToLexicalFunctionInInnermostScope(
429 FunctionBox
* funbox
, ParserBase
* parser
, bool* annexBApplies
) {
430 MOZ_ASSERT(!sc()->strict());
432 TaggedParserAtomIndex name
= funbox
->explicitName();
433 Maybe
<DeclarationKind
> redeclaredKind
;
434 if (!isVarRedeclaredInInnermostScope(
435 name
, parser
, DeclarationKind::VarForAnnexBLexicalFunction
,
440 if (!redeclaredKind
&& isFunctionBox()) {
441 Scope
& funScope
= functionScope();
442 if (&funScope
!= &varScope()) {
443 // Annex B.3.3.1 disallows redeclaring parameter names. In the
444 // presence of parameter expressions, parameter names are on the
445 // function scope, which encloses the var scope. This means the
446 // isVarRedeclaredInInnermostScope call above would not catch this
447 // case, so test it manually.
448 if (DeclaredNamePtr p
= funScope
.lookupDeclaredName(name
)) {
449 DeclarationKind declaredKind
= p
->value()->kind();
450 if (DeclarationKindIsParameter(declaredKind
)) {
451 redeclaredKind
= Some(declaredKind
);
453 MOZ_ASSERT(FunctionScope::isSpecialName(name
));
459 // If an early error would have occurred already, this function should not
460 // exhibit Annex B.3.3 semantics.
461 *annexBApplies
= !redeclaredKind
;
465 bool ParseContext::isVarRedeclaredInInnermostScope(
466 TaggedParserAtomIndex name
, ParserBase
* parser
, DeclarationKind kind
,
467 mozilla::Maybe
<DeclarationKind
>* out
) {
469 return tryDeclareVarHelper
<DryRunInnermostScopeOnly
>(
470 name
, parser
, kind
, DeclaredNameInfo::npos
, out
, &unused
);
473 bool ParseContext::isVarRedeclaredInEval(TaggedParserAtomIndex name
,
475 DeclarationKind kind
,
476 Maybe
<DeclarationKind
>* out
) {
477 auto maybeKind
= parser
->getCompilationState()
478 .scopeContext
.lookupLexicalBindingInEnclosingScope(name
);
484 switch (*maybeKind
) {
485 case ScopeContext::EnclosingLexicalBindingKind::Let
:
486 *out
= Some(DeclarationKind::Let
);
488 case ScopeContext::EnclosingLexicalBindingKind::Const
:
489 *out
= Some(DeclarationKind::Const
);
491 case ScopeContext::EnclosingLexicalBindingKind::CatchParameter
:
492 *out
= Some(DeclarationKind::CatchParameter
);
494 case ScopeContext::EnclosingLexicalBindingKind::Synthetic
:
495 *out
= Some(DeclarationKind::Synthetic
);
497 case ScopeContext::EnclosingLexicalBindingKind::PrivateMethod
:
498 *out
= Some(DeclarationKind::PrivateMethod
);
504 bool ParseContext::tryDeclareVar(TaggedParserAtomIndex name
, ParserBase
* parser
,
505 DeclarationKind kind
, uint32_t beginPos
,
506 Maybe
<DeclarationKind
>* redeclaredKind
,
508 return tryDeclareVarHelper
<NotDryRun
>(name
, parser
, kind
, beginPos
,
509 redeclaredKind
, prevPos
);
512 template <ParseContext::DryRunOption dryRunOption
>
513 bool ParseContext::tryDeclareVarHelper(TaggedParserAtomIndex name
,
514 ParserBase
* parser
, DeclarationKind kind
,
516 Maybe
<DeclarationKind
>* redeclaredKind
,
518 MOZ_ASSERT(DeclarationKindIsVar(kind
));
520 // It is an early error if a 'var' declaration appears inside a
521 // scope contour that has a lexical declaration of the same name. For
522 // example, the following are early errors:
525 // { { var x; } let x; }
527 // And the following are not:
530 // { { let x; } var x; }
532 for (ParseContext::Scope
* scope
= innermostScope();
533 scope
!= varScope().enclosing(); scope
= scope
->enclosing()) {
534 if (AddDeclaredNamePtr p
= scope
->lookupDeclaredNameForAdd(name
)) {
535 DeclarationKind declaredKind
= p
->value()->kind();
536 if (DeclarationKindIsVar(declaredKind
)) {
537 if (dryRunOption
== NotDryRun
) {
538 RedeclareVar(p
, kind
);
540 } else if (!DeclarationKindIsParameter(declaredKind
)) {
541 // Annex B.3.5 allows redeclaring simple (non-destructured)
542 // catch parameters with var declarations.
543 bool annexB35Allowance
=
544 declaredKind
== DeclarationKind::SimpleCatchParameter
;
546 // Annex B.3.3 allows redeclaring functions in the same block.
547 bool annexB33Allowance
=
548 declaredKind
== DeclarationKind::SloppyLexicalFunction
&&
549 kind
== DeclarationKind::VarForAnnexBLexicalFunction
&&
550 scope
== innermostScope();
552 if (!annexB35Allowance
&& !annexB33Allowance
) {
553 *redeclaredKind
= Some(declaredKind
);
554 *prevPos
= p
->value()->pos();
557 } else if (kind
== DeclarationKind::VarForAnnexBLexicalFunction
) {
558 MOZ_ASSERT(DeclarationKindIsParameter(declaredKind
));
560 // Annex B.3.3.1 disallows redeclaring parameter names.
561 // We don't need to set *prevPos here since this case is not
563 *redeclaredKind
= Some(declaredKind
);
566 } else if (dryRunOption
== NotDryRun
) {
567 if (!scope
->addDeclaredName(this, p
, name
, kind
, beginPos
)) {
572 // DryRunOption is used for propagating Annex B functions: we don't
573 // want to declare the synthesized Annex B vars until we exit the var
574 // scope and know that no early errors would have occurred. In order
575 // to avoid quadratic search, we only check for var redeclarations in
576 // the innermost scope when doing a dry run.
577 if (dryRunOption
== DryRunInnermostScopeOnly
) {
582 if (!sc()->strict() && sc()->isEvalContext() &&
583 (dryRunOption
== NotDryRun
|| innermostScope() == &varScope())) {
584 if (!isVarRedeclaredInEval(name
, parser
, kind
, redeclaredKind
)) {
587 // We don't have position information at runtime.
588 *prevPos
= DeclaredNameInfo::npos
;
594 bool ParseContext::hasUsedName(const UsedNameTracker
& usedNames
,
595 TaggedParserAtomIndex name
) {
596 if (auto p
= usedNames
.lookup(name
)) {
597 return p
->value().isUsedInScript(scriptId());
602 bool ParseContext::hasClosedOverName(const UsedNameTracker
& usedNames
,
603 TaggedParserAtomIndex name
) {
604 if (auto p
= usedNames
.lookup(name
)) {
605 return p
->value().isClosedOver(scriptId());
610 bool ParseContext::hasUsedFunctionSpecialName(const UsedNameTracker
& usedNames
,
611 TaggedParserAtomIndex name
) {
612 MOZ_ASSERT(name
== TaggedParserAtomIndex::WellKnown::arguments() ||
613 name
== TaggedParserAtomIndex::WellKnown::dot_this_() ||
614 name
== TaggedParserAtomIndex::WellKnown::dot_newTarget_());
615 return hasUsedName(usedNames
, name
) ||
616 functionBox()->bindingsAccessedDynamically();
619 bool ParseContext::hasClosedOverFunctionSpecialName(
620 const UsedNameTracker
& usedNames
, TaggedParserAtomIndex name
) {
621 MOZ_ASSERT(name
== TaggedParserAtomIndex::WellKnown::arguments());
622 return hasClosedOverName(usedNames
, name
) ||
623 functionBox()->bindingsAccessedDynamically();
626 bool ParseContext::declareFunctionThis(const UsedNameTracker
& usedNames
,
627 bool canSkipLazyClosedOverBindings
) {
628 // The asm.js validator does all its own symbol-table management so, as an
629 // optimization, avoid doing any work here.
630 if (useAsmOrInsideUseAsm()) {
634 // Derived class constructors emit JSOp::CheckReturn, which requires
635 // '.this' to be bound. Class field initializers implicitly read `.this`.
636 // Therefore we unconditionally declare `.this` in all class constructors.
637 FunctionBox
* funbox
= functionBox();
638 auto dotThis
= TaggedParserAtomIndex::WellKnown::dot_this_();
641 if (canSkipLazyClosedOverBindings
) {
642 declareThis
= funbox
->functionHasThisBinding();
644 declareThis
= hasUsedFunctionSpecialName(usedNames
, dotThis
) ||
645 funbox
->isClassConstructor();
649 ParseContext::Scope
& funScope
= functionScope();
650 AddDeclaredNamePtr p
= funScope
.lookupDeclaredNameForAdd(dotThis
);
652 if (!funScope
.addDeclaredName(this, p
, dotThis
, DeclarationKind::Var
,
653 DeclaredNameInfo::npos
)) {
656 funbox
->setFunctionHasThisBinding();
662 bool ParseContext::declareFunctionArgumentsObject(
663 const UsedNameTracker
& usedNames
, bool canSkipLazyClosedOverBindings
) {
664 FunctionBox
* funbox
= functionBox();
665 ParseContext::Scope
& funScope
= functionScope();
666 ParseContext::Scope
& _varScope
= varScope();
668 bool hasExtraBodyVarScope
= &funScope
!= &_varScope
;
670 // Time to implement the odd semantics of 'arguments'.
671 auto argumentsName
= TaggedParserAtomIndex::WellKnown::arguments();
673 bool tryDeclareArguments
= false;
674 bool needsArgsObject
= false;
676 // When delazifying simply defer to the function box.
677 if (canSkipLazyClosedOverBindings
) {
678 tryDeclareArguments
= funbox
->shouldDeclareArguments();
679 needsArgsObject
= funbox
->needsArgsObj();
681 // We cannot compute these values when delazifying, hence why we need to
682 // rely on the function box flags instead.
683 bool bindingClosedOver
=
684 hasClosedOverFunctionSpecialName(usedNames
, argumentsName
);
685 bool bindingUsedOnlyHere
=
686 hasUsedFunctionSpecialName(usedNames
, argumentsName
) &&
689 // Declare arguments if there's a closed-over consumer of the binding, or if
690 // there is a non-length use and we will reference the binding during
691 // bytecode emission.
692 tryDeclareArguments
=
693 !funbox
->isEligibleForArgumentsLength() || bindingClosedOver
;
694 // If we have a use and the binding isn't closed over, then we will do
695 // bytecode emission with the arguments intrinsic.
696 if (bindingUsedOnlyHere
&& funbox
->isEligibleForArgumentsLength()) {
697 // If we're using the intrinsic we should not be declaring the binding.
698 MOZ_ASSERT(!tryDeclareArguments
);
699 funbox
->setUsesArgumentsIntrinsics();
700 } else if (tryDeclareArguments
) {
701 needsArgsObject
= true;
705 // ES 9.2.12 steps 19 and 20 say formal parameters, lexical bindings,
706 // and body-level functions named 'arguments' shadow the arguments
709 // So even if there wasn't a free use of 'arguments' but there is a var
710 // binding of 'arguments', we still might need the arguments object.
712 // If we have an extra var scope due to parameter expressions and the body
713 // declared 'var arguments', we still need to declare 'arguments' in the
715 DeclaredNamePtr p
= _varScope
.lookupDeclaredName(argumentsName
);
716 if (p
&& p
->value()->kind() == DeclarationKind::Var
) {
717 if (hasExtraBodyVarScope
) {
718 // While there is a binding in the var scope, we should declare
719 // the binding in the function scope.
720 tryDeclareArguments
= true;
722 // A binding in the function scope (since varScope and functionScope are
723 // the same) exists, so arguments is used.
724 if (needsArgsObject
) {
725 funbox
->setNeedsArgsObj();
728 // There is no point in continuing on below: We know we already have
729 // a declaration of arguments in the function scope.
734 if (tryDeclareArguments
) {
735 AddDeclaredNamePtr p
= funScope
.lookupDeclaredNameForAdd(argumentsName
);
737 if (!funScope
.addDeclaredName(this, p
, argumentsName
,
738 DeclarationKind::Var
,
739 DeclaredNameInfo::npos
)) {
742 funbox
->setShouldDeclareArguments();
743 if (needsArgsObject
) {
744 funbox
->setNeedsArgsObj();
751 bool ParseContext::declareNewTarget(const UsedNameTracker
& usedNames
,
752 bool canSkipLazyClosedOverBindings
) {
753 // The asm.js validator does all its own symbol-table management so, as an
754 // optimization, avoid doing any work here.
755 if (useAsmOrInsideUseAsm()) {
759 FunctionBox
* funbox
= functionBox();
760 auto dotNewTarget
= TaggedParserAtomIndex::WellKnown::dot_newTarget_();
762 bool declareNewTarget
;
763 if (canSkipLazyClosedOverBindings
) {
764 declareNewTarget
= funbox
->functionHasNewTargetBinding();
766 declareNewTarget
= hasUsedFunctionSpecialName(usedNames
, dotNewTarget
);
769 if (declareNewTarget
) {
770 ParseContext::Scope
& funScope
= functionScope();
771 AddDeclaredNamePtr p
= funScope
.lookupDeclaredNameForAdd(dotNewTarget
);
773 if (!funScope
.addDeclaredName(this, p
, dotNewTarget
, DeclarationKind::Var
,
774 DeclaredNameInfo::npos
)) {
777 funbox
->setFunctionHasNewTargetBinding();
783 bool ParseContext::declareDotGeneratorName() {
784 // The special '.generator' binding must be on the function scope, and must
785 // be marked closed-over, as generators expect to find it on the CallObject.
786 ParseContext::Scope
& funScope
= functionScope();
787 auto dotGenerator
= TaggedParserAtomIndex::WellKnown::dot_generator_();
788 AddDeclaredNamePtr p
= funScope
.lookupDeclaredNameForAdd(dotGenerator
);
790 if (!funScope
.addDeclaredName(this, p
, dotGenerator
, DeclarationKind::Var
,
791 DeclaredNameInfo::npos
, ClosedOver::Yes
)) {
798 bool ParseContext::declareTopLevelDotGeneratorName() {
799 // Provide a .generator binding on the module scope for compatibility with
800 // generator code, which expect to find it on the CallObject for normal
803 sc()->isModuleContext(),
804 "Tried to declare top level dot generator in a non-module context.");
805 ParseContext::Scope
& modScope
= varScope();
806 auto dotGenerator
= TaggedParserAtomIndex::WellKnown::dot_generator_();
807 AddDeclaredNamePtr p
= modScope
.lookupDeclaredNameForAdd(dotGenerator
);
809 modScope
.addDeclaredName(this, p
, dotGenerator
, DeclarationKind::Var
,
810 DeclaredNameInfo::npos
, ClosedOver::Yes
);
813 } // namespace frontend