Search in sources :

Example 11 with Module

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();
}
Also used : Node(com.google.javascript.rhino.Node) QualifiedName(com.google.javascript.rhino.QualifiedName) Module(com.google.javascript.jscomp.modules.Module)

Example 12 with Module

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;
}
Also used : Binding(com.google.javascript.jscomp.modules.Binding) Node(com.google.javascript.rhino.Node) QualifiedName(com.google.javascript.rhino.QualifiedName) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) JSDocInfo(com.google.javascript.rhino.JSDocInfo) Module(com.google.javascript.jscomp.modules.Module) ModuleMetadataMap(com.google.javascript.jscomp.modules.ModuleMetadataMap) HashMap(java.util.HashMap) Map(java.util.Map) ModuleMap(com.google.javascript.jscomp.modules.ModuleMap)

Example 13 with Module

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();
}
Also used : Node(com.google.javascript.rhino.Node) Module(com.google.javascript.jscomp.modules.Module)

Example 14 with Module

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;
}
Also used : Node(com.google.javascript.rhino.Node) Module(com.google.javascript.jscomp.modules.Module) Nullable(javax.annotation.Nullable)

Example 15 with Module

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();
}
Also used : Module(com.google.javascript.jscomp.modules.Module) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ModuleMap(com.google.javascript.jscomp.modules.ModuleMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ModuleMap(com.google.javascript.jscomp.modules.ModuleMap)

Aggregations

Module (com.google.javascript.jscomp.modules.Module)16 Node (com.google.javascript.rhino.Node)11 QualifiedName (com.google.javascript.rhino.QualifiedName)5 ModuleMap (com.google.javascript.jscomp.modules.ModuleMap)4 Binding (com.google.javascript.jscomp.modules.Binding)3 JSType (com.google.javascript.rhino.jstype.JSType)3 ModulePath (com.google.javascript.jscomp.deps.ModuleLoader.ModulePath)2 ModuleMetadata (com.google.javascript.jscomp.modules.ModuleMetadataMap.ModuleMetadata)2 JSDocInfo (com.google.javascript.rhino.JSDocInfo)2 ObjectType (com.google.javascript.rhino.jstype.ObjectType)2 StaticTypedScope (com.google.javascript.rhino.jstype.StaticTypedScope)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 Nullable (javax.annotation.Nullable)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 CheckReturnValue (com.google.errorprone.annotations.CheckReturnValue)1 Name (com.google.javascript.jscomp.GlobalNamespace.Name)1 Ref (com.google.javascript.jscomp.GlobalNamespace.Ref)1 ModuleMetadataMap (com.google.javascript.jscomp.modules.ModuleMetadataMap)1 FlowScope (com.google.javascript.jscomp.type.FlowScope)1