Search in sources :

Example 1 with Binding

use of com.google.javascript.jscomp.modules.Binding 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();
}
Also used : Binding(com.google.javascript.jscomp.modules.Binding) ModulePath(com.google.javascript.jscomp.deps.ModuleLoader.ModulePath) Node(com.google.javascript.rhino.Node)

Example 2 with Binding

use of com.google.javascript.jscomp.modules.Binding in project closure-compiler by google.

the class PolymerBehaviorExtractor method resolveModuleNamespaceBinding.

/**
 * Resolves a name that imports the 'namespace' of a module or provide.
 */
private ResolveBehaviorNameResult resolveModuleNamespaceBinding(Binding b, String rest) {
    if (b.metadata().isGoogModule()) {
        return resolveBehaviorName(GOOG_MODULE_EXPORTS + rest, b.metadata());
    } else if (b.metadata().isGoogProvide()) {
        return resolveBehaviorName(b.closureNamespace() + rest, b.metadata());
    }
    // ES module import *.
    checkState(b.metadata().isEs6Module());
    if (rest.isEmpty()) {
        // The namespace imported by `import *` is never a @polymerBehavior.
        return FAILED_RESOLVE_RESULT;
    }
    // Remove leading '.'.
    rest = rest.substring(1);
    int dot = rest.indexOf('.');
    // Given:
    // `const internalName = 0; export {internalName as exportName};`
    // `import * as mod from './x'; use(mod.exportName.Behavior);`
    // 1. get the internal name `internalName` from` exportName`.
    // 2. then proceed to resolve `internalName.Behavior` in './x'.
    String exportedName = dot == -1 ? rest : rest.substring(0, dot);
    Module originalModule = moduleMap.getModule(b.metadata().path());
    Binding exportBinding = originalModule.namespace().get(exportedName);
    if (exportBinding == null || !exportBinding.isCreatedByEsExport()) {
        // This is an invalid import, and will cause an error elsewhere.
        return FAILED_RESOLVE_RESULT;
    }
    return resolveBehaviorName(exportBinding.originatingExport().localName() + (dot == -1 ? "" : rest.substring(dot)), b.metadata());
}
Also used : Binding(com.google.javascript.jscomp.modules.Binding) Module(com.google.javascript.jscomp.modules.Module)

Example 3 with Binding

use of com.google.javascript.jscomp.modules.Binding in project closure-compiler by google.

the class ModuleImportResolver method declareEsModuleImports.

/**
 * Declares/updates the type of all bindings imported into the ES module scope
 *
 * @return A map from local nodes to ScopedNames for which {@link #nodeToScopeMapper} couldn't
 *     find a scope, despite the original module existing. This is expected to happen for circular
 *     references if not all module scopes are created and the caller should handle declaring
 *     these names later, e.g. in TypedScopeCreator.
 */
Map<Node, ScopedName> declareEsModuleImports(Module module, TypedScope scope, CompilerInput moduleInput) {
    checkArgument(module.metadata().isEs6Module(), module);
    checkArgument(scope.isModuleScope(), scope);
    ImmutableMap.Builder<Node, ScopedName> missingNames = ImmutableMap.builder();
    for (Map.Entry<String, Binding> boundName : module.boundNames().entrySet()) {
        Binding binding = boundName.getValue();
        String localName = boundName.getKey();
        if (!binding.isCreatedByEsImport()) {
            continue;
        }
        // ES imports fall into two categories:
        // - namespace imports. These correspond to an object type containing all named exports.
        // - named imports. These always correspond, eventually, to a name local to a module.
        // Note that we include imports of an `export default` in this case and map them to a
        // pseudo-variable named *default*.
        ScopedName export = getScopedNameFromEsBinding(binding);
        TypedScope modScope = nodeToScopeMapper.apply(export.getScopeRoot());
        if (modScope == null) {
            checkState(binding.sourceNode().getString().equals(localName), binding.sourceNode());
            missingNames.put(binding.sourceNode(), export);
            continue;
        }
        TypedVar originalVar = modScope.getVar(export.getName());
        JSType importType = originalVar.getType();
        scope.declare(localName, binding.sourceNode(), importType, moduleInput, /* inferred= */
        originalVar.isTypeInferred());
        // export and import bindings, if not already there.
        if (!binding.isModuleNamespace() && binding.sourceNode().getTypedefTypeProp() == null) {
            JSType typedefType = originalVar.getNameNode().getTypedefTypeProp();
            if (typedefType != null) {
                binding.sourceNode().setTypedefTypeProp(typedefType);
                registry.declareType(scope, localName, typedefType);
            }
        }
    }
    return missingNames.buildOrThrow();
}
Also used : Binding(com.google.javascript.jscomp.modules.Binding) JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) ImmutableMap(com.google.common.collect.ImmutableMap) ModuleMap(com.google.javascript.jscomp.modules.ModuleMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 4 with Binding

use of com.google.javascript.jscomp.modules.Binding in project closure-compiler by google.

the class ModuleImportResolver method updateEsModuleNamespaceType.

/**
 * Declares or updates the type of properties representing exported names from ES module
 *
 * <p>When the given object type does not have existing properties corresponding to exported
 * names, this method adds new properties to the object type. If the object type already has
 * properties, this method will ignore declared properties and update the type of inferred
 * properties.
 *
 * <p>The additional properties will be inferred (instead of declared) if and only if {@link
 * TypedVar#isTypeInferred()} is true for the original exported name.
 *
 * <p>We create this type to support 'import *' and goog.requires of this module. Note: we could
 * lazily initialize this type if always creating it hurts performance.
 *
 * @param namespace An object type which may already have properties representing exported names.
 * @param scope The scope rooted at the given module.
 */
void updateEsModuleNamespaceType(ObjectType namespace, Module module, TypedScope scope) {
    checkArgument(module.metadata().isEs6Module(), module);
    checkArgument(scope.isModuleScope(), scope);
    for (Map.Entry<String, Binding> boundName : module.namespace().entrySet()) {
        String exportKey = boundName.getKey();
        if (namespace.isPropertyTypeDeclared(exportKey)) {
            // Cannot change the type of a declared property after it is added to the ObjectType.
            continue;
        }
        Binding binding = boundName.getValue();
        // e.g. 'x' in `export let x;` or `export {x};`
        Node bindingSourceNode = binding.sourceNode();
        ScopedName export = getScopedNameFromEsBinding(binding);
        TypedScope originalScope = export.getScopeRoot() == scope.getRootNode() ? scope : nodeToScopeMapper.apply(export.getScopeRoot());
        if (originalScope == null) {
            // Exporting an import from an invalid module load or early reference.
            namespace.defineInferredProperty(exportKey, registry.getNativeType(JSTypeNative.UNKNOWN_TYPE), bindingSourceNode);
            updateAstForExport(bindingSourceNode, registry.getNativeType(JSTypeNative.UNKNOWN_TYPE), /* typedefType= */
            null);
            continue;
        }
        TypedVar originalName = originalScope.getSlot(export.getName());
        JSType exportType = originalName.getType();
        if (exportType == null) {
            exportType = registry.getNativeType(JSTypeNative.NO_TYPE);
        }
        if (originalName.isTypeInferred()) {
            // NB: this method may be either adding a new inferred property or updating the type of an
            // existing inferred property.
            namespace.defineInferredProperty(exportKey, exportType, bindingSourceNode);
        } else {
            namespace.defineDeclaredProperty(exportKey, exportType, bindingSourceNode);
        }
        updateAstForExport(bindingSourceNode, exportType, originalName.getNameNode().getTypedefTypeProp());
    }
}
Also used : Binding(com.google.javascript.jscomp.modules.Binding) JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) ImmutableMap(com.google.common.collect.ImmutableMap) ModuleMap(com.google.javascript.jscomp.modules.ModuleMap) Map(java.util.Map)

