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

com.google.javascript.jscomp.bundle.Source 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 2017 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.bundle;

import static java.util.Arrays.asList;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.CheckReturnValue;
import com.google.errorprone.annotations.Immutable;
import com.google.javascript.jscomp.deps.DependencyInfo;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.function.Function;
import org.jspecify.nullness.Nullable;

/** An abstract representation of a source file. */
@AutoValue
@GwtIncompatible
@Immutable
public abstract class Source {

  /** The path of this source. This may refer to a path on disk or a path on the HTTP server. */
  public abstract Path path();
  /** The text of any source map applicable to this file. */
  public abstract String sourceMap();
  /** The source URL associated with this file. */
  public abstract String sourceUrl();
  /** The URL for a source map associated with this file. */
  public abstract String sourceMappingUrl();
  /**
   * Any runtime libraries necessary for this source. Any transformation that adds a runtime library
   * to any sources must be responsible to never add the same library as a substring to a different
   * source (so that the "no duplicates" invariant of Set will work correctly).
   */
  public abstract ImmutableSet runtimes();
  /** The load flags, specifying module type and language level. */
  public abstract ImmutableMap loadFlags();
  /** A best estimate of the size of this source (in case the source itself is not yet loaded. */
  public abstract int estimatedSize();

  /** The actual code in this source file. */
  public final String code() {
    return codeSupplier().get();
  }

  /** The untransformed code from the original source file. */
  public final String originalCode() {
    return originalCodeSupplier().get();
  }

  /** Copies the data from this source to a new builder. */
  public abstract Builder toBuilder();

  /** Makes a new empty builder. */
  public static Builder builder() {
    return new AutoValue_Source.Builder()
        .setPath(DEV_NULL)
        .setCode("")
        .setOriginalCodeSupplier(null)
        .setSourceMap("")
        .setSourceUrl("")
        .setSourceMappingUrl("")
        .setRuntimes(ImmutableSet.of())
        .setLoadFlags(ImmutableMap.of())
        .setEstimatedSize(0);
  }

  private static final Path DEV_NULL = Paths.get("/dev/null");

  // Internal-only properties: the code suppliers are necessary for lazy bundling,
  // but we cannot use an ordinary supplier since we need guarantees about equals and
  // hash code.  Thus, we use an internal-only Supplier subtype.
  abstract Lazy codeSupplier();

  abstract @Nullable Lazy originalCodeSupplier();

  /** Builder for Source instances. */
  @AutoValue.Builder
  @GwtIncompatible
  public abstract static class Builder {
    public abstract Builder setPath(Path path);
    public abstract Builder setSourceMap(String sourceMap);
    public abstract Builder setSourceUrl(String sourceUrl);
    public abstract Builder setSourceMappingUrl(String sourceMappingUrl);
    public abstract Builder setRuntimes(ImmutableSet runtimes);
    public abstract Builder setLoadFlags(ImmutableMap flags);
    public abstract Builder setEstimatedSize(int estimatedSize);

    public final Builder setCode(Supplier code) {
      return setCodeSupplier(Lazy.memoize(code));
    }

    public final Builder setCode(String code) {
      return setCodeSupplier(Lazy.ofInstance(code));
    }

    public final Builder setOriginalCode(String code) {
      return setOriginalCodeSupplier(Lazy.ofInstance(code));
    }

    public final Builder addRuntime(String... runtimes) {
      return setRuntimes(
          ImmutableSet.builder().addAll(runtimes()).addAll(asList(runtimes)).build());
    }

    public final Builder setDependencyInfo(DependencyInfo info) {
      // TODO(sdh): consider whether to set path.
      return setLoadFlags(info.getLoadFlags());
    }

    public final Source build() {
      if (originalCodeSupplier() == null) {
        setOriginalCodeSupplier(codeSupplier());
      }
      return autoBuild();
    }

    // Internal-only getters and setters.
    abstract Builder setCodeSupplier(Lazy code);
    abstract Builder setOriginalCodeSupplier(@Nullable Lazy code);
    abstract ImmutableSet runtimes();
    abstract Lazy codeSupplier();
    abstract Source autoBuild();

    abstract @Nullable Lazy originalCodeSupplier();
  }

  /** An automorphic transformation on sources. */
  @FunctionalInterface
  public interface Transformer {

    /** The main transformation method. */
    Source transform(Source input);

    static Transformer of(Function function) {
      return function::apply;
    }

    /** Returns an identity transformer. */
    static Transformer identity() {
      return x -> x;
    }

    /** Converts this Transformer to a Function. */
    default Function asFunction() {
      return this::transform;
    }

    /** Concatenates two Transformers. */
    @CheckReturnValue
    default Transformer andThen(Transformer after) {
      Transformer before = this;
      return x -> after.transform(before.transform(x));
    }

    /** Concatenates two Transformers. */
    @CheckReturnValue
    default Transformer compose(Transformer before) {
      Transformer after = this;
      return x -> after.transform(before.transform(x));
    }
  }

  /** Essentially the same as Supplier, but wraps equals and hashCode. */
  @GwtIncompatible
  @Immutable
  abstract static class Lazy implements Supplier {

    @Override
    public boolean equals(Object other) {
      return other instanceof Lazy && Objects.equals(get(), ((Lazy) other).get());
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(get());
    }

    /** Returns a Lazy that always returns the same instance. */
    @SuppressWarnings("Immutable") // T is not known to be immutable.
    static  Lazy ofInstance(T instance) {
      return new Lazy() {
        @Override
        public T get() {
          return instance;
        }
      };
    }

    /** Returns a Lazy from a memoized supplier. */
    @SuppressWarnings("Immutable") // Supplier is not intrinsically immutable.
    static  Lazy memoize(Supplier supplier) {
      Supplier memoized = Suppliers.memoize(supplier);
      return new Lazy() {
        @Override
        public T get() {
          return memoized.get();
        }
      };
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy