Search in sources :

Example 11 with FeatureSet

use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.

the class PolymerClassRewriter method rewritePolymerCall.

/**
 * Rewrites a given call to Polymer({}) to a set of declarations and assignments which can be
 * understood by the compiler.
 *
 * @param exprRoot The root expression of the call to Polymer({}).
 * @param cls The extracted {@link PolymerClassDefinition} for the Polymer element created by this
 *     call.
 */
void rewritePolymerCall(Node exprRoot, final PolymerClassDefinition cls, boolean isInGlobalScope) {
    Node objLit = checkNotNull(cls.descriptor);
    // Add {@code @lends} to the object literal.
    JSDocInfoBuilder objLitDoc = new JSDocInfoBuilder(true);
    objLitDoc.recordLends(cls.target.getQualifiedName() + ".prototype");
    objLit.setJSDocInfo(objLitDoc.build());
    addTypesToFunctions(objLit, cls.target.getQualifiedName(), cls.defType);
    PolymerPassStaticUtils.switchDollarSignPropsToBrackets(objLit, compiler);
    PolymerPassStaticUtils.quoteListenerAndHostAttributeKeys(objLit, compiler);
    for (MemberDefinition prop : cls.props) {
        if (prop.value.isObjectLit()) {
            PolymerPassStaticUtils.switchDollarSignPropsToBrackets(prop.value, compiler);
        }
    }
    // For simplicity add everything into a block, before adding it to the AST.
    Node block = IR.block();
    JSDocInfoBuilder constructorDoc = this.getConstructorDoc(cls);
    // Remove the original constructor JS docs from the objlit.
    Node ctorKey = cls.constructor.value.getParent();
    if (ctorKey != null) {
        ctorKey.removeProp(Node.JSDOC_INFO_PROP);
    }
    if (cls.target.isGetProp()) {
        // foo.bar = Polymer({...});
        Node assign = IR.assign(cls.target.cloneTree(), cls.constructor.value.cloneTree());
        NodeUtil.markNewScopesChanged(assign, compiler);
        assign.setJSDocInfo(constructorDoc.build());
        Node exprResult = IR.exprResult(assign);
        exprResult.useSourceInfoIfMissingFromForTree(cls.target);
        block.addChildToBack(exprResult);
    } else {
        // var foo = Polymer({...}); OR Polymer({...});
        Node var = IR.var(cls.target.cloneTree(), cls.constructor.value.cloneTree());
        NodeUtil.markNewScopesChanged(var, compiler);
        var.useSourceInfoIfMissingFromForTree(exprRoot);
        var.setJSDocInfo(constructorDoc.build());
        block.addChildToBack(var);
    }
    appendPropertiesToBlock(cls, block, cls.target.getQualifiedName() + ".prototype.");
    appendBehaviorMembersToBlock(cls, block);
    ImmutableList<MemberDefinition> readOnlyProps = parseReadOnlyProperties(cls, block);
    ImmutableList<MemberDefinition> attributeReflectedProps = parseAttributeReflectedProperties(cls);
    addInterfaceExterns(cls, readOnlyProps, attributeReflectedProps);
    removePropertyDocs(objLit, PolymerClassDefinition.DefinitionType.ObjectLiteral);
    Node statements = block.removeChildren();
    Node parent = exprRoot.getParent();
    // global.
    if (this.polymerVersion == 1 && !isInGlobalScope && !cls.target.isGetProp()) {
        Node scriptNode = NodeUtil.getEnclosingScript(parent);
        scriptNode.addChildrenToFront(statements);
        compiler.reportChangeToChangeScope(scriptNode);
    } else {
        Node beforeRoot = exprRoot.getPrevious();
        if (beforeRoot == null) {
            parent.addChildrenToFront(statements);
        } else {
            parent.addChildrenAfter(statements, beforeRoot);
        }
        compiler.reportChangeToEnclosingScope(parent);
    }
    compiler.reportChangeToEnclosingScope(statements);
    // we might need to update the FeatureSet.
    if (cls.features != null) {
        Node scriptNode = NodeUtil.getEnclosingScript(parent);
        FeatureSet oldFeatures = (FeatureSet) scriptNode.getProp(Node.FEATURE_SET);
        FeatureSet newFeatures = oldFeatures.union(cls.features);
        if (!newFeatures.equals(oldFeatures)) {
            scriptNode.putProp(Node.FEATURE_SET, newFeatures);
            compiler.reportChangeToChangeScope(scriptNode);
        }
    }
    if (NodeUtil.isNameDeclaration(exprRoot)) {
        Node assignExpr = varToAssign(exprRoot);
        parent.replaceChild(exprRoot, assignExpr);
        compiler.reportChangeToEnclosingScope(assignExpr);
    }
    // with the class members.
    if (polymerVersion > 1 && propertyRenamingEnabled && cls.descriptor != null) {
        Node props = NodeUtil.getFirstPropMatchingKey(cls.descriptor, "properties");
        if (props != null && props.isObjectLit()) {
            addObjectReflectionCall(cls, props);
        }
    }
}
Also used : Node(com.google.javascript.rhino.Node) FeatureSet(com.google.javascript.jscomp.parsing.parser.FeatureSet) JSDocInfoBuilder(com.google.javascript.rhino.JSDocInfoBuilder) MemberDefinition(com.google.javascript.jscomp.PolymerPass.MemberDefinition)

