use of com.google.javascript.jscomp.modules.Module in project closure-compiler by google.
the class Es6RewriteModules method visitScript.
private void visitScript(NodeTraversal t, Node script) {
final Node moduleBody = script.getFirstChild();
// TypedScopeCreator sets the module object type on the MODULE_BODY during type checking.
final AstFactory.Type moduleObjectType = type(moduleBody);
inlineModuleToGlobalScope(moduleBody);
ClosureRewriteModule.checkAndSetStrictModeDirective(t, script);
Module thisModule = moduleMap.getModule(t.getInput().getPath());
QualifiedName qualifiedName = ModuleRenaming.getGlobalName(thisModule.metadata(), /* googNamespace= */
null);
checkState(qualifiedName.isSimple(), "Unexpected qualified name %s", qualifiedName);
String moduleName = qualifiedName.getRoot();
Node moduleVar = createExportsObject(moduleName, t, script, moduleObjectType);
// Rename vars to not conflict in global scope.
NodeTraversal.traverse(compiler, script, new RenameGlobalVars(thisModule));
// Rename the exports object to something we can reference later.
moduleVar.getFirstChild().setString(moduleName);
moduleVar.makeNonIndexableRecursive();
declareGlobalVariable(moduleVar.getFirstChild(), t);
// rewriteRequires is here (rather than being part of the main visit() method, because we only
// want to rewrite the requires if this is an ES6 module. Note that we also want to do this
// AFTER renaming all module scoped vars in the event that something that is goog.require'd is
// a global, unqualified name (e.g. if "goog.provide('foo')" exists, we don't want to rewrite
// "const foo = goog.require('foo')" to "const foo = foo". If we rewrite our module scoped names
// first then we'll rewrite to "const foo$module$fudge = goog.require('foo')", then to
// "const foo$module$fudge = foo".
rewriteRequires(script);
t.reportCodeChange();
}
use of com.google.javascript.jscomp.modules.Module in project closure-compiler by google.
the class Es6RewriteModules method createExportsObject.
private Node createExportsObject(String moduleName, NodeTraversal t, Node script, AstFactory.Type moduleObjectType) {
Node moduleObject = astFactory.createObjectLit(moduleObjectType);
// Going to get renamed by RenameGlobalVars, so the name we choose here doesn't matter as long
// as it doesn't collide with an existing variable. (We can't use `moduleName` since then
// RenameGlobalVars will rename all references to `moduleName` incorrectly). We'll fix the name
// in visitScript after the global renaming to ensure it has a name that is deterministic from
// the path.
//
// So after this method we'll have:
// var $jscomp$tmp$exports$module$name = {};
// module$name.exportName = localName;
//
// After RenameGlobalVars:
// var $jscomp$tmp$exports$module$nameglobalized = {};
// module$name.exportName = localName$globalized;
//
// After visitScript:
// var module$name = {};
// module$name.exportName = localName$globalized;
Node moduleVar = astFactory.createSingleVarNameDeclaration("$jscomp$tmp$exports$module$name", moduleObject);
moduleVar.getFirstChild().putBooleanProp(Node.MODULE_EXPORT, true);
// TODO(b/144593112): Stop adding JSDoc when this pass moves to always be after typechecking.
JSDocInfo.Builder infoBuilder = JSDocInfo.builder();
infoBuilder.recordConstancy();
moduleVar.setJSDocInfo(infoBuilder.build());
moduleVar.getFirstChild().setDeclaredConstantVar(true);
script.addChildToBack(moduleVar.srcrefTreeIfMissing(script));
Module thisModule = moduleMap.getModule(t.getInput().getPath());
for (Map.Entry<String, Binding> entry : thisModule.namespace().entrySet()) {
String exportedName = entry.getKey();
Binding binding = entry.getValue();
Node nodeForSourceInfo = binding.sourceNode();
boolean mutated = binding.isMutated();
QualifiedName boundVariableQualifiedName = ModuleRenaming.getGlobalName(binding);
checkState(boundVariableQualifiedName.isSimple(), "unexpected qualified name: %s", boundVariableQualifiedName);
String boundVariableName = boundVariableQualifiedName.getRoot();
Node getProp = astFactory.createGetPropWithoutColor(astFactory.createName(moduleName, moduleObjectType), exportedName);
getProp.putBooleanProp(Node.MODULE_EXPORT, true);
if (typedefs.contains(exportedName)) {
// /** @typedef {foo} */
// moduleName.foo;
JSDocInfo.Builder builder = JSDocInfo.builder().parseDocumentation();
JSTypeExpression typeExpr = new JSTypeExpression(astFactory.createString(exportedName).srcref(nodeForSourceInfo), script.getSourceFileName());
builder.recordTypedef(typeExpr);
JSDocInfo info = builder.build();
getProp.setJSDocInfo(info);
Node exprResult = astFactory.exprResult(getProp).srcrefTreeIfMissing(nodeForSourceInfo);
script.addChildToBack(exprResult);
} else if (mutated) {
final Node globalExportName = astFactory.createName(boundVariableName, type(getProp));
addGetterExport(script, nodeForSourceInfo, moduleObject, exportedName, globalExportName);
NodeUtil.addFeatureToScript(t.getCurrentScript(), Feature.GETTER, compiler);
} else {
// Avoid the extra complexity of using getters when the property isn't mutated.
// exports.foo = foo;
Node assign = astFactory.createAssign(getProp, astFactory.createName(boundVariableName, type(getProp)));
// TODO(b/144593112): Stop adding JSDoc when this pass moves to always be after typechecking
JSDocInfo.Builder builder = JSDocInfo.builder().parseDocumentation();
builder.recordConstancy();
JSDocInfo info = builder.build();
assign.setJSDocInfo(info);
script.addChildToBack(astFactory.exprResult(assign).srcrefTreeIfMissing(nodeForSourceInfo));
}
}
return moduleVar;
}
use of com.google.javascript.jscomp.modules.Module in project closure-compiler by google.
the class ModuleImportResolver method getClosureNamespaceTypeFromCall.
/**
* Attempts to look up the type of a Closure namespace from a require call
*
* <p>This returns null if the given {@link ModuleMap} is null, if the required module does not
* exist, or if support is missing for the type of required {@link Module}. Currently only
* requires of goog.modules, goog.provides, and ES module with goog.declareModuleId are supported.
*
* @param googRequire a CALL node representing some kind of Closure require.
*/
ScopedName getClosureNamespaceTypeFromCall(Node googRequire) {
if (moduleMap == null) {
// TODO(b/124919359): make sure all tests have generated a ModuleMap
return null;
}
String moduleId = googRequire.getSecondChild().getString();
Module module = moduleMap.getClosureModule(moduleId);
if (module == null) {
return null;
}
switch(module.metadata().moduleType()) {
case GOOG_PROVIDE:
// Expect this to be a global variable
Node provide = module.metadata().rootNode();
if (provide != null && provide.isScript()) {
return ScopedName.of(moduleId, provide.getGrandparent());
} else {
// Unknown module requires default to 'goog provides', but we don't want to type them.
return null;
}
case GOOG_MODULE:
case LEGACY_GOOG_MODULE:
// TODO(b/124919359): Fix getGoogModuleScopeRoot to never return null.
Node scopeRoot = getGoogModuleScopeRoot(module);
return scopeRoot != null ? ScopedName.of("exports", scopeRoot) : null;
case ES6_MODULE:
// SCRIPT -> MODULE_BODY
Node moduleBody = module.metadata().rootNode().getFirstChild();
return ScopedName.of(Export.NAMESPACE, moduleBody);
case COMMON_JS:
throw new IllegalStateException("Type checking CommonJs modules not yet supported");
case SCRIPT:
throw new IllegalStateException("Cannot import a name from a SCRIPT");
}
throw new AssertionError();
}
use of com.google.javascript.jscomp.modules.Module in project closure-compiler by google.
the class ModuleImportResolver method getModuleFromScopeRoot.
/**
* Returns the {@link Module} corresponding to this scope root, or null if not a module root.
*/
@Nullable
static Module getModuleFromScopeRoot(ModuleMap moduleMap, CompilerInputProvider inputProvider, Node moduleBody) {
if (isGoogModuleBody(moduleBody)) {
Node googModuleCall = moduleBody.getFirstChild();
String namespace = googModuleCall.getFirstChild().getSecondChild().getString();
return moduleMap.getClosureModule(namespace);
} else if (moduleBody.isModuleBody()) {
Node scriptNode = moduleBody.getParent();
CompilerInput input = checkNotNull(inputProvider.getInput(scriptNode.getInputId()));
Module module = moduleMap.getModule(input.getPath());
// TODO(b/131418081): Also cover CommonJS modules.
checkState(module.metadata().isEs6Module(), "Typechecking of non-goog- and non-es-modules not supported");
return module;
}
return null;
}
use of com.google.javascript.jscomp.modules.Module in project closure-compiler by google.
the class RewriteGoogJsImports method changeModules.
private void changeModules() {
ImmutableMap.Builder<String, Module> resolvedModules = ImmutableMap.builder();
ImmutableMap.Builder<String, Module> closureModules = ImmutableMap.builder();
for (Map.Entry<String, Module> m : moduleMap.getModulesByPath().entrySet()) {
Module newModule = moduleReplacements.getOrDefault(m.getValue(), m.getValue());
resolvedModules.put(m.getKey(), newModule);
}
for (Map.Entry<String, Module> m : moduleMap.getModulesByClosureNamespace().entrySet()) {
Module newModule = moduleReplacements.getOrDefault(m.getValue(), m.getValue());
closureModules.put(m.getKey(), newModule);
}
compiler.setModuleMap(new ModuleMap(resolvedModules.buildOrThrow(), closureModules.buildOrThrow()));
moduleReplacements.clear();
}
Aggregations