use of com.google.javascript.jscomp.deps.ModuleLoader.ModulePath in project closure-compiler by google.
the class RewriteDynamicImports method visit.
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
if (n.getToken() != Token.DYNAMIC_IMPORT) {
return;
}
// If the module specifier is a string, attempt to resolve the module
final ModuleMap moduleMap = compiler.getModuleMap();
final Node importSpecifier = n.getFirstChild();
if (importSpecifier.isStringLit() && moduleMap != null) {
final ModulePath targetPath = t.getInput().getPath().resolveJsModule(importSpecifier.getString(), n.getSourceFileName(), n.getLineno(), n.getCharno());
final Module module = (targetPath == null) ? null : compiler.getModuleMap().getModule(targetPath);
final String targetModuleVarName = (module == null) ? null : GlobalizedModuleName.create(module.metadata(), null, null).aliasName().join();
final Var targetModuleNS = (targetModuleVarName == null) ? null : t.getScope().getVar(targetModuleVarName);
if (targetModuleNS != null) {
final JSChunk targetModule = targetModuleNS.getInput().getChunk();
// No further rewriting occurs for this case.
if (t.getChunk() == targetModule) {
replaceDynamicImportWithPromise(t, n, targetModuleNS);
return;
} else {
// The target output chunk is recognized and different from the current chunk.
// Retarget the import specifier path to the output chunk path and rewrite
// the import to reference the rewritten global module namespace variable.
retargetImportSpecifier(t, n, targetModule);
if (NodeUtil.isExpressionResultUsed(n)) {
addChainedThen(n, targetModuleNS);
}
}
}
}
if (aliasIsValid()) {
aliasDynamicImport(t, n);
} else if (this.alias != null) {
t.report(n, DYNAMIC_IMPORT_INVALID_ALIAS);
} else if (requiresAliasing) {
t.report(n, DYNAMIC_IMPORT_ALIASING_REQUIRED);
}
}
use of com.google.javascript.jscomp.deps.ModuleLoader.ModulePath in project closure-compiler by google.
the class RewriteGoogJsImports method process.
@Override
public void process(Node externs, Node root) {
googModule = null;
Node googJsScriptNode = findGoogJsScriptNode(root);
if (googJsScriptNode == null) {
// Potentially in externs if library level type checking.
googJsScriptNode = findGoogJsScriptNode(externs);
}
if (mode == Mode.LINT_AND_REWRITE) {
if (googJsScriptNode != null) {
ModulePath googJsPath = compiler.getInput(googJsScriptNode.getInputId()).getPath();
googModule = moduleMap.getModule(googJsPath);
checkNotNull(googModule);
Predicate<Binding> isFromGoog = (Binding b) -> b.originatingExport().modulePath() == googJsPath;
checkState(googModule.boundNames().values().stream().allMatch(isFromGoog), "goog.js should never import anything");
checkState(!googModule.namespace().containsKey("default"), "goog.js should never have a default export.");
checkState(googModule.namespace().values().stream().allMatch(isFromGoog), "goog.js should never export from anything.");
}
} else {
checkState(mode == Mode.LINT_ONLY);
}
for (Node script = root.getFirstChild(); script != null; script = script.getNext()) {
rewriteImports(script);
}
changeModules();
}
use of com.google.javascript.jscomp.deps.ModuleLoader.ModulePath in project closure-compiler by google.
the class ProcessCommonJSModules method removeWebpackModuleShim.
/**
* For AMD wrappers, webpack adds a shim for the "module" variable. We need that to be a free var
* so we remove the shim.
*/
private void removeWebpackModuleShim(Node root) {
checkState(root.isScript());
Node n = root.getFirstChild();
// Skip any empty statements from those
while (n != null && n.isEmpty()) {
n = n.getNext();
}
// and it must be an expression statement.
if (n == null || !n.isExprResult() || n.getNext() != null) {
return;
}
Node call = n.getFirstChild();
if (call == null || !call.isCall()) {
return;
}
// Find the IIFE call and function nodes
Node callTarget = call.getFirstChild();
if (!callTarget.isFunction()) {
return;
}
Node fnc = callTarget;
Node params = NodeUtil.getFunctionParameters(fnc);
Node moduleParam = null;
Node param = params.getFirstChild();
int paramNumber = 0;
while (param != null) {
paramNumber++;
if (param.isName() && param.getString().equals(MODULE)) {
moduleParam = param;
break;
}
param = param.getNext();
}
if (moduleParam == null) {
return;
}
boolean isFreeCall = call.getBooleanProp(Node.FREE_CALL);
Node arg = call.getChildAtIndex(isFreeCall ? paramNumber : paramNumber + 1);
if (arg == null) {
return;
}
Node argCallTarget = arg.getFirstChild();
if (arg.isCall() && argCallTarget.isCall() && isCommonJsImport(argCallTarget) && argCallTarget.getNext().matchesName(MODULE)) {
String importPath = getCommonJsImportPath(argCallTarget);
ModulePath modulePath = compiler.getInput(root.getInputId()).getPath().resolveJsModule(importPath, arg.getSourceFileName(), arg.getLineno(), arg.getCharno());
if (modulePath == null) {
// The module loader will issue an error
return;
}
if (modulePath.toString().contains("/buildin/module.js")) {
arg.detach();
param.detach();
compiler.reportChangeToChangeScope(fnc);
compiler.reportChangeToEnclosingScope(fnc);
}
}
}
use of com.google.javascript.jscomp.deps.ModuleLoader.ModulePath in project closure-compiler by google.
the class Compiler method parseInputs.
// ------------------------------------------------------------------------
// Parsing
// ------------------------------------------------------------------------
/**
* Parses the externs and main inputs.
*
* @return A synthetic root node whose two children are the externs root and the main root
*/
Node parseInputs() {
boolean devMode = options.devMode != DevMode.OFF;
// If old roots exist (we are parsing a second time), detach each of the
// individual file parse trees.
externsRoot.detachChildren();
jsRoot.detachChildren();
scriptNodeByFilename.clear();
Tracer tracer = newTracer(PassNames.PARSE_INPUTS);
beforePass(PassNames.PARSE_INPUTS);
try {
// Parse externs sources.
if (options.numParallelThreads > 1) {
new PrebuildAst(this, options.numParallelThreads).prebuild(externs);
}
for (CompilerInput input : externs) {
Node n = checkNotNull(input.getAstRoot(this));
if (hasErrors()) {
return null;
}
externsRoot.addChildToBack(n);
scriptNodeByFilename.put(input.getSourceFile().getName(), n);
}
if (options.transformAMDToCJSModules) {
processAMDModules(moduleGraph.getAllInputs());
}
if (options.getLanguageIn().toFeatureSet().has(Feature.MODULES) || options.getProcessCommonJSModules()) {
initializeModuleLoader();
} else {
// Use an empty module loader if we're not actually dealing with modules.
this.moduleLoader = ModuleLoader.EMPTY;
}
if (options.getDependencyOptions().needsManagement()) {
findModulesFromEntryPoints(options.getLanguageIn().toFeatureSet().has(Feature.MODULES), options.getProcessCommonJSModules());
} else if (options.needsTranspilationFrom(FeatureSet.ES2015_MODULES) || options.getProcessCommonJSModules()) {
if (options.getLanguageIn().toFeatureSet().has(Feature.MODULES)) {
parsePotentialModules(moduleGraph.getAllInputs());
}
// Build a map of module identifiers for any input which provides no namespace.
// These files could be imported modules which have no exports, but do have side effects.
Map<String, CompilerInput> inputModuleIdentifiers = new HashMap<>();
for (CompilerInput input : moduleGraph.getAllInputs()) {
if (input.getKnownProvides().isEmpty()) {
ModulePath modPath = moduleLoader.resolve(input.getSourceFile().getName());
inputModuleIdentifiers.put(modPath.toModuleName(), input);
}
}
// Find out if any input attempted to import a module that had no exports.
// In this case we must force module rewriting to occur on the imported file
Map<String, CompilerInput> inputsToRewrite = new HashMap<>();
for (CompilerInput input : moduleGraph.getAllInputs()) {
for (String require : input.getKnownRequiredSymbols()) {
if (inputModuleIdentifiers.containsKey(require) && !inputsToRewrite.containsKey(require)) {
inputsToRewrite.put(require, inputModuleIdentifiers.get(require));
}
}
}
for (CompilerInput input : inputsToRewrite.values()) {
input.setJsModuleType(ModuleType.IMPORTED_SCRIPT);
}
}
if (this.moduleLoader != null) {
this.moduleLoader.setErrorHandler(this);
}
orderInputs();
// If in IDE mode, we ignore the error and keep going.
if (hasErrors()) {
return null;
}
// Build the AST.
if (options.numParallelThreads > 1) {
new PrebuildAst(this, options.numParallelThreads).prebuild(moduleGraph.getAllInputs());
}
for (CompilerInput input : moduleGraph.getAllInputs()) {
Node n = checkNotNull(input.getAstRoot(this));
if (devMode) {
runValidityCheck();
if (hasErrors()) {
return null;
}
}
// externExportsPath.
if (options.sourceMapOutputPath != null || options.isExternExportsEnabled() || options.externExportsPath != null || !options.replaceStringsFunctionDescriptions.isEmpty()) {
// Annotate the nodes in the tree with information from the
// input file. This information is used to construct the SourceMap.
SourceInformationAnnotator sia = DevMode.OFF.equals(options.devMode) ? SourceInformationAnnotator.create() : SourceInformationAnnotator.createWithAnnotationChecks(input.getName());
NodeTraversal.traverse(this, n, sia);
}
if (NodeUtil.isFromTypeSummary(n)) {
input.setIsExtern();
externsRoot.addChildToBack(n);
} else {
jsRoot.addChildToBack(n);
}
scriptNodeByFilename.put(input.getSourceFile().getName(), n);
}
if (hasErrors()) {
return null;
}
return externAndJsRoot;
} finally {
afterPass(PassNames.PARSE_INPUTS);
stopTracer(tracer, PassNames.PARSE_INPUTS);
// TODO(lharker): do we actually need the synthetic externs file in stage 2?
if (this.typedAstFilesystem != null) {
this.typedAstFilesystem = ImmutableMap.of(SYNTHETIC_EXTERNS_FILE, this.typedAstFilesystem.get(SYNTHETIC_EXTERNS_FILE));
}
}
}
use of com.google.javascript.jscomp.deps.ModuleLoader.ModulePath in project closure-compiler by google.
the class TypeInference method traverseDynamicImport.
private FlowScope traverseDynamicImport(Node dynamicImport, FlowScope scope) {
JSType templateType = registry.getNativeType(JSTypeNative.UNKNOWN_TYPE);
// If the module specifier is a string, attempt to resolve the module
ModuleMap moduleMap = compiler.getModuleMap();
Node importSpecifier = dynamicImport.getFirstChild();
CompilerInput input = compiler.getInput(NodeUtil.getInputId(dynamicImport));
if (importSpecifier.isStringLit() && moduleMap != null && input != null) {
ModulePath targetPath = input.getPath().resolveJsModule(importSpecifier.getString(), importSpecifier.getSourceFileName(), importSpecifier.getLineno(), importSpecifier.getCharno());
Module targetModule = targetPath != null ? moduleMap.getModule(targetPath) : null;
if (targetModule != null) {
// TypedScopeCreator ensures that the MODULE_BODY type is the export namespace type
Node scriptNode = targetModule.metadata().rootNode();
if (scriptNode.hasOneChild() && scriptNode.getFirstChild().isModuleBody()) {
JSType exportNamespaceType = scriptNode != null ? scriptNode.getOnlyChild().getJSType() : null;
if (exportNamespaceType != null) {
templateType = exportNamespaceType;
}
} else {
// Module transpilation has occurred before type inference so a MODULE_BODY node
// no longer exists. Traverse the script to locate the module namespace variable
// and retrieve the type from it.
Node moduleName = NodeUtil.findPreorder(scriptNode, (node) -> node.matchesQualifiedName(targetPath.toModuleName()), Predicates.alwaysTrue());
if (moduleName != null && moduleName.getJSType() != null) {
templateType = moduleName.getJSType();
}
}
}
}
dynamicImport.setJSType(registry.createTemplatizedType(registry.getNativeObjectType(JSTypeNative.PROMISE_TYPE), templateType));
return traverseChildren(dynamicImport, scope);
}
Aggregations