Example 12 with FeatureSet

use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.

the class PolymerBehaviorExtractor method extractBehaviors.

/**
 * Extracts all Behaviors from an array literal, recursively. Entries in the array can be object
 * literals or array literals (of other behaviors). Behavior names must be global, fully qualified
 * names. TODO(rishipal): Make this function better handle case where the same behavior
 * transitively gets included in the same Polymer element more than once.
 *
 * @see https://github.com/Polymer/polymer/blob/0.8-preview/PRIMER.md#behaviors
 * @param moduleMetadata The module in which these behaviors are being resolved, or null if not in
 *     a module.
 * @return A list of all {@code BehaviorDefinitions} in the array.
 */
ImmutableList<BehaviorDefinition> extractBehaviors(Node behaviorArray, @Nullable ModuleMetadata moduleMetadata) {
    if (behaviorArray == null) {
        return ImmutableList.of();
    }
    if (!behaviorArray.isArrayLit()) {
        compiler.report(JSError.make(behaviorArray, PolymerPassErrors.POLYMER_INVALID_BEHAVIOR_ARRAY));
        return ImmutableList.of();
    }
    ImmutableList.Builder<BehaviorDefinition> behaviors = ImmutableList.builder();
    for (Node behaviorName = behaviorArray.getFirstChild(); behaviorName != null; behaviorName = behaviorName.getNext()) {
        if (behaviorName.isObjectLit()) {
            PolymerPassStaticUtils.switchDollarSignPropsToBrackets(behaviorName, compiler);
            PolymerPassStaticUtils.quoteListenerAndHostAttributeKeys(behaviorName, compiler);
            if (NodeUtil.getFirstPropMatchingKey(behaviorName, "is") != null) {
                compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_INVALID_BEHAVIOR));
            }
            Node behaviorModule = NodeUtil.getEnclosingModuleIfPresent(behaviorName);
            behaviors.add(new BehaviorDefinition(PolymerPassStaticUtils.extractProperties(behaviorName, PolymerClassDefinition.DefinitionType.ObjectLiteral, compiler, /* constructor= */
            null), getBehaviorFunctionsToCopy(behaviorName), getNonPropertyMembersToCopy(behaviorName), /* isGlobalDeclaration= */
            NodeUtil.getEnclosingScopeRoot(behaviorName).isRoot(), (FeatureSet) NodeUtil.getEnclosingScript(behaviorName).getProp(Node.FEATURE_SET), behaviorModule));
            continue;
        }
        ResolveBehaviorNameResult resolveResult;
        if (isGoogModuleGetCall(behaviorName)) {
            resolveResult = resolveGoogModuleGet(behaviorName.getSecondChild().getString());
        } else {
            resolveResult = resolveBehaviorName(getQualifiedNameThroughCast(behaviorName), moduleMetadata);
        }
        if (resolveResult.equals(FAILED_RESOLVE_RESULT)) {
            compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_UNQUALIFIED_BEHAVIOR));
            continue;
        }
        Node behaviorValue = resolveResult.node;
        if (behaviorValue.isArrayLit()) {
            // Individual behaviors can also be arrays of behaviors. Parse them recursively.
            behaviors.addAll(extractBehaviors(behaviorValue, resolveResult.moduleMetadata));
        } else if (behaviorValue.isObjectLit()) {
            PolymerPassStaticUtils.switchDollarSignPropsToBrackets(behaviorValue, compiler);
            PolymerPassStaticUtils.quoteListenerAndHostAttributeKeys(behaviorValue, compiler);
            if (NodeUtil.getFirstPropMatchingKey(behaviorValue, "is") != null) {
                compiler.report(JSError.make(behaviorValue, PolymerPassErrors.POLYMER_INVALID_BEHAVIOR));
            }
            Node behaviorModule = NodeUtil.getEnclosingModuleIfPresent(behaviorValue);
            behaviors.add(new BehaviorDefinition(PolymerPassStaticUtils.extractProperties(behaviorValue, PolymerClassDefinition.DefinitionType.ObjectLiteral, compiler, /* constructor= */
            null), getBehaviorFunctionsToCopy(behaviorValue), getNonPropertyMembersToCopy(behaviorValue), resolveResult.isGlobalDeclaration, (FeatureSet) NodeUtil.getEnclosingScript(behaviorValue).getProp(Node.FEATURE_SET), behaviorModule));
        } else {
            compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_UNQUALIFIED_BEHAVIOR));
        }
    }
    return behaviors.build();
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) Node(com.google.javascript.rhino.Node) FeatureSet(com.google.javascript.jscomp.parsing.parser.FeatureSet)

