Skip to content

Commit

Permalink
Do the goog.loadModule inlining while processing the AST rather than
Browse files Browse the repository at this point in the history
having to keep around extra state to do it at the end.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=139781248
  • Loading branch information
blickly committed Nov 21, 2016
1 parent b587fa1 commit 9904fad
Showing 1 changed file with 34 additions and 31 deletions.
65 changes: 34 additions & 31 deletions src/com/google/javascript/jscomp/ClosureRewriteModule.java
Expand Up @@ -386,10 +386,13 @@ private class ScriptUpdater implements Callback {
@Override @Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) { public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
switch (n.getToken()) { switch (n.getToken()) {
case CALL: case EXPR_RESULT:
if (NodeUtil.isCallTo(n, "goog.loadModule") && n.getLastChild().isFunction()) { if (isGoogLoadModuleStatement(n)) {
updateGoogLoadModule(n); updateGoogLoadModuleEarly(n);
} }
break;

case CALL:
if (NodeUtil.isCallTo(n, "goog.module")) { if (NodeUtil.isCallTo(n, "goog.module")) {
updateGoogModule(n); updateGoogModule(n);
} }
Expand Down Expand Up @@ -434,6 +437,12 @@ public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
@Override @Override
public void visit(NodeTraversal t, Node n, Node parent) { public void visit(NodeTraversal t, Node n, Node parent) {
switch (n.getToken()) { switch (n.getToken()) {
case EXPR_RESULT:
if (isGoogLoadModuleStatement(n)) {
updateGoogLoadModuleLate(n);
}
break;

case SCRIPT: case SCRIPT:
updateEndScript(); updateEndScript();
break; break;
Expand All @@ -449,6 +458,13 @@ public void visit(NodeTraversal t, Node n, Node parent) {
} }
} }


private static boolean isGoogLoadModuleStatement(Node exprResult) {
Preconditions.checkArgument(exprResult.isExprResult());
Node call = exprResult.getFirstChild();
return call != null
&& NodeUtil.isCallTo(call, "goog.loadModule") && call.getLastChild().isFunction();
}

/** /**
* Checks that imports of goog.module provided files are used correctly. * Checks that imports of goog.module provided files are used correctly.
*/ */
Expand Down Expand Up @@ -540,7 +556,6 @@ public void visit(Node typeRefNode) {
// Per script state needed for rewriting including nested goog.loadModule() calls. // Per script state needed for rewriting including nested goog.loadModule() calls.
private Deque<ScriptDescription> scriptStack = new LinkedList<>(); private Deque<ScriptDescription> scriptStack = new LinkedList<>();
private ScriptDescription currentScript = null; private ScriptDescription currentScript = null;
private List<Node> loadModuleStatements = new ArrayList<>(); // Statements to be inlined.


// Global state tracking an association between the dotted names of goog.module()s and whether // Global state tracking an association between the dotted names of goog.module()s and whether
// the goog.module declares itself as a legacy namespace. // the goog.module declares itself as a legacy namespace.
Expand Down Expand Up @@ -632,8 +647,6 @@ private void processAllFiles(Deque<ScriptDescription> scriptDescriptions, Node s
pushScript(scriptDescriptions.removeFirst()); pushScript(scriptDescriptions.removeFirst());
NodeTraversal.traverseEs6(compiler, c, new ScriptUpdater()); NodeTraversal.traverseEs6(compiler, c, new ScriptUpdater());
popScript(); popScript();

inlineGoogLoadModuleCalls();
} }
} }


Expand All @@ -654,8 +667,6 @@ public void hotSwapScript(Node scriptRoot, Node originalRoot) {
NodeTraversal.traverseEs6(compiler, scriptRoot, new ScriptUpdater()); NodeTraversal.traverseEs6(compiler, scriptRoot, new ScriptUpdater());
popScript(); popScript();


inlineGoogLoadModuleCalls();

reportUnrecognizedRequires(); reportUnrecognizedRequires();
} }


Expand Down Expand Up @@ -880,13 +891,23 @@ static void inlineModuleIntoGlobal(Node scriptNode) {
scriptNode.addChildrenToBack(moduleNode.removeChildren()); scriptNode.addChildrenToBack(moduleNode.removeChildren());
} }


private void updateGoogLoadModule(Node call) { private void updateGoogLoadModuleEarly(Node exprResultNode) {
pushScript(currentScript.removeFirstChildScript()); pushScript(currentScript.removeFirstChildScript());
Node moduleScopeRoot = exprResultNode.getFirstChild().getLastChild().getLastChild();
Preconditions.checkState(NodeUtil.isModuleScopeRoot(moduleScopeRoot),
"goog.loadModule called with non-module contents: %s", moduleScopeRoot);
currentScript.rootNode = moduleScopeRoot;
}

private void updateGoogLoadModuleLate(Node exprResultNode) {
Node call = exprResultNode.removeFirstChild();
Node moduleBlockNode = call.getLastChild().getLastChild();


currentScript.rootNode = call.getLastChild().getLastChild(); exprResultNode.setToken(Token.BLOCK);
// These should be removed and replaced with the block in the function being passed as a exprResultNode.addChildrenToBack(moduleBlockNode.removeChildren());
// parameter, but it's not safe to do this in the middle of AST traversal. currentScript.rootNode = exprResultNode;
loadModuleStatements.add(NodeUtil.getEnclosingStatement(call)); NodeUtil.tryMergeBlock(exprResultNode);
compiler.reportCodeChange();
} }


private void updateGoogModule(Node call) { private void updateGoogModule(Node call) {
Expand Down Expand Up @@ -1354,24 +1375,6 @@ private void exportTheEmptyBinaryNamespaceAt(Node atNode, AddAt addAt) {
currentScript.hasCreatedExportObject = true; currentScript.hasCreatedExportObject = true;
} }


/**
* Rewrite "goog.loadModule(function(exports) { asdf; });" to "{ asdf; }"
*
* Can't be done in updateGoogLoadModule() because it runs in the middle of AST traversal and
* performing a block merge in the middle of AST traversal will either hide the block contents
* from the traversal or will screw up the NodeTraversal.getScope() creation.
*/
private void inlineGoogLoadModuleCalls() {
for (Node loadModuleStatement : loadModuleStatements) {
Node moduleBlockNode = loadModuleStatement.getFirstChild().getLastChild().getLastChild();
moduleBlockNode.detach();
loadModuleStatement.replaceWith(moduleBlockNode);
NodeUtil.tryMergeBlock(moduleBlockNode);
compiler.reportCodeChange();
}
loadModuleStatements.clear();
}

static void checkAndSetStrictModeDirective(NodeTraversal t, Node n) { static void checkAndSetStrictModeDirective(NodeTraversal t, Node n) {
Preconditions.checkState(n.isScript(), n); Preconditions.checkState(n.isScript(), n);


Expand Down

0 comments on commit 9904fad

Please sign in to comment.