Example 5 with Binding

use of com.google.javascript.jscomp.modules.Binding in project closure-compiler by google.

the class PolymerBehaviorExtractor method getNameIfModuleImport.

/**
 * Handles resolving behaviors whose root is imported from another module or a provide.
 *
 * <p>Returns null if the given name is not imported or {@link #FAILED_RESOLVE_RESULT} if it is
 * imported but is not annotated @polymerBehavior.
 */
private ResolveBehaviorNameResult getNameIfModuleImport(String name, ModuleMetadata metadata) {
    if (metadata == null || (!metadata.isEs6Module() && !metadata.isGoogModule())) {
        return null;
    }
    Module module = metadata.isGoogModule() ? moduleMap.getClosureModule(metadata.googNamespaces().asList().get(0)) : moduleMap.getModule(metadata.path());
    checkNotNull(module, metadata);
    int dot = name.indexOf('.');
    String root = dot == -1 ? name : name.substring(0, dot);
    Binding b = module.boundNames().get(root);
    if (b == null || !b.isSomeImport()) {
        return null;
    }
    String rest = dot == -1 ? "" : name.substring(dot);
    if (b.isModuleNamespace()) {
        // `import * as x from '';` or `const ns = goog.require('...`
        return resolveModuleNamespaceBinding(b, rest);
    }
    ModuleMetadata importMetadata = b.originatingExport().moduleMetadata();
    // The name in the module being imported
    String originatingName;
    if (importMetadata.isEs6Module()) {
        // import {exportName} from './mod';
        originatingName = b.originatingExport().localName() + rest;
    } else if (importMetadata.isGoogModule()) {
        // `const {exportName: localName} = goog.require('some.module');`
        originatingName = GOOG_MODULE_EXPORTS + "." + b.originatingExport().exportName() + rest;
    } else {
        // `const {exportName: localName} = goog.require('some.provide');`
        checkState(importMetadata.isGoogProvide(), importMetadata);
        originatingName = b.closureNamespace() + "." + b.originatingExport().exportName() + rest;
    }
    return resolveBehaviorName(originatingName, importMetadata);
}
Also used : Binding(com.google.javascript.jscomp.modules.Binding) ModuleMetadata(com.google.javascript.jscomp.modules.ModuleMetadataMap.ModuleMetadata) Module(com.google.javascript.jscomp.modules.Module)

Aggregations

Binding (com.google.javascript.jscomp.modules.Binding)6 Node (com.google.javascript.rhino.Node)4 Module (com.google.javascript.jscomp.modules.Module)3 ModuleMap (com.google.javascript.jscomp.modules.ModuleMap)3 Map (java.util.Map)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 JSType (com.google.javascript.rhino.jstype.JSType)2 ModulePath (com.google.javascript.jscomp.deps.ModuleLoader.ModulePath)1 ModuleMetadataMap (com.google.javascript.jscomp.modules.ModuleMetadataMap)1 ModuleMetadata (com.google.javascript.jscomp.modules.ModuleMetadataMap.ModuleMetadata)1 JSDocInfo (com.google.javascript.rhino.JSDocInfo)1 JSTypeExpression (com.google.javascript.rhino.JSTypeExpression)1 QualifiedName (com.google.javascript.rhino.QualifiedName)1 HashMap (java.util.HashMap)1