Example 13 with FeatureSet

use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.

the class InjectTranspilationRuntimeLibraries method process.

@Override
public void process(Node externs, Node root) {
    FeatureSet used = FeatureSet.ES3;
    for (Node script = root.getFirstChild(); script != null; script = script.getNext()) {
        used = used.with(getScriptFeatures(script));
    }
    FeatureSet outputFeatures = compiler.getOptions().getOutputFeatureSet();
    // Check for references to global `Symbol` and getters/setters
    if (!outputFeatures.contains(used)) {
        NodeTraversal.traverse(compiler, root, this);
    }
    FeatureSet mustBeCompiledAway = used.without(outputFeatures);
    if (mustBeCompiledAway.contains(Feature.TEMPLATE_LITERALS)) {
        Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "createtemplatetagfirstarg");
    }
    if (mustBeCompiledAway.contains(Feature.FOR_OF) || mustBeCompiledAway.contains(Feature.ARRAY_DESTRUCTURING) || mustBeCompiledAway.contains(Feature.OBJECT_PATTERN_REST)) {
        // `makeIterator` isn't needed directly for `OBJECT_PATTERN_REST`, but when we transpile
        // a destructuring case that contains it, we transpile the entire destructured assignment,
        // which may also include `ARRAY_DESTRUCTURING`.
        Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "makeIterator");
    }
    if (mustBeCompiledAway.contains(Feature.ARRAY_PATTERN_REST)) {
        Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "arrayFromIterator");
    }
    if (mustBeCompiledAway.contains(Feature.SPREAD_EXPRESSIONS) || mustBeCompiledAway.contains(Feature.CLASS_EXTENDS)) {
        // We must automatically generate the default constructor for descendent classes,
        // and those must call super(...arguments), so we end up injecting our own spread
        // expressions for such cases.
        Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "arrayFromIterable");
    }
    if ((mustBeCompiledAway.contains(Feature.OBJECT_LITERALS_WITH_SPREAD) || mustBeCompiledAway.contains(Feature.OBJECT_PATTERN_REST)) && !outputFeatures.contains(FeatureSet.ES2015)) {
        // We need `Object.assign` to transpile `obj = {a, ...rest};` or `const {a, ...rest} = obj;`,
        // but the output language level doesn't indicate that it is guaranteed to be present, so
        // we'll include our polyfill.
        compiler.ensureLibraryInjected("es6/object/assign", /* force= */
        false);
    }
    if (mustBeCompiledAway.contains(Feature.CLASS_EXTENDS)) {
        Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "construct");
        Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "inherits");
    }
    if (mustBeCompiledAway.contains(Feature.CLASS_GETTER_SETTER)) {
        compiler.ensureLibraryInjected("util/global", /* force= */
        false);
    }
    if (mustBeCompiledAway.contains(Feature.GENERATORS)) {
        compiler.ensureLibraryInjected("es6/generator_engine", /* force= */
        false);
    }
    if (mustBeCompiledAway.contains(Feature.ASYNC_FUNCTIONS)) {
        compiler.ensureLibraryInjected("es6/execute_async_generator", /* force= */
        false);
    }
    if (mustBeCompiledAway.contains(Feature.ASYNC_GENERATORS)) {
        compiler.ensureLibraryInjected("es6/async_generator_wrapper", /* force= */
        false);
    }
    if (mustBeCompiledAway.contains(Feature.FOR_AWAIT_OF)) {
        compiler.ensureLibraryInjected("es6/util/makeasynciterator", /* force= */
        false);
    }
    if (mustBeCompiledAway.contains(Feature.REST_PARAMETERS)) {
        compiler.ensureLibraryInjected("es6/util/restarguments", /* force= */
        false);
    }
}
Also used : Node(com.google.javascript.rhino.Node) FeatureSet(com.google.javascript.jscomp.parsing.parser.FeatureSet)

