private void inlineAliasIfPossible ( Name name , Ref alias , GlobalNamespace namespace ) { // Ensure that the alias is assigned to a local variable at that // variable's declaration. If the alias's parent is a NAME, // then the NAME must be the child of a VAR, LET, or CONST node, and we must // be in a VAR, LET, or CONST assignment. // Otherwise if the parent is an assign, we are in a "a = alias" case. Node aliasParent = alias . getNode ( ) . getParent ( ) ; if ( aliasParent . isName ( ) || aliasParent . isAssign ( ) ) { Node aliasLhsNode = aliasParent . isName ( ) ? aliasParent : aliasParent . getFirstChild ( ) ; String aliasVarName = aliasLhsNode . getString ( ) ; Var aliasVar = alias . scope . getVar ( aliasVarName ) ; checkState ( aliasVar != null , "Expected variable to be defined in scope" , aliasVarName ) ; ReferenceCollectingCallback collector = new ReferenceCollectingCallback ( compiler , ReferenceCollectingCallback . DO_NOTHING_BEHAVIOR , new Es6SyntacticScopeCreator ( compiler ) , Predicates . equalTo ( aliasVar ) ) ; Scope aliasScope = aliasVar . getScope ( ) ; collector . processScope ( aliasScope ) ; ReferenceCollection aliasRefs = collector . getReferences ( aliasVar ) ; Set < AstChange > newNodes = new LinkedHashSet <> ( ) ; if ( aliasRefs . isWellDefined ( ) && aliasRefs . isAssignedOnceInLifetime ( ) ) { // The alias is well-formed, so do the inlining now. int size = aliasRefs . references . size ( ) ; // It's initialized on either the first or second reference. int firstRead = aliasRefs . references . get ( 0 ) . isInitializingDeclaration ( ) ? 1 : 2 ; for ( int i = firstRead ; i < size ; i ++ ) { Reference aliasRef = aliasRefs . references . get ( i ) ; newNodes . add ( replaceAliasReference ( alias , aliasRef ) ) ; } // just set the original alias to null. tryReplacingAliasingAssignment ( alias , aliasLhsNode ) ; // Inlining the variable may have introduced new references // to descendants of {@code name}. So those need to be collected now. namespace . scanNewNodes ( newNodes ) ; return ; } if ( name . isConstructor ( ) ) { // TODO(lharker): the main reason this was added is because method decomposition inside // generators introduces some constructor aliases that weren't getting inlined. // If we find another (safer) way to avoid aliasing in method decomposition, consider // removing this. if ( ! partiallyInlineAlias ( alias , namespace , aliasRefs , aliasLhsNode ) ) { // If we can't inline all alias references, make sure there are no unsafe property // accesses. if ( referencesCollapsibleProperty ( aliasRefs , name , namespace ) ) { compiler . report ( JSError . make ( aliasParent , UNSAFE_CTOR_ALIASING , aliasVarName ) ) ; } } } } }
Attempts to inline a non - global alias of a global name .