All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.javascript.jscomp.RemoveUnnecessarySyntheticExterns Maven / Gradle / Ivy

Go to download

Closure Compiler is a JavaScript optimizing compiler. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls. It is used in many of Google's JavaScript apps, including Gmail, Google Web Search, Google Maps, and Google Docs.

There is a newer version: v20240317
Show newest version
/*
 * Copyright 2021 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.javascript.jscomp;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.javascript.jscomp.SyntacticScopeCreator.RedeclarationHandler;
import com.google.javascript.rhino.Node;
import java.util.LinkedHashSet;

/**
 * Deletes name declarations from synthetic externs if they are in fact declared in source
 *
 * 

The VarCheck pass will create synthetic extern declarations (`var someName;`) for every * variable name referenced without a corresponding externs or code declaration. Such names are * "unfulfilled". VarCheck only does this because later compiler passes expect the following * invariant to hold: all variable names referenced in externs or code are also declared in externs * or code. * *

When running optimizations based on precompiled TypedAST library shards, it's possible for a * name to be unfulfilled in shard A, but declared in another shard B. Shard B "fulfills" the * reference from shard A. This pass removes the corresponding synthetic extern that came from shard * A now that the name is fulfilled. The purpose is to improve optimizations, e.g. to allow mangling * the name if it is not defined in externs. */ final class RemoveUnnecessarySyntheticExterns implements CompilerPass { private final AbstractCompiler compiler; private final LinkedHashSet nodesToDetach = new LinkedHashSet<>(); RemoveUnnecessarySyntheticExterns(AbstractCompiler compiler) { this.compiler = compiler; } @Override public void process(Node externs, Node root) { Node globalRoot = externs.getParent(); ScopeCreator scopeCreator = new SyntacticScopeCreator(compiler, new RedeclarationCheckHandler()); // This call will invoke the RedeclarationCheckHandler on duplicate synthetic names scopeCreator.createScope(globalRoot, /* parent= */ null); if (nodesToDetach.isEmpty()) { return; } for (Node n : nodesToDetach) { n.detach(); } Node syntheticExternsScript = compiler.getSynthesizedExternsInput().getAstRoot(compiler); compiler.reportChangeToEnclosingScope(syntheticExternsScript); } /** The handler for duplicate declarations. */ private class RedeclarationCheckHandler implements RedeclarationHandler { @Override public void onRedeclaration(Scope s, String name, Node n, CompilerInput input) { checkArgument(s.isGlobal(), "Unexpected non-global redeclaration %s in scope %s", n, s); boolean isSynthetic = input.equals(compiler.getSynthesizedExternsInput()); Var origVar = s.getVar(name); // origNode will be null for `arguments`, since there's no node that declares it. Node origNode = origVar.getNode(); if (isSynthetic) { // Delete duplicate unfulfilled synthetic declarations. // The original declaration will be deleted later iff it's also synthetic and we visit a // non-synthetic duplicate declaration. if (n.getParent().isSynthesizedUnfulfilledNameDeclaration()) { nodesToDetach.add(n.getParent()); } } else if (origNode != null && origNode.getParent().isSynthesizedUnfulfilledNameDeclaration()) { // Found a synthetic extern declaration that's fulfilled by some non-synthetic code. nodesToDetach.add(origNode.getParent()); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy