v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
scopes.h
Go to the documentation of this file.
1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_AST_SCOPES_H_
6#define V8_AST_SCOPES_H_
7
8#include <numeric>
9
10#include "src/ast/ast.h"
12#include "src/base/hashmap.h"
15#include "src/common/globals.h"
18#include "src/zone/zone.h"
19
20namespace v8 {
21
22namespace internal {
23class Scope;
24} // namespace internal
25
26namespace base {
27template <>
29 static constexpr int kAvailableBits = 1;
30};
31} // namespace base
32
33namespace internal {
34
35class AstNodeFactory;
36class AstValueFactory;
37class AstRawString;
38class Declaration;
39class ParseInfo;
40class Parser;
41class PreparseDataBuilder;
42class SloppyBlockFunctionStatement;
43class Statement;
44class StringSet;
45class VariableProxy;
46
49
50// A hash map to support fast variable declaration and lookup.
51class VariableMap : public ZoneHashMap {
52 public:
53 explicit VariableMap(Zone* zone);
54 VariableMap(const VariableMap& other, Zone* zone);
55
56 VariableMap(VariableMap&& other) V8_NOEXCEPT : ZoneHashMap(std::move(other)) {
57 }
58
60 static_cast<ZoneHashMap&>(*this) = std::move(other);
61 return *this;
62 }
63
64 Variable* Declare(Zone* zone, Scope* scope, const AstRawString* name,
66 InitializationFlag initialization_flag,
67 MaybeAssignedFlag maybe_assigned_flag,
68 IsStaticFlag is_static_flag, bool* was_added);
69
71 void Remove(Variable* var);
72 void Add(Variable* var);
73
74 Zone* zone() const { return allocator().zone(); }
75};
76
77// Global invariants after AST construction: Each reference (i.e. identifier)
78// to a JavaScript variable (including global properties) is represented by a
79// VariableProxy node. Immediately after AST construction and before variable
80// allocation, most VariableProxy nodes are "unresolved", i.e. not bound to a
81// corresponding variable (though some are bound during parse time). Variable
82// allocation binds each unresolved VariableProxy to one Variable and assigns
83// a location. Note that many VariableProxy nodes may refer to the same Java-
84// Script variable.
85
86// JS environments are represented in the parser using Scope, DeclarationScope
87// and ModuleScope. DeclarationScope is used for any scope that hosts 'var'
88// declarations. This includes script, module, eval, varblock, and function
89// scope. ModuleScope further specializes DeclarationScope.
90class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
91 public:
92 // ---------------------------------------------------------------------------
93 // Construction
94
95 Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type);
96
97#ifdef DEBUG
98 // The scope name is only used for printing/debugging.
99 void SetScopeName(const AstRawString* scope_name) {
100 scope_name_ = scope_name;
101 }
102#endif
103
104 // An ID that uniquely identifies this scope within the script. Inner scopes
105 // have a higher ID than their outer scopes. ScopeInfo created from a scope
106 // has the same ID as the scope.
107 int UniqueIdInScript() const;
108
110 const DeclarationScope* AsDeclarationScope() const;
111 ModuleScope* AsModuleScope();
112 const ModuleScope* AsModuleScope() const;
113 ClassScope* AsClassScope();
114 const ClassScope* AsClassScope() const;
115
116 bool is_reparsed() const { return !scope_info_.is_null(); }
117
118 // Re-writes the {VariableLocation} of top-level 'let' bindings from CONTEXT
119 // to REPL_GLOBAL. Should only be called on REPL scripts.
120 void RewriteReplGlobalVariables();
121
122 class Snapshot final {
123 public:
124 inline explicit Snapshot(Scope* scope);
125
126 // Disallow copy and move.
127 Snapshot(const Snapshot&) = delete;
128 Snapshot(Snapshot&&) = delete;
129
131 // Restore eval flags from before the scope was active.
132 if (sloppy_eval_can_extend_vars_) {
133 declaration_scope_->sloppy_eval_can_extend_vars_ = true;
134 }
135 if (calls_eval_) {
136 outer_scope_->calls_eval_ = true;
137 }
138 }
139
140 void Reparent(DeclarationScope* new_parent);
141
142 private:
148 // While the scope is active, the scope caches the flag values for
149 // outer_scope_ / declaration_scope_ they can be used to know what happened
150 // while parsing the arrow head. If this turns out to be an arrow head, new
151 // values on the respective scopes will be cleared and moved to the inner
152 // scope. Otherwise the cached flags will be merged with the flags from the
153 // arrow head.
156 };
157
158 enum class DeserializationMode { kIncludingVariables, kScopesOnly };
159
160 template <typename IsolateT>
162 static Scope* DeserializeScopeChain(IsolateT* isolate, Zone* zone,
163 Tagged<ScopeInfo> scope_info,
164 DeclarationScope* script_scope,
165 AstValueFactory* ast_value_factory,
166 DeserializationMode deserialization_mode,
167 ParseInfo* info = nullptr);
168
169 template <typename IsolateT>
171 static void SetScriptScopeInfo(IsolateT* isolate,
172 DeclarationScope* script_scope);
173
174 // Checks if the block scope is redundant, i.e. it does not contain any
175 // block scoped declarations. In that case it is removed from the scope
176 // tree and its children are reparented.
177 Scope* FinalizeBlockScope();
178
179 Zone* zone() const { return variables_.zone(); }
180
182 if (must_use_preparsed_scope_data_) {
183 return;
184 }
185 must_use_preparsed_scope_data_ = true;
186 if (outer_scope_) {
187 outer_scope_->SetMustUsePreparseData();
188 }
189 }
190
192 return must_use_preparsed_scope_data_;
193 }
194
195 // ---------------------------------------------------------------------------
196 // Declarations
197
198 // Lookup a variable in this scope. Returns the variable or nullptr if not
199 // found.
201 DCHECK(scope_info_.is_null());
202 return variables_.Lookup(name);
203 }
204
205 Variable* LookupInScopeInfo(const AstRawString* name, Scope* cache);
206
207 // Declare a local variable in this scope. If the variable has been
208 // declared before, the previously declared variable is returned.
209 Variable* DeclareLocal(const AstRawString* name, VariableMode mode,
210 VariableKind kind, bool* was_added,
211 InitializationFlag init_flag = kCreatedInitialized);
212
213 Variable* DeclareVariable(Declaration* declaration, const AstRawString* name,
215 InitializationFlag init, bool* was_added,
216 bool* sloppy_mode_block_scope_function_redefinition,
217 bool* ok);
218
219 // Returns nullptr if there was a declaration conflict.
220 Variable* DeclareVariableName(const AstRawString* name, VariableMode mode,
221 bool* was_added,
222 VariableKind kind = NORMAL_VARIABLE);
223 Variable* DeclareCatchVariableName(const AstRawString* name);
224
225 Variable* DeclareHomeObjectVariable(AstValueFactory* ast_value_factory);
226 Variable* DeclareStaticHomeObjectVariable(AstValueFactory* ast_value_factory);
227
228 // Declarations list.
230
232
233 // Create a new unresolved variable.
235 const AstRawString* name, int start_pos,
236 VariableKind kind = NORMAL_VARIABLE) {
237 DCHECK_IMPLIES(already_resolved_, reparsing_for_class_initializer_);
238 DCHECK_EQ(factory->zone(), zone());
239 VariableProxy* proxy = factory->NewVariableProxy(name, kind, start_pos);
240 AddUnresolved(proxy);
241 return proxy;
242 }
243
244 void AddUnresolved(VariableProxy* proxy);
245
246 // Deletes an unresolved variable. The variable proxy cannot be reused for
247 // another list later. During parsing, an unresolved variable may have been
248 // added optimistically, but then only the variable name was used (typically
249 // for labels and arrow function parameters). If the variable was not
250 // declared, the addition introduced a new unresolved variable which may end
251 // up being allocated globally as a "ghost" variable. DeleteUnresolved removes
252 // such a variable again if it was added; otherwise this is a no-op.
253 void DeleteUnresolved(VariableProxy* var);
254
255 // Creates a new temporary variable in this scope's TemporaryScope. The
256 // name is only used for printing and cannot be used to find the variable.
257 // In particular, the only way to get hold of the temporary is by keeping the
258 // Variable* around. The name should not clash with a legitimate variable
259 // names.
260 // TODO(verwaest): Move to DeclarationScope?
261 Variable* NewTemporary(const AstRawString* name);
262
263 // Find variable with (variable->mode() <= |mode_limit|) that was declared in
264 // |scope|. This is used to catch patterns like `try{}catch(e){let e;}` and
265 // function([e]) { let e }, which are errors even though the two 'e's are each
266 // time declared in different scopes. Returns the first duplicate variable
267 // name if there is one, nullptr otherwise.
268 const AstRawString* FindVariableDeclaredIn(Scope* scope,
269 VariableMode mode_limit);
270
271 // ---------------------------------------------------------------------------
272 // Scope-specific info.
273
274 // Inform the scope and outer scopes that the corresponding code contains an
275 // eval call.
276 inline void RecordEvalCall();
277
279 inner_scope_calls_eval_ = true;
280 for (Scope* scope = outer_scope(); scope != nullptr;
281 scope = scope->outer_scope()) {
282 if (scope->inner_scope_calls_eval_) return;
283 scope->inner_scope_calls_eval_ = true;
284 }
285 }
286
287 // Set the language mode flag (unless disabled by a global flag).
288 void SetLanguageMode(LanguageMode language_mode) {
289 DCHECK(!is_module_scope() || is_strict(language_mode));
290 set_language_mode(language_mode);
291 }
292
293 // Inform the scope that the scope may execute declarations nonlinearly.
294 // Currently, the only nonlinear scope is a switch statement. The name is
295 // more general in case something else comes up with similar control flow,
296 // for example the ability to break out of something which does not have
297 // its own lexical scope.
298 // The bit does not need to be stored on the ScopeInfo because none of
299 // the three compilers will perform hole check elimination on a variable
300 // located in VariableLocation::CONTEXT. So, direct eval and closures
301 // will not expose holes.
302 void SetNonlinear() { scope_nonlinear_ = true; }
303
304 // Position in the source where this scope begins and ends.
305 //
306 // * For the scope of a with statement
307 // with (obj) stmt
308 // start position: start position of first token of 'stmt'
309 // end position: end position of last token of 'stmt'
310 // * For the scope of a block
311 // { stmts }
312 // start position: start position of '{'
313 // end position: end position of '}'
314 // * For the scope of a function literal or decalaration
315 // function fun(a,b) { stmts }
316 // start position: start position of '('
317 // end position: end position of '}'
318 // * For the scope of a catch block
319 // try { stms } catch(e) { stmts }
320 // start position: start position of '('
321 // end position: end position of ')'
322 // * For the scope of a for-statement
323 // for (let x ...) stmt
324 // start position: start position of '('
325 // end position: end position of last token of 'stmt'
326 // * For the scope of a switch statement
327 // switch (tag) { cases }
328 // start position: start position of '{'
329 // end position: end position of '}'
330 // * For the scope of a class literal or declaration
331 // class A extends B { body }
332 // start position: start position of 'class'
333 // end position: end position of '}'
334 // * For the scope of a class member initializer functions:
335 // class A extends B { body }
336 // start position: start position of '{'
337 // end position: end position of '}'
338 int start_position() const { return start_position_; }
339 void set_start_position(int statement_pos) {
340 start_position_ = statement_pos;
341 }
342 int end_position() const { return end_position_; }
343 void set_end_position(int statement_pos) { end_position_ = statement_pos; }
344
345 // Scopes created for desugaring are hidden. I.e. not visible to the debugger.
346 bool is_hidden() const { return is_hidden_; }
347 void set_is_hidden() { is_hidden_ = true; }
348
350 DCHECK(!already_resolved_);
351 force_context_allocation_for_parameters_ = true;
352 }
354 return force_context_allocation_for_parameters_;
355 }
356
357 // ---------------------------------------------------------------------------
358 // Predicates.
359
360 // Specific scope types.
361 bool is_eval_scope() const { return scope_type_ == EVAL_SCOPE; }
362 bool is_function_scope() const { return scope_type_ == FUNCTION_SCOPE; }
363 bool is_module_scope() const { return scope_type_ == MODULE_SCOPE; }
364 bool is_script_scope() const {
365 return scope_type_ == SCRIPT_SCOPE || scope_type_ == REPL_MODE_SCOPE;
366 }
367 bool is_catch_scope() const { return scope_type_ == CATCH_SCOPE; }
368 bool is_block_scope() const {
369 return scope_type_ == BLOCK_SCOPE || scope_type_ == CLASS_SCOPE;
370 }
371 bool is_with_scope() const { return scope_type_ == WITH_SCOPE; }
372 bool is_declaration_scope() const { return is_declaration_scope_; }
373 bool is_class_scope() const { return scope_type_ == CLASS_SCOPE; }
374 bool is_home_object_scope() const {
375 return is_class_scope() ||
376 (is_block_scope() && is_block_scope_for_object_literal_);
377 }
379 DCHECK_IMPLIES(is_block_scope_for_object_literal_, is_block_scope());
380 return is_block_scope_for_object_literal_;
381 }
383 DCHECK(is_block_scope());
384 is_block_scope_for_object_literal_ = true;
385 }
386
387 bool inner_scope_calls_eval() const { return inner_scope_calls_eval_; }
389 return private_name_lookup_skips_outer_class_;
390 }
391
392 bool has_using_declaration() const { return has_using_declaration_; }
394 return has_await_using_declaration_;
395 }
396
397 bool is_wrapped_function() const {
398 DCHECK_IMPLIES(is_wrapped_function_, is_function_scope());
399 return is_wrapped_function_;
400 }
402 DCHECK(is_function_scope());
403 is_wrapped_function_ = true;
404 }
405
406#if V8_ENABLE_WEBASSEMBLY
407 bool IsAsmModule() const;
408 // Returns true if this scope or any inner scopes that might be eagerly
409 // compiled are asm modules.
410 bool ContainsAsmModule() const;
411#endif // V8_ENABLE_WEBASSEMBLY
412
413 // Does this scope have the potential to execute declarations non-linearly?
414 bool is_nonlinear() const { return scope_nonlinear_; }
415 // Returns if we need to force a context because the current scope is stricter
416 // than the outerscope. We need this to properly track the language mode using
417 // the context. This is required in ICs where we lookup the language mode
418 // from the context.
420 // For function scopes we need not force a context since the language mode
421 // can be obtained from the closure. Script scopes always have a context.
422 if (scope_type_ == FUNCTION_SCOPE || is_script_scope()) {
423 return false;
424 }
425 DCHECK_NOT_NULL(outer_scope_);
426 return (language_mode() > outer_scope_->language_mode());
427 }
428
429 // Whether this needs to be represented by a runtime context.
430 bool NeedsContext() const {
431 // Catch scopes always have heap slots.
432 DCHECK_IMPLIES(is_catch_scope(), num_heap_slots() > 0);
433 DCHECK_IMPLIES(is_with_scope(), num_heap_slots() > 0);
434 DCHECK_IMPLIES(ForceContextForLanguageMode(), num_heap_slots() > 0);
435 return num_heap_slots() > 0;
436 }
437
438 // Use Scope::ForEach for depth first traversal of scopes.
439 // Before:
440 // void Scope::VisitRecursively() {
441 // DoSomething();
442 // for (Scope* s = inner_scope_; s != nullptr; s = s->sibling_) {
443 // if (s->ShouldContinue()) continue;
444 // s->VisitRecursively();
445 // }
446 // }
447 //
448 // After:
449 // void Scope::VisitIteratively() {
450 // this->ForEach([](Scope* s) {
451 // s->DoSomething();
452 // return s->ShouldContinue() ? kContinue : kDescend;
453 // });
454 // }
455 template <typename FunctionType>
456 V8_INLINE void ForEach(FunctionType callback);
458 // Continue the iteration on the same level, do not recurse/descent into
459 // inner scopes.
461 // Recurse/descend into inner scopes.
462 kDescend
463 };
464
465 bool IsConstructorScope() const;
466
467 // Check is this scope is an outer scope of the given scope.
468 bool IsOuterScopeOf(Scope* other) const;
469
470 // ---------------------------------------------------------------------------
471 // Accessors.
472
473 // The type of this scope.
474 ScopeType scope_type() const { return scope_type_; }
475
476 // The language mode of this scope.
478 return is_strict_ ? LanguageMode::kStrict : LanguageMode::kSloppy;
479 }
480
481 // inner_scope() and sibling() together implement the inner scope list of a
482 // scope. Inner scope points to the an inner scope of the function, and
483 // "sibling" points to a next inner scope of the outer scope of this scope.
484 Scope* inner_scope() const { return inner_scope_; }
485 Scope* sibling() const { return sibling_; }
486
487 // The scope immediately surrounding this scope, or nullptr.
488 Scope* outer_scope() const { return outer_scope_; }
489
491 DCHECK(is_catch_scope());
492 DCHECK_EQ(1, num_var());
493 return static_cast<Variable*>(variables_.Start()->value);
494 }
495
496 bool ShouldBanArguments();
497
498 // ---------------------------------------------------------------------------
499 // Variable allocation.
500
501 // Result of variable allocation.
502 int num_stack_slots() const { return num_stack_slots_; }
503 int num_heap_slots() const { return num_heap_slots_; }
504
506 switch (scope_type_) {
507 case MODULE_SCOPE:
508 case WITH_SCOPE: // DebugEvaluateContext as well
509 case SCRIPT_SCOPE: // Side data for const tracking let.
510 case REPL_MODE_SCOPE:
511 return true;
512 default:
513 DCHECK_IMPLIES(sloppy_eval_can_extend_vars_,
514 scope_type_ == FUNCTION_SCOPE ||
515 scope_type_ == EVAL_SCOPE ||
516 scope_type_ == BLOCK_SCOPE);
517 DCHECK_IMPLIES(sloppy_eval_can_extend_vars_, is_declaration_scope());
518 return sloppy_eval_can_extend_vars_;
519 }
520 UNREACHABLE();
521 }
523 return HasContextExtensionSlot() ? Context::MIN_CONTEXT_EXTENDED_SLOTS
524 : Context::MIN_CONTEXT_SLOTS;
525 }
526
527 int ContextLocalCount() const;
528
529 // Determine if we can parse a function literal in this scope lazily without
530 // caring about the unresolved variables within.
531 bool AllowsLazyParsingWithoutUnresolvedVariables(const Scope* outer) const;
532
533 // The number of contexts between this and scope; zero if this == scope.
534 int ContextChainLength(Scope* scope) const;
535
536 // The number of contexts between this and the outermost context that has a
537 // sloppy eval call. One if this->sloppy_eval_can_extend_vars().
538 int ContextChainLengthUntilOutermostSloppyEval() const;
539
540 // Find the first function, script, eval or (declaration) block scope. This is
541 // the scope where var declarations will be hoisted to in the implementation.
542 DeclarationScope* GetDeclarationScope();
543
544 // Find the first function, script, or (declaration) block scope.
545 // This is the scope where var declarations will be hoisted to in the
546 // implementation, including vars in direct sloppy eval calls.
547 //
548 // TODO(leszeks): Check how often we skip eval scopes in GetDeclarationScope,
549 // and possibly merge this with GetDeclarationScope.
550 DeclarationScope* GetNonEvalDeclarationScope();
551
552 // Find the first non-block declaration scope. This should be either a script,
553 // function, or eval scope. Same as DeclarationScope(), but skips declaration
554 // "block" scopes. Used for differentiating associated function objects (i.e.,
555 // the scope for which a function prologue allocates a context) or declaring
556 // temporaries.
557 DeclarationScope* GetClosureScope();
558 const DeclarationScope* GetClosureScope() const;
559
560 // Find the first (non-arrow) function or script scope. This is where
561 // 'this' is bound, and what determines the function kind.
562 DeclarationScope* GetReceiverScope();
563
564 // Find the first constructor scope. Its outer scope is where the instance
565 // members that should be initialized right after super() is called
566 // are declared.
567 DeclarationScope* GetConstructorScope();
568
569 // Find the first class scope or object literal block scope. This is where
570 // 'super' is bound.
571 Scope* GetHomeObjectScope();
572
573 DeclarationScope* GetScriptScope();
574
575 // Find the innermost outer scope that needs a context.
576 Scope* GetOuterScopeWithContext();
577
578 bool HasReceiverToDeserialize() const;
579 bool HasThisReference() const;
580 // Analyze() must have been called once to create the ScopeInfo.
582 DCHECK(!scope_info_.is_null());
583 return scope_info_;
584 }
585
586 int num_var() const { return variables_.occupancy(); }
587
588 // ---------------------------------------------------------------------------
589 // Debugging.
590
591#ifdef DEBUG
592 void Print(int n = 0); // n = indentation; n < 0 => don't print recursively
593
594 // Check that the scope has positions assigned.
595 void CheckScopePositions();
596
597 // Check that all Scopes in the scope tree use the same Zone.
598 void CheckZones();
599
600 void MarkReparsingForClassInitializer() {
601 reparsing_for_class_initializer_ = true;
602 }
603#endif
604
605 // Retrieve `IsSimpleParameterList` of current or outer function.
606 bool HasSimpleParameters();
607 void set_is_debug_evaluate_scope() { is_debug_evaluate_scope_ = true; }
608 bool is_debug_evaluate_scope() const { return is_debug_evaluate_scope_; }
609 bool IsSkippableFunctionScope();
610 bool is_repl_mode_scope() const { return scope_type_ == REPL_MODE_SCOPE; }
611
612 bool needs_home_object() const {
613 DCHECK(is_home_object_scope());
614 return needs_home_object_;
615 }
616
618 DCHECK(is_home_object_scope());
619 needs_home_object_ = true;
620 }
621
622 bool RemoveInnerScope(Scope* inner_scope) {
623 DCHECK_NOT_NULL(inner_scope);
624 if (inner_scope == inner_scope_) {
625 inner_scope_ = inner_scope_->sibling_;
626 return true;
627 }
628 for (Scope* scope = inner_scope_; scope != nullptr;
629 scope = scope->sibling_) {
630 if (scope->sibling_ == inner_scope) {
631 scope->sibling_ = scope->sibling_->sibling_;
632 return true;
633 }
634 }
635 return false;
636 }
637
639 Variable* var = variables_.Lookup(name);
640 if (var != nullptr || scope_info_.is_null()) return var;
641 return LookupInScopeInfo(name, cache);
642 }
643
645 for (Scope* scope = this; scope != nullptr; scope = scope->outer_scope()) {
646 Variable* var = scope->LookupInScopeOrScopeInfo(name, scope);
647 if (var != nullptr) return var;
648 }
649 return nullptr;
650 }
651
652 void ForceDynamicLookup(VariableProxy* proxy);
653
654 protected:
655 Scope(Zone* zone, ScopeType scope_type);
656
657 void set_language_mode(LanguageMode language_mode) {
658 is_strict_ = is_strict(language_mode);
659 }
660
661 private:
662 Variable* Declare(Zone* zone, const AstRawString* name, VariableMode mode,
663 VariableKind kind, InitializationFlag initialization_flag,
664 MaybeAssignedFlag maybe_assigned_flag, bool* was_added) {
665 // Static variables can only be declared using ClassScope methods.
666 Variable* result = variables_.Declare(
667 zone, this, name, mode, kind, initialization_flag, maybe_assigned_flag,
668 IsStaticFlag::kNotStatic, was_added);
669 if (mode == VariableMode::kUsing) has_using_declaration_ = true;
670 if (mode == VariableMode::kAwaitUsing) has_await_using_declaration_ = true;
671 if (*was_added) locals_.Add(result);
672 return result;
673 }
674
675 // This method should only be invoked on scopes created during parsing (i.e.,
676 // not deserialized from a context). Also, since NeedsContext() is only
677 // returning a valid result after variables are resolved, NeedsScopeInfo()
678 // should also be invoked after resolution.
679 bool NeedsScopeInfo() const;
680
681 Variable* NewTemporary(const AstRawString* name,
682 MaybeAssignedFlag maybe_assigned);
683
684 // Walk the scope chain to find DeclarationScopes; call
685 // SavePreparseDataForDeclarationScope for each.
686 void SavePreparseData(Parser* parser);
687
688 // Create a non-local variable with a given name.
689 // These variables are looked up dynamically at runtime.
690 Variable* NonLocal(const AstRawString* name, VariableMode mode);
691
696
697 // Variable resolution.
698 // Lookup a variable reference given by name starting with this scope, and
699 // stopping when reaching the outer_scope_end scope. If the code is executed
700 // because of a call to 'eval', the context parameter should be set to the
701 // calling context of 'eval'.
702 template <ScopeLookupMode mode>
703 static Variable* Lookup(VariableProxy* proxy, Scope* scope,
704 Scope* outer_scope_end, Scope* cache_scope = nullptr,
705 bool force_context_allocation = false);
706 static Variable* LookupWith(VariableProxy* proxy, Scope* scope,
707 Scope* outer_scope_end, Scope* cache_scope,
708 bool force_context_allocation);
709 static Variable* LookupSloppyEval(VariableProxy* proxy, Scope* scope,
710 Scope* outer_scope_end, Scope* cache_scope,
711 bool force_context_allocation);
712 static void ResolvePreparsedVariable(VariableProxy* proxy, Scope* scope,
713 Scope* end);
714 void ResolveTo(VariableProxy* proxy, Variable* var);
715 void ResolveVariable(VariableProxy* proxy);
716 V8_WARN_UNUSED_RESULT bool ResolveVariablesRecursively(Scope* end);
717
718 // Finds free variables of this scope. This mutates the unresolved variables
719 // list along the way, so full resolution cannot be done afterwards.
720 void AnalyzePartially(DeclarationScope* max_outer_scope,
721 AstNodeFactory* ast_node_factory,
722 UnresolvedList* new_unresolved_list,
723 bool maybe_in_arrowhead);
724
725 // Predicates.
726 bool MustAllocate(Variable* var);
727 bool MustAllocateInContext(Variable* var);
728
729 // Variable allocation.
730 void AllocateStackSlot(Variable* var);
731 V8_INLINE void AllocateHeapSlot(Variable* var);
732 void AllocateNonParameterLocal(Variable* var);
734 V8_INLINE void AllocateNonParameterLocalsAndDeclaredGlobals();
735 void AllocateVariablesRecursively();
736
737 template <typename IsolateT>
739 IsolateT* isolate, MaybeHandle<ScopeInfo> outer_scope,
740 std::unordered_map<int, IndirectHandle<ScopeInfo>>& scope_infos_to_reuse);
741
742 // Construct a scope based on the scope info.
743 Scope(Zone* zone, ScopeType type, AstValueFactory* ast_value_factory,
744 Handle<ScopeInfo> scope_info);
745
746 // Construct a catch scope with a binding for the name.
747 Scope(Zone* zone, const AstRawString* catch_variable_name,
748 MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info);
749
750 void AddInnerScope(Scope* inner_scope) {
751 inner_scope->sibling_ = inner_scope_;
752 inner_scope_ = inner_scope;
753 inner_scope->outer_scope_ = this;
754 }
755
756 void SetDefaults();
757
758 friend class DeclarationScope;
759 friend class ClassScope;
760 friend class ScopeTestHelper;
761 friend Zone;
762
763 // Scope tree.
764 Scope* outer_scope_; // the immediately enclosing outer scope, or nullptr
765 Scope* inner_scope_; // an inner scope of this scope
766 Scope* sibling_; // a sibling inner scope of the outer scope of this scope.
767
768 // The variables declared in this scope:
769 //
770 // All user-declared variables (incl. parameters). For script scopes
771 // variables may be implicitly 'declared' by being used (possibly in
772 // an inner scope) with no intervening with statements or eval calls.
774 // In case of non-scopeinfo-backed scopes, this contains the variables of the
775 // map above in order of addition.
777 // Unresolved variables referred to from this scope. The proxies themselves
778 // form a linked list of all unresolved proxies.
780 // Declarations.
782
783 // Serialized scope info support.
785// Debugging support.
786#ifdef DEBUG
787 const AstRawString* scope_name_;
788
789 // True if it doesn't need scope resolution (e.g., if the scope was
790 // constructed based on a serialized scope info or a catch context).
791 bool already_resolved_;
792 bool reparsing_for_class_initializer_;
793 // True if this scope may contain objects from a temp zone that needs to be
794 // fixed up.
795 bool needs_migration_;
796#endif
797
798 // Source positions.
801
802 // Computed via AllocateVariables.
805
806 // The scope type.
808
809 // Scope-specific information computed during parsing.
810 //
811 // The language mode of this scope.
812 static_assert(LanguageModeSize == 2);
813 bool is_strict_ : 1;
814 // This scope contains an 'eval' call.
815 bool calls_eval_ : 1;
816 // The context associated with this scope can be extended by a sloppy eval
817 // called inside of it.
819 // This scope's declarations might not be executed in order (e.g., switch).
821 bool is_hidden_ : 1;
822 // Temporary workaround that allows masking of 'this' in debug-evaluate
823 // scopes.
825
826 // True if one of the inner scopes or the scope itself calls eval.
829
830 // True if it holds 'var' declarations.
832
833 // True if the outer scope is a class scope and should be skipped when
834 // resolving private names, i.e. if the scope is in a class heritage
835 // expression.
837
839
842
843 // If declarations include any `using` or `await using` declarations.
846
847 // If the scope was generated for wrapped function syntax, which will affect
848 // its UniqueIdInScript.
850};
851
853 public:
854 DeclarationScope(Zone* zone, Scope* outer_scope, ScopeType scope_type,
855 FunctionKind function_kind = FunctionKind::kNormalFunction);
856 DeclarationScope(Zone* zone, ScopeType scope_type,
857 AstValueFactory* ast_value_factory,
858 Handle<ScopeInfo> scope_info);
859 // Creates a script scope.
860 DeclarationScope(Zone* zone, AstValueFactory* ast_value_factory,
861 REPLMode repl_mode = REPLMode::kNo);
862
863 FunctionKind function_kind() const { return function_kind_; }
864
865 // Inform the scope that the corresponding code uses "super".
867 DCHECK(IsConciseMethod(function_kind()) ||
868 IsAccessorFunction(function_kind()) ||
869 IsClassConstructor(function_kind()));
870 uses_super_property_ = true;
871 Scope* home_object_scope = GetHomeObjectScope();
872 DCHECK_NOT_NULL(home_object_scope);
873 home_object_scope->set_needs_home_object();
874 }
875
876 bool uses_super_property() const { return uses_super_property_; }
877
878 void TakeUnresolvedReferencesFromParent();
879
880 bool is_arrow_scope() const {
881 return is_function_scope() && IsArrowFunction(function_kind_);
882 }
883
884 // Inform the scope and outer scopes that the corresponding code contains an
885 // eval call.
887 calls_eval_ = true;
888
889 // The caller already checked whether we're in sloppy mode.
890 CHECK(is_sloppy(language_mode()));
891
892 // Sloppy eval in script scopes can only introduce global variables anyway,
893 // so we don't care that it calls sloppy eval.
894 if (is_script_scope()) return;
895
896 // Sloppy eval in an eval scope can only introduce variables into the outer
897 // (non-eval) declaration scope, not into this eval scope.
898 if (is_eval_scope()) {
899#ifdef DEBUG
900 // One of three things must be true:
901 // 1. The outer non-eval declaration scope should already be marked as
902 // being extendable by sloppy eval, by the current sloppy eval rather
903 // than the inner one,
904 // 2. The outer non-eval declaration scope is a script scope and thus
905 // isn't extendable anyway, or
906 // 3. This is a debug evaluate and all bets are off.
907 DeclarationScope* outer_decl_scope = outer_scope()->GetDeclarationScope();
908 while (outer_decl_scope->is_eval_scope()) {
909 outer_decl_scope = outer_decl_scope->GetDeclarationScope();
910 }
911 if (outer_decl_scope->is_debug_evaluate_scope()) {
912 // Don't check anything.
913 // TODO(9662): Figure out where variables declared by an eval inside a
914 // debug-evaluate actually go.
915 } else if (!outer_decl_scope->is_script_scope()) {
916 DCHECK(outer_decl_scope->sloppy_eval_can_extend_vars_);
917 }
918#endif
919
920 return;
921 }
922
923 sloppy_eval_can_extend_vars_ = true;
924 }
925
927 return sloppy_eval_can_extend_vars_;
928 }
929
930 bool was_lazily_parsed() const { return was_lazily_parsed_; }
931
933 DCHECK(is_module_scope());
934 Variable* var = variables_.Lookup(name);
935 DCHECK_NOT_NULL(var);
936 return var;
937 }
938
939 void DeserializeReceiver(AstValueFactory* ast_value_factory);
940
941#ifdef DEBUG
942 void set_is_being_lazily_parsed(bool is_being_lazily_parsed) {
943 is_being_lazily_parsed_ = is_being_lazily_parsed;
944 }
945 bool is_being_lazily_parsed() const { return is_being_lazily_parsed_; }
946#endif
947
948 void set_zone(Zone* zone) {
949#ifdef DEBUG
950 needs_migration_ = true;
951#endif
952 // Migrate variables_' backing store to new zone.
953 variables_ = VariableMap(variables_, zone);
954 }
955
956 // ---------------------------------------------------------------------------
957 // Illegal redeclaration support.
958
959 // Check if the scope has conflicting var
960 // declarations, i.e. a var declaration that has been hoisted from a nested
961 // scope over a let binding of the same name.
962 Declaration* CheckConflictingVarDeclarations(
963 bool* allowed_catch_binding_var_redeclaration);
964
965 void set_has_checked_syntax(bool has_checked_syntax) {
966 has_checked_syntax_ = has_checked_syntax;
967 }
968 bool has_checked_syntax() const { return has_checked_syntax_; }
969
970 bool ShouldEagerCompile() const {
971 return force_eager_compilation_ || should_eager_compile_;
972 }
973
974 void set_should_eager_compile();
975
977 DCHECK(is_script_scope());
978 DCHECK(scope_info_.is_null());
979 scope_info_ = scope_info;
980 }
981
982#if V8_ENABLE_WEBASSEMBLY
983 bool is_asm_module() const { return is_asm_module_; }
984 void set_is_asm_module();
985#endif // V8_ENABLE_WEBASSEMBLY
986
987 bool should_ban_arguments() const {
988 return IsClassMembersInitializerFunction(function_kind());
989 }
990
992 DCHECK(IsModule(function_kind_));
993 function_kind_ = FunctionKind::kModuleWithTopLevelAwait;
994 }
995
996 void DeclareThis(AstValueFactory* ast_value_factory);
997 void DeclareArguments(AstValueFactory* ast_value_factory);
998 void DeclareDefaultFunctionVariables(AstValueFactory* ast_value_factory);
999
1000 // Declare the function variable for a function literal. This variable
1001 // is in an intermediate scope between this function scope and the the
1002 // outer scope. Only possible for function scopes; at most one variable.
1003 //
1004 // This function needs to be called after all other variables have been
1005 // declared in the scope. It will add a variable for {name} to {variables_};
1006 // either the function variable itself, or a non-local in case the function
1007 // calls sloppy eval.
1008 Variable* DeclareFunctionVar(const AstRawString* name,
1009 Scope* cache = nullptr);
1010
1011 // Declare some special internal variables which must be accessible to
1012 // Ignition without ScopeInfo.
1013 Variable* DeclareGeneratorObjectVar(const AstRawString* name);
1014
1015 // Declare a parameter in this scope. When there are duplicated
1016 // parameters the rightmost one 'wins'. However, the implementation
1017 // expects all parameters to be declared and from left to right.
1018 Variable* DeclareParameter(const AstRawString* name, VariableMode mode,
1019 bool is_optional, bool is_rest,
1020 AstValueFactory* ast_value_factory, int position);
1021
1022 // Makes sure that num_parameters_ and has_rest is correct for the preparser.
1023 void RecordParameter(bool is_rest);
1024
1025 // Declare an implicit global variable in this scope which must be a
1026 // script scope. The variable was introduced (possibly from an inner
1027 // scope) by a reference to an unresolved variable with no intervening
1028 // with statements or eval calls.
1029 Variable* DeclareDynamicGlobal(const AstRawString* name,
1030 VariableKind variable_kind, Scope* cache);
1031
1032 // The variable corresponding to the 'this' value.
1034 DCHECK(has_this_declaration() || is_script_scope());
1036 return receiver_;
1037 }
1038
1039 bool has_this_declaration() const { return has_this_declaration_; }
1040
1041 // The variable corresponding to the 'new.target' value.
1042 Variable* new_target_var() { return new_target_; }
1043
1044 // The variable holding the function literal for named function
1045 // literals, or nullptr. Only valid for function scopes.
1046 Variable* function_var() const { return function_; }
1047
1048 // The variable holding the JSGeneratorObject for generator, async
1049 // and async generator functions, and modules. Only valid for
1050 // function, module and REPL mode script scopes.
1052 DCHECK(is_function_scope() || is_module_scope() || is_repl_mode_scope());
1053 return GetRareVariable(RareVariable::kGeneratorObject);
1054 }
1055
1056 // Parameters. The left-most parameter has index 0.
1057 // Only valid for function and module scopes.
1058 Variable* parameter(int index) const {
1059 DCHECK(is_function_scope() || is_module_scope());
1060 DCHECK(!is_being_lazily_parsed_);
1061 return params_[index];
1062 }
1063
1064 // Returns the number of formal parameters, excluding a possible rest
1065 // parameter. Examples:
1066 // function foo(a, b) {} ==> 2
1067 // function foo(a, b, ...c) {} ==> 2
1068 // function foo(a, b, c = 1) {} ==> 3
1069 int num_parameters() const { return num_parameters_; }
1070
1071 // The function's rest parameter (nullptr if there is none).
1073 return has_rest_ ? params_[params_.length() - 1] : nullptr;
1074 }
1075
1076 bool has_simple_parameters() const { return has_simple_parameters_; }
1077
1078 // TODO(caitp): manage this state in a better way. PreParser must be able to
1079 // communicate that the scope is non-simple, without allocating any parameters
1080 // as the Parser does. This is necessary to ensure that TC39's proposed early
1081 // error can be reported consistently regardless of whether lazily parsed or
1082 // not.
1084 DCHECK(is_function_scope());
1085 has_simple_parameters_ = false;
1086 }
1087
1089 SetHasNonSimpleParameters();
1090 for (ZoneHashMap::Entry* p = variables_.Start(); p != nullptr;
1091 p = variables_.Next(p)) {
1092 Variable* var = reinterpret_cast<Variable*>(p->value);
1093 if (var->is_parameter()) var->MakeParameterNonSimple();
1094 }
1095 }
1096
1097 // Returns whether the arguments object aliases formal parameters.
1099 DCHECK(is_function_scope());
1100 DCHECK(!is_arrow_scope());
1102 return is_sloppy(language_mode()) && has_simple_parameters()
1103 ? CreateArgumentsType::kMappedArguments
1104 : CreateArgumentsType::kUnmappedArguments;
1105 }
1106
1107 // The local variable 'arguments' if we need to allocate it; nullptr
1108 // otherwise.
1110 DCHECK_IMPLIES(is_arrow_scope(), arguments_ == nullptr);
1111 return arguments_;
1112 }
1113
1115 Variable* this_function = GetRareVariable(RareVariable::kThisFunction);
1116
1117 // This is only used in derived constructors atm.
1118 DCHECK(this_function == nullptr ||
1119 (is_function_scope() && (IsClassConstructor(function_kind()) ||
1120 IsConciseMethod(function_kind()) ||
1121 IsAccessorFunction(function_kind()))));
1122 return this_function;
1123 }
1124
1125 // Adds a local variable in this scope's locals list. This is for adjusting
1126 // the scope of temporaries and do-expression vars when desugaring parameter
1127 // initializers.
1128 void AddLocal(Variable* var);
1129
1130 void DeclareSloppyBlockFunction(
1131 SloppyBlockFunctionStatement* sloppy_block_function);
1132
1133 // Go through sloppy_block_functions_ and hoist those (into this scope)
1134 // which should be hoisted.
1135 void HoistSloppyBlockFunctions(AstNodeFactory* factory);
1136
1137 // Compute top scope and allocate variables. For lazy compilation the top
1138 // scope only contains the single lazily compiled function, so this
1139 // doesn't re-allocate variables repeatedly.
1140 //
1141 // Returns false if private names can not be resolved and
1142 // ParseInfo's pending_error_handler will be populated with an
1143 // error. Otherwise, returns true.
1145 static bool Analyze(ParseInfo* info);
1146
1147 // To be called during parsing. Do just enough scope analysis that we can
1148 // discard the Scope contents for lazily compiled functions. In particular,
1149 // this records variables which cannot be resolved inside the Scope (we don't
1150 // yet know what they will resolve to since the outer Scopes are incomplete)
1151 // and recreates them with the correct Zone with ast_node_factory.
1152 void AnalyzePartially(Parser* parser, AstNodeFactory* ast_node_factory,
1153 bool maybe_in_arrowhead);
1154
1155 // Allocate ScopeInfos for top scope and any inner scopes that need them.
1156 // Does nothing if ScopeInfo is already allocated.
1157 template <typename IsolateT>
1159 DirectHandle<Script> script,
1160 IsolateT* isolate);
1161
1162 // Determine if we can use lazy compilation for this scope.
1163 bool AllowsLazyCompilation() const;
1164
1165 // Make sure this closure and all outer closures are eagerly compiled.
1167 DCHECK_EQ(this, GetClosureScope());
1169 for (s = this; !s->is_script_scope();
1170 s = s->outer_scope()->GetClosureScope()) {
1171 s->force_eager_compilation_ = true;
1172 }
1173 s->force_eager_compilation_ = true;
1174 }
1175
1176#ifdef DEBUG
1177 void PrintParameters();
1178#endif
1179
1180 V8_INLINE void AllocateLocals();
1181 V8_INLINE void AllocateParameterLocals();
1182 V8_INLINE void AllocateReceiver();
1183
1184 void ResetAfterPreparsing(AstValueFactory* ast_value_factory, bool aborted);
1185
1186 bool is_skipped_function() const { return is_skipped_function_; }
1187 void set_is_skipped_function(bool is_skipped_function) {
1188 is_skipped_function_ = is_skipped_function;
1189 }
1190
1192 return has_inferred_function_name_;
1193 }
1195 DCHECK(is_function_scope());
1196 has_inferred_function_name_ = value;
1197 }
1198
1199 // Save data describing the context allocation of the variables in this scope
1200 // and its subscopes (except scopes at the laziness boundary). The data is
1201 // saved in produced_preparse_data_.
1202 void SavePreparseDataForDeclarationScope(Parser* parser);
1203
1204 void set_preparse_data_builder(PreparseDataBuilder* preparse_data_builder) {
1205 preparse_data_builder_ = preparse_data_builder;
1206 }
1207
1209 return preparse_data_builder_;
1210 }
1211
1212 void set_has_this_reference() { has_this_reference_ = true; }
1213 bool has_this_reference() const { return has_this_reference_; }
1214 void UsesThis() {
1215 set_has_this_reference();
1216 GetReceiverScope()->receiver()->ForceContextAllocation();
1217 }
1218
1220 return needs_private_name_context_chain_recalc_;
1221 }
1222 void RecordNeedsPrivateNameContextChainRecalc();
1223
1225 class_scope_has_private_brand_ = value;
1226 }
1228 return class_scope_has_private_brand_;
1229 }
1230
1231 private:
1232 V8_INLINE void AllocateParameter(Variable* var, int index);
1233
1234 // Resolve and fill in the allocation information for all variables
1235 // in this scopes. Must be called *after* all scopes have been
1236 // processed (parsed) to ensure that unresolved variables can be
1237 // resolved properly.
1238 //
1239 // In the case of code compiled and run using 'eval', the context
1240 // parameter is the context in which eval was called. In all other
1241 // cases the context parameter is an empty handle.
1242 //
1243 // Returns false if private names can not be resolved.
1244 bool AllocateVariables(ParseInfo* info);
1245
1246 void SetDefaults();
1247
1248 // Recalculate the private name context chain from the existing skip bit in
1249 // preparation for AllocateScopeInfos. Because the private name scope is
1250 // implemented with a skip bit for scopes in heritage position, that bit may
1251 // need to be recomputed due scopes that do not need contexts.
1253
1255#if V8_ENABLE_WEBASSEMBLY
1256 // This scope contains an "use asm" annotation.
1257 bool is_asm_module_ : 1;
1258#endif // V8_ENABLE_WEBASSEMBLY
1260 // This function scope has a rest parameter.
1261 bool has_rest_ : 1;
1262 // This scope has a parameter called "arguments".
1264 // This scope uses "super" property ('super.foo').
1267 // Set to true after we have finished lazy parsing the scope.
1269#if DEBUG
1270 bool is_being_lazily_parsed_ : 1;
1271#endif
1279 // If the scope is a function scope, this is the function kind.
1281
1282 int num_parameters_ = 0;
1283
1284 // Parameter list in source order.
1286 // Map of function names to lists of functions defined in sloppy blocks
1288 // Convenience variable.
1290 // Function variable, if any; function scopes only.
1292 // new.target variable, function scopes only.
1294 // Convenience variable; function scopes only.
1296
1297 // For producing the scope allocation data during preparsing.
1299
1300 struct RareData : public ZoneObject {
1301 // Convenience variable; Subclass constructor only
1302 Variable* this_function = nullptr;
1303
1304 // Generator object, if any; generator function scopes and module scopes
1305 // only.
1306 Variable* generator_object = nullptr;
1307 };
1308
1309 enum class RareVariable {
1310 kThisFunction = offsetof(RareData, this_function),
1311 kGeneratorObject = offsetof(RareData, generator_object),
1312 };
1313
1315 if (rare_data_ == nullptr) {
1316 rare_data_ = zone()->New<RareData>();
1317 }
1318 return rare_data_;
1319 }
1320
1322 if (rare_data_ == nullptr) return nullptr;
1323 return *reinterpret_cast<Variable**>(
1324 reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id));
1325 }
1326
1327 // Set `var` to null if it's non-null and Predicate (Variable*) -> bool
1328 // returns true.
1329 template <typename Predicate>
1330 V8_INLINE void NullifyRareVariableIf(RareVariable id, Predicate predicate) {
1331 if (V8_LIKELY(rare_data_ == nullptr)) return;
1332 Variable** var = reinterpret_cast<Variable**>(
1333 reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id));
1334 if (*var && predicate(*var)) *var = nullptr;
1335 }
1336
1337 RareData* rare_data_ = nullptr;
1338};
1339
1341 calls_eval_ = true;
1342 if (is_sloppy(language_mode())) {
1344 }
1346 // The eval contents might access "super" (if it's inside a function that
1347 // binds super).
1348 DeclarationScope* receiver_scope = GetReceiverScope();
1349 DCHECK(!receiver_scope->is_arrow_scope());
1350 FunctionKind function_kind = receiver_scope->function_kind();
1351 if (BindsSuper(function_kind)) {
1352 receiver_scope->RecordSuperPropertyUsage();
1353 }
1354}
1355
1357 : outer_scope_(scope),
1358 declaration_scope_(scope->GetDeclarationScope()),
1359 top_inner_scope_(scope->inner_scope_),
1360 top_unresolved_(scope->unresolved_list_.end()),
1361 top_local_(scope->GetClosureScope()->locals_.end()),
1362 calls_eval_(outer_scope_->calls_eval_),
1363 sloppy_eval_can_extend_vars_(
1364 declaration_scope_->sloppy_eval_can_extend_vars_) {
1365 // Reset in order to record (sloppy) eval calls during this Snapshot's
1366 // lifetime.
1367 outer_scope_->calls_eval_ = false;
1369}
1370
1371class ModuleScope final : public DeclarationScope {
1372 public:
1373 ModuleScope(DeclarationScope* script_scope, AstValueFactory* avfactory);
1374
1375 // Deserialization. Does not restore the module descriptor.
1376 ModuleScope(Handle<ScopeInfo> scope_info, AstValueFactory* avfactory);
1377
1378 // Returns nullptr in a deserialized scope.
1379 SourceTextModuleDescriptor* module() const { return module_descriptor_; }
1380
1381 // Set MODULE as VariableLocation for all variables that will live in a
1382 // module's export table.
1383 void AllocateModuleVariables();
1384
1385 private:
1387};
1388
1390 public:
1391 ClassScope(Zone* zone, Scope* outer_scope, bool is_anonymous);
1392 // Deserialization.
1393 template <typename IsolateT>
1394 ClassScope(IsolateT* isolate, Zone* zone, AstValueFactory* ast_value_factory,
1395 Handle<ScopeInfo> scope_info);
1396
1398 explicit HeritageParsingScope(ClassScope* class_scope)
1399 : class_scope_(class_scope) {
1400 class_scope_->SetIsParsingHeritage(true);
1401 }
1402 ~HeritageParsingScope() { class_scope_->SetIsParsingHeritage(false); }
1403
1404 private:
1406 };
1407
1408 // Declare a private name in the private name map and add it to the
1409 // local variables of this scope.
1410 Variable* DeclarePrivateName(const AstRawString* name, VariableMode mode,
1411 IsStaticFlag is_static_flag, bool* was_added);
1413
1414 // Try resolving all unresolved private names found in the current scope.
1415 // Called from DeclarationScope::AllocateVariables() when reparsing a
1416 // method to generate code or when eval() is called to access private names.
1417 // If there are any private names that cannot be resolved, returns false.
1418 V8_WARN_UNUSED_RESULT bool ResolvePrivateNames(ParseInfo* info);
1419
1420 // Called after the entire class literal is parsed.
1421 // - If we are certain a private name cannot be resolve, return that
1422 // variable proxy.
1423 // - If we find the private name in the scope chain, return nullptr.
1424 // If the name is found in the current class scope, resolve it
1425 // immediately.
1426 // - If we are not sure if the private name can be resolved or not yet,
1427 // return nullptr.
1428 VariableProxy* ResolvePrivateNamesPartially();
1429
1430 // Get the current tail of unresolved private names to be used to
1431 // reset the tail.
1432 UnresolvedList::Iterator GetUnresolvedPrivateNameTail();
1433
1434 // Reset the tail of unresolved private names, discard everything
1435 // between the tail passed into this method and the current tail.
1436 void ResetUnresolvedPrivateNameTail(UnresolvedList::Iterator tail);
1437
1438 // Migrate private names added between the tail passed into this method
1439 // and the current tail.
1440 void MigrateUnresolvedPrivateNameTail(AstNodeFactory* ast_node_factory,
1442 Variable* DeclareBrandVariable(AstValueFactory* ast_value_factory,
1443 IsStaticFlag is_static_flag,
1444 int class_token_pos);
1445
1446 Variable* DeclareClassVariable(AstValueFactory* ast_value_factory,
1447 const AstRawString* name, int class_token_pos);
1448
1450 return GetRareData() == nullptr ? nullptr : GetRareData()->brand;
1451 }
1452
1453 Variable* class_variable() { return class_variable_; }
1454
1456 return rare_data_and_is_parsing_heritage_.GetPayload();
1457 }
1458
1459 // Only maintained when the scope is parsed, not when the scope is
1460 // deserialized.
1462 return has_static_private_methods_;
1463 }
1464
1465 // Returns whether the index of class variable of this class scope should be
1466 // recorded in the ScopeInfo.
1467 // If any inner scope accesses static private names directly, the class
1468 // variable will be forced to be context-allocated.
1469 // The inner scope may also calls eval which may results in access to
1470 // static private names.
1471 // Only maintained when the scope is parsed.
1473 return should_save_class_variable_index_ ||
1474 has_explicit_static_private_methods_access_ ||
1475 (has_static_private_methods_ && inner_scope_calls_eval_);
1476 }
1477
1478 // Only maintained when the scope is parsed.
1479 bool is_anonymous_class() const { return is_anonymous_class_; }
1480
1481 // Overriden during reparsing
1483 should_save_class_variable_index_ = true;
1484 }
1485
1486 private:
1487 friend class Scope;
1489
1490 // Find the private name declared in the private name map first,
1491 // if it cannot be found there, try scope info if there is any.
1492 // Returns nullptr if it cannot be found.
1493 Variable* LookupPrivateName(VariableProxy* proxy);
1494 // Lookup a private name from the local private name map of the current
1495 // scope.
1496 Variable* LookupLocalPrivateName(const AstRawString* name);
1497 // Lookup a private name from the scope info of the current scope.
1498 Variable* LookupPrivateNameInScopeInfo(const AstRawString* name);
1499
1500 struct RareData : public ZoneObject {
1501 explicit RareData(Zone* zone) : private_name_map(zone) {}
1504 Variable* brand = nullptr;
1505 };
1506
1508 return rare_data_and_is_parsing_heritage_.GetPointer();
1509 }
1511 if (GetRareData() == nullptr) {
1512 rare_data_and_is_parsing_heritage_.SetPointer(
1513 zone()->New<RareData>(zone()));
1514 }
1515 return GetRareData();
1516 }
1518 rare_data_and_is_parsing_heritage_.SetPayload(v);
1519 }
1520
1523 Variable* class_variable_ = nullptr;
1524 // These are only maintained when the scope is parsed, not when the
1525 // scope is deserialized.
1528 bool is_anonymous_class_ : 1 = false;
1529 // This is only maintained during reparsing, restored from the
1530 // preparsed data.
1532};
1533
1534// Iterate over the private name scope chain. The iteration proceeds from the
1535// innermost private name scope outwards.
1537 public:
1539
1540 bool Done() const { return current_scope_ == nullptr; }
1541 void Next();
1542
1543 // Add an unresolved private name to the current scope.
1544 void AddUnresolvedPrivateName(VariableProxy* proxy);
1545
1547 DCHECK(!Done());
1548 return current_scope_->AsClassScope();
1549 }
1550
1551 private:
1552 bool skipped_any_scopes_ = false;
1555};
1556
1557} // namespace internal
1558} // namespace v8
1559
1560#endif // V8_AST_SCOPES_H_
Address * arguments_
Builtins::Kind kind
Definition builtins.cc:40
SourcePosition pos
VariableProxy * NewVariableProxy(Variable *var, int start_position=kNoSourcePosition)
Definition ast.h:3299
Zone * zone() const
Definition ast.h:3605
V8_INLINE RareData * EnsureRareData()
Definition scopes.h:1510
bool should_save_class_variable_index() const
Definition scopes.h:1472
bool has_static_private_methods() const
Definition scopes.h:1461
bool has_explicit_static_private_methods_access_
Definition scopes.h:1527
V8_INLINE void SetIsParsingHeritage(bool v)
Definition scopes.h:1517
bool is_anonymous_class() const
Definition scopes.h:1479
Variable * class_variable()
Definition scopes.h:1453
bool should_save_class_variable_index_
Definition scopes.h:1531
base::PointerWithPayload< RareData, bool, 1 > rare_data_and_is_parsing_heritage_
Definition scopes.h:1522
void set_should_save_class_variable_index()
Definition scopes.h:1482
V8_INLINE RareData * GetRareData()
Definition scopes.h:1507
V8_INLINE bool IsParsingHeritage()
Definition scopes.h:1455
Variable * RedeclareSyntheticContextVariable(const AstRawString *name)
void SetScriptScopeInfo(Handle< ScopeInfo > scope_info)
Definition scopes.h:976
static V8_EXPORT_PRIVATE void AllocateScopeInfos(ParseInfo *info, DirectHandle< Script > script, IsolateT *isolate)
bool uses_super_property() const
Definition scopes.h:876
Variable * this_function_var() const
Definition scopes.h:1114
void set_is_skipped_function(bool is_skipped_function)
Definition scopes.h:1187
FunctionKind function_kind() const
Definition scopes.h:863
bool should_ban_arguments() const
Definition scopes.h:987
bool class_scope_has_private_brand() const
Definition scopes.h:1227
V8_INLINE RareData * EnsureRareData()
Definition scopes.h:1314
CreateArgumentsType GetArgumentsType() const
Definition scopes.h:1098
Variable * function_var() const
Definition scopes.h:1046
bool ShouldEagerCompile() const
Definition scopes.h:970
bool needs_private_name_context_chain_recalc() const
Definition scopes.h:1219
bool has_this_reference() const
Definition scopes.h:1213
void set_zone(Zone *zone)
Definition scopes.h:948
V8_INLINE Variable * GetRareVariable(RareVariable id) const
Definition scopes.h:1321
Variable * LookupInModule(const AstRawString *name)
Definition scopes.h:932
bool has_checked_syntax() const
Definition scopes.h:968
void set_has_inferred_function_name(bool value)
Definition scopes.h:1194
Variable * parameter(int index) const
Definition scopes.h:1058
bool is_skipped_function() const
Definition scopes.h:1186
void set_has_checked_syntax(bool has_checked_syntax)
Definition scopes.h:965
void set_class_scope_has_private_brand(bool value)
Definition scopes.h:1224
Variable * arguments() const
Definition scopes.h:1109
PreparseDataBuilder * preparse_data_builder() const
Definition scopes.h:1208
bool has_inferred_function_name() const
Definition scopes.h:1191
bool sloppy_eval_can_extend_vars() const
Definition scopes.h:926
Variable * generator_object_var() const
Definition scopes.h:1051
bool was_lazily_parsed() const
Definition scopes.h:930
bool has_this_declaration() const
Definition scopes.h:1039
PreparseDataBuilder * preparse_data_builder_
Definition scopes.h:1298
void set_preparse_data_builder(PreparseDataBuilder *preparse_data_builder)
Definition scopes.h:1204
base::ThreadedList< SloppyBlockFunctionStatement > sloppy_block_functions_
Definition scopes.h:1287
Variable * rest_parameter() const
Definition scopes.h:1072
V8_INLINE void NullifyRareVariableIf(RareVariable id, Predicate predicate)
Definition scopes.h:1330
ZonePtrList< Variable > params_
Definition scopes.h:1285
bool has_simple_parameters() const
Definition scopes.h:1076
SourceTextModuleDescriptor *const module_descriptor_
Definition scopes.h:1386
SourceTextModuleDescriptor * module() const
Definition scopes.h:1379
base::ThreadedList< Variable >::Iterator top_local_
Definition scopes.h:147
Snapshot(Snapshot &&)=delete
Snapshot(const Snapshot &)=delete
UnresolvedList::Iterator top_unresolved_
Definition scopes.h:146
bool HasContextExtensionSlot() const
Definition scopes.h:505
int num_heap_slots() const
Definition scopes.h:503
void RecordInnerScopeEvalCall()
Definition scopes.h:278
void set_is_block_scope_for_object_literal()
Definition scopes.h:382
void SetLanguageMode(LanguageMode language_mode)
Definition scopes.h:288
bool is_wrapped_function_
Definition scopes.h:849
void set_language_mode(LanguageMode language_mode)
Definition scopes.h:657
int num_var() const
Definition scopes.h:586
bool is_repl_mode_scope() const
Definition scopes.h:610
void set_end_position(int statement_pos)
Definition scopes.h:343
bool has_using_declaration_
Definition scopes.h:844
Variable * Declare(Zone *zone, const AstRawString *name, VariableMode mode, VariableKind kind, InitializationFlag initialization_flag, MaybeAssignedFlag maybe_assigned_flag, bool *was_added)
Definition scopes.h:662
void ForceContextAllocationForParameters()
Definition scopes.h:349
void AllocateScopeInfosRecursively(IsolateT *isolate, MaybeHandle< ScopeInfo > outer_scope, std::unordered_map< int, IndirectHandle< ScopeInfo > > &scope_infos_to_reuse)
bool private_name_lookup_skips_outer_class() const
Definition scopes.h:388
base::ThreadedList< Declaration > * declarations()
Definition scopes.h:229
Variable * catch_variable() const
Definition scopes.h:490
Variable * LookupForTesting(const AstRawString *name)
Definition scopes.h:644
bool is_reparsed() const
Definition scopes.h:116
Scope * outer_scope() const
Definition scopes.h:488
bool is_debug_evaluate_scope_
Definition scopes.h:824
DeclarationScope * AsDeclarationScope()
VariableProxy * NewUnresolved(AstNodeFactory *factory, const AstRawString *name, int start_pos, VariableKind kind=NORMAL_VARIABLE)
Definition scopes.h:234
base::ThreadedList< Variable > * locals()
Definition scopes.h:231
base::ThreadedList< Declaration > decls_
Definition scopes.h:781
Scope * inner_scope_
Definition scopes.h:765
bool is_block_scope_for_object_literal() const
Definition scopes.h:378
bool is_home_object_scope() const
Definition scopes.h:374
base::ThreadedList< Variable > locals_
Definition scopes.h:776
bool is_script_scope() const
Definition scopes.h:364
bool private_name_lookup_skips_outer_class_
Definition scopes.h:836
const ScopeType scope_type_
Definition scopes.h:807
bool must_use_preparsed_scope_data() const
Definition scopes.h:191
bool RemoveInnerScope(Scope *inner_scope)
Definition scopes.h:622
Scope * outer_scope_
Definition scopes.h:764
int ContextHeaderLength() const
Definition scopes.h:522
DeclarationScope * GetReceiverScope()
Definition scopes.cc:1501
bool is_declaration_scope_
Definition scopes.h:831
bool is_debug_evaluate_scope() const
Definition scopes.h:608
bool is_class_scope() const
Definition scopes.h:373
VariableMap variables_
Definition scopes.h:773
void AddInnerScope(Scope *inner_scope)
Definition scopes.h:750
Handle< ScopeInfo > scope_info() const
Definition scopes.h:581
bool has_forced_context_allocation_for_parameters() const
Definition scopes.h:353
bool is_eval_scope() const
Definition scopes.h:361
bool is_function_scope() const
Definition scopes.h:362
void SetMustUsePreparseData()
Definition scopes.h:181
ScopeType scope_type() const
Definition scopes.h:474
bool inner_scope_calls_eval() const
Definition scopes.h:387
bool needs_home_object_
Definition scopes.h:840
bool force_context_allocation_for_parameters_
Definition scopes.h:828
bool has_await_using_declaration_
Definition scopes.h:845
Scope * inner_scope() const
Definition scopes.h:484
bool has_using_declaration() const
Definition scopes.h:392
void set_needs_home_object()
Definition scopes.h:617
UnresolvedList unresolved_list_
Definition scopes.h:779
bool has_await_using_declaration() const
Definition scopes.h:393
bool is_hidden() const
Definition scopes.h:346
void set_is_wrapped_function()
Definition scopes.h:401
bool NeedsContext() const
Definition scopes.h:430
void set_is_hidden()
Definition scopes.h:347
bool needs_home_object() const
Definition scopes.h:612
bool is_wrapped_function() const
Definition scopes.h:397
bool is_block_scope_for_object_literal_
Definition scopes.h:841
Zone * zone() const
Definition scopes.h:179
bool is_nonlinear() const
Definition scopes.h:414
void AllocateDeclaredGlobal(Variable *var)
bool inner_scope_calls_eval_
Definition scopes.h:827
bool is_with_scope() const
Definition scopes.h:371
void set_start_position(int statement_pos)
Definition scopes.h:339
void RecordEvalCall()
Definition scopes.h:1340
bool is_block_scope() const
Definition scopes.h:368
int num_stack_slots() const
Definition scopes.h:502
void set_is_debug_evaluate_scope()
Definition scopes.h:607
bool must_use_preparsed_scope_data_
Definition scopes.h:838
V8_INLINE void ForEach(FunctionType callback)
int end_position() const
Definition scopes.h:342
DeclarationScope * GetDeclarationScope()
Definition scopes.cc:1456
bool sloppy_eval_can_extend_vars_
Definition scopes.h:818
LanguageMode language_mode() const
Definition scopes.h:477
void SetNonlinear()
Definition scopes.h:302
Scope * sibling() const
Definition scopes.h:485
Variable * LookupInScopeOrScopeInfo(const AstRawString *name, Scope *cache)
Definition scopes.h:638
bool is_catch_scope() const
Definition scopes.h:367
int start_position() const
Definition scopes.h:338
bool is_module_scope() const
Definition scopes.h:363
IndirectHandle< ScopeInfo > scope_info_
Definition scopes.h:784
bool ForceContextForLanguageMode() const
Definition scopes.h:419
bool is_declaration_scope() const
Definition scopes.h:372
Variable * LookupLocal(const AstRawString *name)
Definition scopes.h:200
V8_EXPORT_PRIVATE Variable * Lookup(const AstRawString *name)
Definition scopes.cc:84
void Add(Variable *var)
Definition scopes.cc:75
VariableMap(Zone *zone)
Definition scopes.cc:40
Zone * zone() const
Definition scopes.h:74
VariableMap & operator=(VariableMap &&other) V8_NOEXCEPT
Definition scopes.h:59
void Remove(Variable *var)
Definition scopes.cc:70
Variable * Declare(Zone *zone, Scope *scope, const AstRawString *name, VariableMode mode, VariableKind kind, InitializationFlag initialization_flag, MaybeAssignedFlag maybe_assigned_flag, IsStaticFlag is_static_flag, bool *was_added)
Definition scopes.cc:46
VariableMap(VariableMap &&other) V8_NOEXCEPT
Definition scopes.h:56
bool is_parameter() const
Definition variables.h:256
T * New(Args &&... args)
Definition zone.h:114
const JSFunctionRef function_
const ScopeInfoRef scope_info_
int start
int end
#define EXPORT_TEMPLATE_DECLARE(export)
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation nullptr
OptionalOpIndex index
Node * receiver_
TNode< Object > callback
ZoneVector< RpoNumber > & result
int position
Definition liveedit.cc:290
int s
Definition mul-fft.cc:297
bool IsArrowFunction(FunctionKind kind)
bool is_sloppy(LanguageMode language_mode)
Definition globals.h:773
bool IsClassConstructor(FunctionKind kind)
bool IsConciseMethod(FunctionKind kind)
bool IsAccessorFunction(FunctionKind kind)
bool IsModule(FunctionKind kind)
bool BindsSuper(FunctionKind kind)
bool is_strict(LanguageMode language_mode)
Definition globals.h:777
bool IsClassMembersInitializerFunction(FunctionKind kind)
base::PointerTemplateHashMapImpl< ZoneAllocationPolicy > ZoneHashMap
std::vector< ValueType > locals_
#define V8_NOEXCEPT
#define NON_EXPORTED_BASE(code)
#define UNREACHABLE()
Definition logging.h:67
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460
HeritageParsingScope(ClassScope *class_scope)
Definition scopes.h:1398
UnresolvedList unresolved_private_names
Definition scopes.h:1502
Symbol declaration
#define V8_INLINE
Definition v8config.h:500
#define V8_LIKELY(condition)
Definition v8config.h:661
#define V8_WARN_UNUSED_RESULT
Definition v8config.h:671
std::unique_ptr< ValueMirror > value