Example 14 with FeatureSet

use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.

the class NodeUtil method addFeatureToScript.

/**
 * Adds the given features to a SCRIPT node's FeatureSet property.
 *
 * <p>Also updates the compiler's FeatureSet.
 */
static void addFeatureToScript(Node scriptNode, Feature feature, AbstractCompiler compiler) {
    checkState(scriptNode.isScript(), scriptNode);
    FeatureSet currentFeatures = getFeatureSetOfScript(scriptNode);
    FeatureSet newFeatures = currentFeatures != null ? currentFeatures.with(feature) : FeatureSet.BARE_MINIMUM.with(feature);
    scriptNode.putProp(Node.FEATURE_SET, newFeatures);
    compiler.setFeatureSet(compiler.getFeatureSet().with(feature));
}
Also used : FeatureSet(com.google.javascript.jscomp.parsing.parser.FeatureSet)

Example 15 with FeatureSet

use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.

the class RewritePolyfills method removeUnneededPolyfills.

// Remove any $jscomp.polyfill calls whose 3rd parameter (the language version
// that already contains the library) is the same or lower than languageOut.
private void removeUnneededPolyfills(Node parent, Node runtimeEnd) {
    Node node = parent.getFirstChild();
    // The target environment is assumed to support the features in this set.
    final FeatureSet outputFeatureSet = compiler.getOptions().getOutputFeatureSet();
    while (node != null && node != runtimeEnd) {
        // look up the next node now, because we may be removing this one.
        Node next = node.getNext();
        FeatureSet polyfillSupportedFeatureSet = getPolyfillSupportedFeatureSet(node);
        if (polyfillSupportedFeatureSet != null && outputFeatureSet.contains(polyfillSupportedFeatureSet)) {
            NodeUtil.removeChild(parent, node);
            NodeUtil.markFunctionsDeleted(node, compiler);
        }
        node = next;
    }
}
Also used : Node(com.google.javascript.rhino.Node) FeatureSet(com.google.javascript.jscomp.parsing.parser.FeatureSet)

Aggregations

FeatureSet (com.google.javascript.jscomp.parsing.parser.FeatureSet)17 Node (com.google.javascript.rhino.Node)14 MemberDefinition (com.google.javascript.jscomp.PolymerPass.MemberDefinition)4 JSDocInfo (com.google.javascript.rhino.JSDocInfo)4 Nullable (javax.annotation.Nullable)3 ImmutableList (com.google.common.collect.ImmutableList)2 BehaviorDefinition (com.google.javascript.jscomp.PolymerBehaviorExtractor.BehaviorDefinition)2 ArrayList (java.util.ArrayList)2 Name (com.google.javascript.jscomp.GlobalNamespace.Name)1 Ref (com.google.javascript.jscomp.GlobalNamespace.Ref)1 Polyfill (com.google.javascript.jscomp.PolyfillUsageFinder.Polyfill)1 Parser (com.google.javascript.jscomp.parsing.parser.Parser)1 SourceFile (com.google.javascript.jscomp.parsing.parser.SourceFile)1 Comment (com.google.javascript.jscomp.parsing.parser.trees.Comment)1 ProgramTree (com.google.javascript.jscomp.parsing.parser.trees.ProgramTree)1 JSDocInfoBuilder (com.google.javascript.rhino.JSDocInfoBuilder)1 JSTypeExpression (com.google.javascript.rhino.JSTypeExpression)1 StaticSourceFile (com.google.javascript.rhino.StaticSourceFile)1 LinkedHashMap (java.util.LinkedHashMap)1 TreeMap (java.util.TreeMap)1