private void declareVariablesForObjLitValues(
      Name objlitName,
      String alias,
      Node objlit,
      Node varNode,
      Node nameToAddAfter,
      Node varParent) {
    int arbitraryNameCounter = 0;
    boolean discardKeys = !objlitName.shouldKeepKeys();

    for (Node key = objlit.getFirstChild(), nextKey; key != null;
         key = nextKey) {
      Node value = key.getFirstChild();
      nextKey = key.getNext();

      // A computed property, or a get or a set can not be rewritten as a VAR. We don't know what
      // properties will be generated by a spread.
      switch (key.getToken()) {
        case GETTER_DEF:
        case SETTER_DEF:
        case COMPUTED_PROP:
        case SPREAD:
          continue;
        case STRING_KEY:
        case MEMBER_FUNCTION_DEF:
          break;
        default:
          throw new IllegalStateException("Unexpected child of OBJECTLIT: " + key.toStringTree());
      }

      // We generate arbitrary names for keys that aren't valid JavaScript
      // identifiers, since those keys are never referenced. (If they were,
      // this object literal's child names wouldn't be collapsible.) The only
      // reason that we don't eliminate them entirely is the off chance that
      // their values are expressions that have side effects.
      boolean isJsIdentifier = !key.isNumber() && TokenStream.isJSIdentifier(key.getString());
      String propName = isJsIdentifier ? key.getString() : String.valueOf(++arbitraryNameCounter);

      // If the name cannot be collapsed, skip it.
      String qName = objlitName.getFullName() + '.' + propName;
      Name p = nameMap.get(qName);
      if (p != null && !canCollapse(p)) {
        continue;
      }

      String propAlias = appendPropForAlias(alias, propName);
      Node refNode = null;
      if (discardKeys) {
        objlit.removeChild(key);
        value.detach();
        // Don't report a change here because the objlit has already been removed from the tree.
      } else {
        // Substitute a reference for the value.
        refNode = IR.name(propAlias);
        if (key.getBooleanProp(Node.IS_CONSTANT_NAME)) {
          refNode.putBooleanProp(Node.IS_CONSTANT_NAME, true);
        }

        key.replaceChild(value, refNode);
        compiler.reportChangeToEnclosingScope(refNode);
      }

      // Declare the collapsed name as a variable with the original value.
      Node nameNode = IR.name(propAlias);
      nameNode.addChildToFront(value);
      if (key.getBooleanProp(Node.IS_CONSTANT_NAME)) {
        nameNode.putBooleanProp(Node.IS_CONSTANT_NAME, true);
      }
      Node newVar = IR.var(nameNode).useSourceInfoIfMissingFromForTree(key);
      if (nameToAddAfter != null) {
        varParent.addChildAfter(newVar, nameToAddAfter);
      } else {
        varParent.addChildBefore(newVar, varNode);
      }
      compiler.reportChangeToEnclosingScope(newVar);
      nameToAddAfter = newVar;

      // Update the global name's node ancestry if it hasn't already been
      // done. (Duplicate keys in an object literal can bring us here twice
      // for the same global name.)
      if (isJsIdentifier && p != null) {
        if (!discardKeys) {
          p.addAliasingGetClonedFromDeclaration(refNode);
        }

        p.updateRefNode(p.getDeclaration(), nameNode);

        if (value.isFunction()) {
          checkForHosedThisReferences(value, key.getJSDocInfo(), p);
        }
      }
    }
  }
private void declareVariablesForObjLitValues ( Name objlitName , String alias , Node objlit , Node varNode , Node nameToAddAfter , Node varParent ) { int arbitraryNameCounter = 0 ; boolean discardKeys = ! objlitName . shouldKeepKeys ( ) ; for ( Node key = objlit . getFirstChild ( ) , nextKey ; key != null ; key = nextKey ) { Node value = key . getFirstChild ( ) ; nextKey = key . getNext ( ) ; switch ( key . getToken ( ) ) { case GETTER_DEF : case SETTER_DEF : case COMPUTED_PROP : case SPREAD : continue ; case STRING_KEY : case MEMBER_FUNCTION_DEF : break ; default : throw new IllegalStateException ( "Unexpected child of OBJECTLIT: " + key . toStringTree ( ) ) ; } boolean isJsIdentifier = ! key . isNumber ( ) && TokenStream . isJSIdentifier ( key . getString ( ) ) ; String propName = isJsIdentifier ? key . getString ( ) : String . valueOf ( ++ arbitraryNameCounter ) ; String qName = objlitName . getFullName ( ) + '.' + propName ; Name p = nameMap . get ( qName ) ; if ( p != null && ! canCollapse ( p ) ) { continue ; } String propAlias = appendPropForAlias ( alias , propName ) ; Node refNode = null ; if ( discardKeys ) { objlit . removeChild ( key ) ; value . detach ( ) ; } else { refNode = IR . name ( propAlias ) ; if ( key . getBooleanProp ( Node . IS_CONSTANT_NAME ) ) { refNode . putBooleanProp ( Node . IS_CONSTANT_NAME , true ) ; } key . replaceChild ( value , refNode ) ; compiler . reportChangeToEnclosingScope ( refNode ) ; } Node nameNode = IR . name ( propAlias ) ; nameNode . addChildToFront ( value ) ; if ( key . getBooleanProp ( Node . IS_CONSTANT_NAME ) ) { nameNode . putBooleanProp ( Node . IS_CONSTANT_NAME , true ) ; } Node newVar = IR . var ( nameNode ) . useSourceInfoIfMissingFromForTree ( key ) ; if ( nameToAddAfter != null ) { varParent . addChildAfter ( newVar , nameToAddAfter ) ; } else { varParent . addChildBefore ( newVar , varNode ) ; } compiler . reportChangeToEnclosingScope ( newVar ) ; nameToAddAfter = newVar ; if ( isJsIdentifier && p != null ) { if ( ! discardKeys ) { p . addAliasingGetClonedFromDeclaration ( refNode ) ; } p . updateRefNode ( p . getDeclaration ( ) , nameNode ) ; if ( value . isFunction ( ) ) { checkForHosedThisReferences ( value , key . getJSDocInfo ( ) , p ) ; } } } }
Declares global variables to serve as aliases for the values in an object literal, optionally
removing all of the object literal's keys and values.

@param alias The object literal's flattened name (e.g. "a$b$c")
@param objlit The OBJLIT node
@param varNode The VAR node to which new global variables should be added as children
@param nameToAddAfter The child of {@code varNode} after which new variables should be added
(may be null)
@param varParent {@code varNode}'s parent