Class AbstractScope<S extends AbstractScope<S,V>,V extends AbstractVar<S,V>>

java.lang.Object
com.google.javascript.jscomp.AbstractScope<S,V>
All Implemented Interfaces:
StaticScope, Serializable
Direct Known Subclasses:
Scope, TypedScope

public abstract class AbstractScope<S extends AbstractScope<S,V>,V extends AbstractVar<S,V>> extends Object implements StaticScope, Serializable
Scope contains information about a variable scope in JavaScript. Scopes can be nested, a scope points back to its parent scope. A Scope contains information about variables defined in that scope.

ES 2015 introduces new scoping rules, which adds some complexity to this class. In particular, scopes fall into two mutually exclusive categories: block and container. Block scopes are all scopes whose roots are blocks, as well as any control structures whose optional blocks are omitted. These scopes did not exist at all prior to ES 2015. Container scopes comprise function scopes, global scopes, and module scopes, and (aside from modules, which didn't exist in ES5) corresponds to the ES5 scope rules. This corresponds roughly to one container scope per CFG root (but not exactly, due to SCRIPT-level CFGs).

All container scopes, plus the outermost block scope within a function (i.e. the function block scope) are considered hoist scopes. All functions thus have two hoist scopes: the function scope and the function block scope. Hoist scopes are relevant because "var" declarations are hoisted to the closest hoist scope, as opposed to "let" and "const" which always apply to the specific scope in which they occur.

Note that every function actually has two distinct hoist scopes: a container scope on the FUNCTION node, and a block-scope on the top-level BLOCK in the function (the "function block"). Local variables are declared on the function block, while parameters and optionally the function name (if it bleeds, i.e. from a named function expression) are declared on the container scope. This is required so that default parameter initializers can refer to names from outside the function that could possibly be shadowed in the function block. But these scopes are not fully independent of one another, since the language does not allow a top-level local variable to shadow a parameter name - so in some situations these scopes must be treated as a single scope.

See Also:
  • Method Details

    • getDepth

      public abstract int getDepth()
      The depth of the scope. The global scope has depth 0.
    • getParent

      public abstract S getParent()
      Returns the parent scope, or null if this is the global scope.
    • toString

      public final String toString()
      Overrides:
      toString in class Object
    • untyped

      public Scope untyped()
    • typed

      public TypedScope typed()
    • getRootNode

      public final Node getRootNode()
      Gets the container node of the scope. This is typically the FUNCTION node or the global BLOCK/SCRIPT node.
      Specified by:
      getRootNode in interface StaticScope
    • getGlobalScope

      public final S getGlobalScope()
      Walks up the tree to find the global scope.
    • getParentScope

      public final S getParentScope()
      Description copied from interface: StaticScope
      Returns the scope enclosing this one or null if none.
      Specified by:
      getParentScope in interface StaticScope
    • hasOwnImplicitSlot

      protected boolean hasOwnImplicitSlot(@Nullable com.google.javascript.jscomp.AbstractScope.ImplicitVar name)
      Returns true iff this scope implies a slot with the given name.
    • hasOwnSlot

      public final boolean hasOwnSlot(String name)
      Returns true if a variable is declared in this scope, with no recursion.
    • hasSlot

      public final boolean hasSlot(String name)
      Returns true if a variable is declared in this or any parent scope.
    • getOwnSlot

      public final V getOwnSlot(String name)
      Description copied from interface: StaticScope
      Like getSlot but does not recurse into parent scopes.
      Specified by:
      getOwnSlot in interface StaticScope
    • getSlot

      public final V getSlot(String name)
      Description copied from interface: StaticScope
      Returns any defined slot within this scope for this name. This call continues searching through parent scopes if a slot with this name is not found in the current scope.
      Specified by:
      getSlot in interface StaticScope
      Parameters:
      name - The name of the variable slot to look up.
      Returns:
      The defined slot for the variable, or null if no definition exists.
    • getVar

      public V getVar(String name)
      Returns the variable, may be null

      Non-final for TypedScope which needs to handle qualified names.

    • getArgumentsVar

      public final V getArgumentsVar()
      Get a unique Var object to represent "arguments" within this scope.

      This explicitly excludes user declared variables that are names "arguments". It only returns special "arguments" variable that is inherent to a function.

    • getVarIterable

      public final Iterable<V> getVarIterable()
      Return an iterable over all of the variables declared in this scope (except the special 'arguments' variable).
    • getAllAccessibleVariables

      public final Iterable<V> getAllAccessibleVariables()
      Return an iterable over all of the variables accessible to this scope (i.e. the variables in this scope and its parent scopes). Any variables declared in the local scope with the same name as a variable declared in a parent scope gain precedence - if let x exists in the block scope, a declaration let x from the parent scope would not be included because the parent scope's variable gets shadowed.

      The iterable contains variables from inner scopes before adding variables from outer parent scopes.

      We do not include the special 'arguments' variable.

    • getAllSymbols

      public final Iterable<V> getAllSymbols()
    • getVarCount

      public final int getVarCount()
      Returns number of variables in this scope (excluding the special 'arguments' variable)
    • isGlobal

      public final boolean isGlobal()
      Returns whether this is the global scope.
    • isLocal

      public final boolean isLocal()
      Returns whether this is a local scope (i.e. not the global scope).
    • isBlockScope

      public final boolean isBlockScope()
    • isStaticBlockScope

      public final boolean isStaticBlockScope()
    • isFunctionBlockScope

      public final boolean isFunctionBlockScope()
    • isFunctionScope

      public final boolean isFunctionScope()
    • isModuleScope

      public final boolean isModuleScope()
    • isMemberFieldDefScope

      public final boolean isMemberFieldDefScope()
    • isComputedFieldDefRhsScope

      public final boolean isComputedFieldDefRhsScope()
    • isCatchScope

      public final boolean isCatchScope()
    • isCfgRootScope

      public final boolean isCfgRootScope()
    • getClosestHoistScope

      public final S getClosestHoistScope()
      If a var were declared in this scope, return the scope it would be hoisted to.

      For function scopes, we return back the scope itself, since even though there is no way to declare a var inside function parameters, it would make even less sense to say that such declarations would be "hoisted" somewhere else.

    • getClosestCfgRootScope

      public final S getClosestCfgRootScope()
    • getClosestContainerScope

      public final S getClosestContainerScope()
      Returns the closest container scope. This is equivalent to what the current scope would have been for non-ES6 scope creators, and is thus useful for migrating code to use block scopes.