Skip to content

Commit

Permalink
Initial support for the --env flag.
Browse files Browse the repository at this point in the history
Builtin externs are now arranged by environment specific folders
Replaces the --use_only_custom_externs flag with the --env=CUSTOM argument
esX.js externs are now included for every environment - including CUSTOM
  • Loading branch information
ChadKillingsworth committed Aug 12, 2015
1 parent 73eb61b commit 2fceff5
Show file tree
Hide file tree
Showing 57 changed files with 169 additions and 131 deletions.
7 changes: 3 additions & 4 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,16 @@
<copy todir="${classes.dir}/com/google/javascript/jscomp/js">
<fileset dir="${src.dir}/com/google/javascript/jscomp/js" />
</copy>

<!-- Zip the externs and move them to the classes folder -->
<zip destfile="${classes.dir}/externs.zip" basedir="${externs.dir}" includes="**/*.js" />
</target>

<target name="jar"
depends="compile"
description="package compiler as an executable jar">
<zip destfile="${build.dir}/externs.zip" basedir="${externs.dir}" includes="*.js" />
<jar destfile="${compiler-jarfile}" update="true">
<fileset dir="${classes.dir}" />
<fileset dir="${build.dir}" includes="externs.zip" />
<zipfileset src="${lib.dir}/args4j.jar"/>
<zipfileset src="${lib.dir}/guava.jar"/>
<zipfileset src="${lib.dir}/gson.jar"/>
Expand Down Expand Up @@ -341,7 +342,6 @@
<target name="webservice-jar"
description="package the compiler and Webservice classes"
depends="webservice-compile, compile">
<zip destfile="${build.dir}/externs.zip" basedir="${externs.dir}" includes="*.js" />
<jar destfile="${webservice-jarfile}" update="true">
<zipgroupfileset dir="${lib.dir}" includes="*.jar"/>
<fileset dir="${classes.dir}" />
Expand Down Expand Up @@ -379,7 +379,6 @@
<target name="refasterjs-jar"
description="Packages the compiler and RefasterJS classes"
depends="refasterjs-compile, compile">
<zip destfile="${build.dir}/externs.zip" basedir="${externs.dir}" includes="*.js" />
<jar destfile="${refasterjs-jarfile}" update="true">
<zipgroupfileset dir="${lib.dir}" includes="*.jar"/>
<fileset dir="${build.dir}" includes="externs.zip" />
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -821,11 +821,11 @@ private static void closeAppendable(Appendable output) throws IOException {
protected int doRun() throws FlagUsageException, IOException {
Compiler.setLoggingLevel(Level.parse(config.loggingLevel));

List<SourceFile> externs = createExterns();

compiler = createCompiler();
B options = createOptions();

List<SourceFile> externs = createExterns(options);

List<JSModule> modules = null;
Result result = null;

Expand Down Expand Up @@ -1086,8 +1086,8 @@ private Charset getOutputCharset2() throws FlagUsageException {
return UTF_8;
}

protected List<SourceFile> createExterns() throws FlagUsageException,
IOException {
protected List<SourceFile> createExterns(CompilerOptions options)
throws FlagUsageException, IOException {
return isInTestMode() ? externsSupplierForTesting.get() :
createExternInputs(config.externs);
}
Expand Down
187 changes: 88 additions & 99 deletions src/com/google/javascript/jscomp/CommandLineRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -380,12 +379,6 @@ private static class Flags {
"QUIET, DEFAULT, VERBOSE")
private WarningLevel warningLevel = WarningLevel.DEFAULT;

@Option(name = "--use_only_custom_externs",
hidden = true,
handler = BooleanOptionHandler.class,
usage = "Specifies whether the default externs should be excluded")
private boolean useOnlyCustomExterns = false;

@Option(name = "--debug",
hidden = true,
handler = BooleanOptionHandler.class,
Expand Down Expand Up @@ -589,6 +582,13 @@ private static class Flags {
usage = "A list of JS Conformance configurations in text protocol buffer format.")
private List<String> conformanceConfigs = new ArrayList<>();

@Option(name = "--env",
hidden = true,
usage = "Determines the set of builtin externs to load. "
+ "Options: BROWSER, CUSTOM. Defaults to BROWSER.")
private CompilerOptions.Environment environment =
CompilerOptions.Environment.BROWSER;

@Argument
private List<String> arguments = new ArrayList<>();
private final CmdLineParser parser;
Expand Down Expand Up @@ -1128,6 +1128,8 @@ protected CompilerOptions createOptions() {
level.setDebugOptionsForCompilationLevel(options);
}

options.setEnvironment(flags.environment);

options.setChecksOnly(flags.checksOnly);

if (flags.useTypesForOptimization) {
Expand Down Expand Up @@ -1191,15 +1193,15 @@ protected Compiler createCompiler() {
}

@Override
protected List<SourceFile> createExterns() throws FlagUsageException,
IOException {
List<SourceFile> externs = super.createExterns();
if (flags.useOnlyCustomExterns || isInTestMode()) {
protected List<SourceFile> createExterns(CompilerOptions options)
throws FlagUsageException, IOException {
List<SourceFile> externs = super.createExterns(options);
if (isInTestMode()) {
return externs;
} else {
List<SourceFile> defaultExterns = getDefaultExterns();
defaultExterns.addAll(externs);
return defaultExterns;
List<SourceFile> builtinExterns = getBuiltinExterns(options);
builtinExterns.addAll(externs);
return builtinExterns;
}
}

Expand Down Expand Up @@ -1238,79 +1240,42 @@ private static ConformanceConfig loadConformanceConfig(String configFile)
return builder.build();
}

// The externs expected in externs.zip, in sorted order.
private static final List<String> DEFAULT_EXTERNS_NAMES = ImmutableList.of(
// JS externs
"es3.js",
"es5.js",
"es6.js",
"es6_collections.js",
"intl.js",

// Event APIs
"w3c_event.js",
"w3c_event3.js",
"gecko_event.js",
"ie_event.js",
"webkit_event.js",
"w3c_device_sensor_event.js",

// DOM apis
"w3c_dom1.js",
"w3c_dom2.js",
"w3c_dom3.js",
"gecko_dom.js",
"ie_dom.js",
"webkit_dom.js",

// CSS apis
"w3c_css.js",
"gecko_css.js",
"ie_css.js",
"webkit_css.js",

// Top-level namespaces
"google.js",

"chrome.js",

"deprecated.js",
"fetchapi.js",
"fileapi.js",
"flash.js",
"gecko_xml.js",
"html5.js",
"ie_vml.js",
"iphone.js",
"mediasource.js",
"page_visibility.js",
"streamsapi.js",
"v8.js",
"webstorage.js",
"w3c_anim_timing.js",
"w3c_audio.js",
"w3c_batterystatus.js",
"w3c_encoding.js",
"w3c_css3d.js",
"w3c_elementtraversal.js",
"w3c_geolocation.js",
"w3c_indexeddb.js",
"w3c_navigation_timing.js",
"w3c_range.js",
"w3c_rtc.js",
"w3c_selectors.js",
"w3c_serviceworker.js",
"w3c_webcrypto.js",
"w3c_xml.js",
"window.js",
"webkit_notifications.js",
"webgl.js");
// The core language externs expected in externs.zip, in sorted order.
private static final List<String> BUILTIN_LANG_EXTERNS = ImmutableList.of(
"es3.js",
"es5.js",
"es6.js",
"es6_collections.js");

// Externs expected in externs.zip, in sorted order.
// Externs not included in this list will be added last
private static final List<String> BUILTIN_EXTERN_DEP_ORDER = ImmutableList.of(
//-- browser externs --
"browser/intl.js",
"browser/w3c_event.js",
"browser/w3c_event3.js",
"browser/gecko_event.js",
"browser/ie_event.js",
"browser/webkit_event.js",
"browser/w3c_device_sensor_event.js",
"browser/w3c_dom1.js",
"browser/w3c_dom2.js",
"browser/w3c_dom3.js",
"browser/gecko_dom.js",
"browser/ie_dom.js",
"browser/webkit_dom.js",
"browser/w3c_css.js",
"browser/gecko_css.js",
"browser/ie_css.js",
"browser/webkit_css.js"
);

/**
* @return a mutable list
* @throws IOException
*/
public static List<SourceFile> getDefaultExterns() throws IOException {
public static List<SourceFile> getBuiltinExterns(CompilerOptions options)
throws IOException {
InputStream input = CommandLineRunner.class.getResourceAsStream(
"/externs.zip");
if (input == null) {
Expand All @@ -1320,30 +1285,54 @@ public static List<SourceFile> getDefaultExterns() throws IOException {
Preconditions.checkNotNull(input);

ZipInputStream zip = new ZipInputStream(input);
final String envPrefix = options.getEnvironment().toString().toLowerCase()
+ "/";

Map<String, SourceFile> externsMap = new HashMap<>();
for (ZipEntry entry = null; (entry = zip.getNextEntry()) != null; ) {
BufferedInputStream entryStream = new BufferedInputStream(
ByteStreams.limit(zip, entry.getSize()));
externsMap.put(entry.getName(),
SourceFile.fromInputStream(
// Give the files an odd prefix, so that they do not conflict
// with the user's files.
"externs.zip//" + entry.getName(),
entryStream,
UTF_8));
// Only load externs in the root folder or in a subfolder matching
// the specified environment
if (entry.getName().indexOf("/") < 0 ||
(entry.getName().indexOf(envPrefix) == 0 &&
entry.getName().length() > envPrefix.length())) {
BufferedInputStream entryStream = new BufferedInputStream(
ByteStreams.limit(zip, entry.getSize()));
externsMap.put(entry.getName(),
SourceFile.fromInputStream(
// Give the files an odd prefix, so that they do not conflict
// with the user's files.
"externs.zip//" + entry.getName(),
entryStream,
UTF_8));
}
}

Preconditions.checkState(
externsMap.keySet().equals(new HashSet<>(DEFAULT_EXTERNS_NAMES)),
"Externs zip must match our hard-coded list of externs.");

// Order matters, so the resources must be added to the result list
// in the expected order.
List<SourceFile> externs = new ArrayList<>();
for (String key : DEFAULT_EXTERNS_NAMES) {
externs.add(externsMap.get(key));

// The externs for core JS objects are loaded in all environments.
for (String key : BUILTIN_LANG_EXTERNS) {
Preconditions.checkState(
externsMap.containsKey(key),
"Externs zip must contain " + key + ".");
externs.add(externsMap.remove(key));
}

// Order matters, so extern resources which have dependencies must be added
// to the result list in the expected order.
for (String key : BUILTIN_EXTERN_DEP_ORDER) {
if (key.indexOf(envPrefix) < 0) {
continue;
}

Preconditions.checkState(
externsMap.containsKey(key),
"Externs zip must contain " + key + " when environment is " +
options.getEnvironment().toString());
externs.add(externsMap.remove(key));
}

externs.addAll(externsMap.values());

return externs;
}

Expand Down
35 changes: 35 additions & 0 deletions src/com/google/javascript/jscomp/CompilerOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ protected DiagnosticGroups getDiagnosticGroups() {
*/
private LanguageMode languageOut;

/**
* The builtin set of externs to be used
*/
private Environment environment;

/**
* If true, don't transpile ES6 to ES3.
* WARNING: Enabling this option will likely cause the compiler to crash
Expand Down Expand Up @@ -961,6 +966,9 @@ public CompilerOptions() {
languageIn = LanguageMode.ECMASCRIPT3;
languageOut = LanguageMode.NO_TRANSPILE;

// Which environment to use
environment = Environment.BROWSER;

// Language variation
acceptTypeSyntax = false;

Expand Down Expand Up @@ -1647,6 +1655,17 @@ public LanguageMode getLanguageOut() {
return languageOut;
}

/**
* Set which set of builtin externs to use.
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}

public Environment getEnvironment() {
return environment;
}

/**
* @return whether we are currently transpiling from ES6 to a lower version.
*/
Expand Down Expand Up @@ -2551,4 +2570,20 @@ public void addAlias(String alias, String definition) {
}
}
}

/**
* An environment specifies the built-in externs that are loaded for a given
* compilation.
*/
public static enum Environment {
/**
* Hand crafted externs that have traditionally been the default externs.
*/
BROWSER,

/**
* Only language externs are loaded.
*/
CUSTOM
}
}
Loading

0 comments on commit 2fceff5

Please sign in to comment.