-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make ES6 module transpilation a "real" compiler pass.
This moves it from happening at the end of parsing into DefaultPassConfig, where it can be more easily reordered around other passes. Many of the existing passes were relying on module rewriting happening at parse time, so much of the churn is from porting those. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159139260
- Loading branch information
Showing
13 changed files
with
119 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,8 @@ | |
*/ | ||
package com.google.javascript.jscomp; | ||
|
||
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.Feature.MODULES; | ||
|
||
import com.google.common.base.Preconditions; | ||
import com.google.common.base.Splitter; | ||
import com.google.common.collect.ImmutableSet; | ||
|
@@ -34,13 +36,13 @@ | |
import java.util.Set; | ||
|
||
/** | ||
* Rewrites a ES6 module into a form that can be safely concatenated. | ||
* Note that we treat a file as an ES6 module if it has at least one import or | ||
* export statement. | ||
* Rewrites a ES6 module into a form that can be safely concatenated. Note that we treat a file as | ||
* an ES6 module if it has at least one import or export statement. | ||
* | ||
* @author [email protected] (Michael Zhou) | ||
*/ | ||
public final class Es6RewriteModules extends AbstractPostOrderCallback { | ||
public final class Es6RewriteModules extends AbstractPostOrderCallback | ||
implements HotSwapCompilerPass { | ||
private static final String DEFAULT_EXPORT_NAME = "$jscompDefaultExport"; | ||
|
||
static final DiagnosticType LHS_OF_GOOG_REQUIRE_MUST_BE_CONST = | ||
|
@@ -54,13 +56,13 @@ public final class Es6RewriteModules extends AbstractPostOrderCallback { | |
"Namespace imports ('goog:some.Namespace') cannot use import * as. " | ||
+ "Did you mean to import {0} from ''{1}'';?"); | ||
|
||
private final Compiler compiler; | ||
private int scriptNodeCount = 0; | ||
private final AbstractCompiler compiler; | ||
private int scriptNodeCount; | ||
|
||
/** | ||
* Maps exported names to their names in current module. | ||
*/ | ||
private Map<String, NameNodePair> exportMap = new LinkedHashMap<>(); | ||
private Map<String, NameNodePair> exportMap; | ||
|
||
/** | ||
* Maps symbol names to a pair of (moduleName, originalName). The original | ||
|
@@ -69,12 +71,12 @@ public final class Es6RewriteModules extends AbstractPostOrderCallback { | |
* object. Eg: "import {foo as f} from 'm'" maps 'f' to the pair ('m', 'foo'). | ||
* In the entry for "import * as ns", the originalName will be the empty string. | ||
*/ | ||
private Map<String, ModuleOriginalNamePair> importMap = new HashMap<>(); | ||
private Map<String, ModuleOriginalNamePair> importMap; | ||
|
||
private Set<String> classes = new HashSet<>(); | ||
private Set<String> typedefs = new HashSet<>(); | ||
private Set<String> classes; | ||
private Set<String> typedefs; | ||
|
||
private Set<String> alreadyRequired = new HashSet<>(); | ||
private Set<String> alreadyRequired; | ||
|
||
private boolean forceRewrite; | ||
|
||
|
@@ -84,7 +86,7 @@ public final class Es6RewriteModules extends AbstractPostOrderCallback { | |
* Creates a new Es6RewriteModules instance which can be used to rewrite | ||
* ES6 modules to a concatenable form. | ||
*/ | ||
public Es6RewriteModules(Compiler compiler) { | ||
public Es6RewriteModules(AbstractCompiler compiler) { | ||
this.compiler = compiler; | ||
} | ||
|
||
|
@@ -104,6 +106,8 @@ public static boolean isEs6ModuleRoot(Node scriptNode) { | |
* "import" or "export" statements. Fails if the file contains a goog.provide or goog.module. | ||
* | ||
* @return True, if the file is now an ES6 module. False, if the file must remain a script. | ||
* TODO(blickly): Move this logic out of this pass, since it is independent of whether or | ||
* not we are actually transpiling modules | ||
*/ | ||
public boolean forceToEs6Module(Node root) { | ||
if (isEs6ModuleRoot(root)) { | ||
|
@@ -120,15 +124,42 @@ public boolean forceToEs6Module(Node root) { | |
return true; | ||
} | ||
|
||
@Override | ||
public void process(Node externs, Node root) { | ||
Preconditions.checkState(compiler.getOptions().getLanguageIn().toFeatureSet().has(MODULES)); | ||
for (Node file = root.getFirstChild(); file != null; file = file.getNext()) { | ||
hotSwapScript(file, null); | ||
} | ||
compiler.setFeatureSet(compiler.getFeatureSet().without(MODULES)); | ||
} | ||
|
||
@Override | ||
public void hotSwapScript(Node scriptNode, Node originalRoot) { | ||
if (isEs6ModuleRoot(scriptNode)) { | ||
processFile(scriptNode); | ||
} | ||
} | ||
|
||
/** | ||
* Rewrite a single ES6 module file to a global script version. | ||
*/ | ||
public void processFile(Node root) { | ||
private void processFile(Node root) { | ||
Preconditions.checkArgument(isEs6ModuleRoot(root), root); | ||
this.forceRewrite = true; | ||
clearState(); | ||
NodeTraversal.traverseEs6(compiler, root, this); | ||
} | ||
|
||
public void clearState() { | ||
this.scriptNodeCount = 0; | ||
this.exportMap = new LinkedHashMap<>(); | ||
this.importMap = new HashMap<>(); | ||
this.classes = new HashSet<>(); | ||
this.typedefs = new HashSet<>(); | ||
this.alreadyRequired = new HashSet<>(); | ||
this.forceRewrite = true; | ||
this.googRequireInsertSpot = null; | ||
} | ||
|
||
/** | ||
* Avoid processing if we find the appearance of goog.provide or goog.module. | ||
* | ||
|
@@ -284,8 +315,7 @@ private void visitExport(NodeTraversal t, Node export, Node parent) { | |
} | ||
|
||
if (name != null) { | ||
Node decl = child.cloneTree(); | ||
decl.setJSDocInfo(child.getJSDocInfo()); | ||
Node decl = child.detach(); | ||
parent.replaceChild(export, decl); | ||
exportMap.put("default", new NameNodePair(name, child)); | ||
} else { | ||
|
@@ -556,6 +586,7 @@ public void visit(NodeTraversal t, Node n, Node parent) { | |
n.setString(newName); | ||
n.setOriginalName(name); | ||
} | ||
t.reportCodeChange(n); | ||
} else if (var == null && importMap.containsKey(name)) { | ||
// Change to property access on the imported module object. | ||
if (parent.isCall() && parent.getFirstChild() == n) { | ||
|
@@ -571,6 +602,7 @@ public void visit(NodeTraversal t, Node n, Node parent) { | |
IR.getprop(moduleAccess, IR.string(pair.originalName)) | ||
.useSourceInfoIfMissingFromForTree(n)); | ||
} | ||
t.reportCodeChange(moduleAccess); | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.