code: public static void traverseScopeRoots(
        AbstractCompiler compiler,
        @Nullable Node root,
        @Nullable List<Node> scopeNodes,
        final Callback cb,
        @Nullable final ChangeScopeRootCallback changeCallback,
        final boolean traverseNested) {
      if (scopeNodes == null) {
        NodeTraversal.traverse(compiler, root, cb);
      } else {
        MemoizedScopeCreator scopeCreator =
            new MemoizedScopeCreator(new Es6SyntacticScopeCreator(compiler));
  
        for (final Node scopeNode : scopeNodes) {
          traverseSingleScopeRoot(
              compiler, cb, changeCallback, traverseNested, scopeCreator, scopeNode);
        }
      }
    }
docs: Traverses *just* the contents of provided scope nodes (and optionally scopes nested within
  them) but will fall back on traversing the entire AST from root if a null scope nodes list is
  provided. Also allows for a callback to notify when starting on one of the provided scope
  nodes.
  @param root If scopeNodes is null, this method will just traverse 'root' instead. If scopeNodes
  is not null, this parameter is ignored.