Skip to content

Commit

Permalink
Update GwtRunner to export a single compile method, accepting multiple
Browse files Browse the repository at this point in the history
code/externs arguments. This is linked with MinimalLinker.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=126866531
  • Loading branch information
thorogood authored and blickly committed Jul 8, 2016
1 parent 12623a8 commit ee8f67f
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 262 deletions.
3 changes: 2 additions & 1 deletion src/com/google/JsComp.gwt.xml
Expand Up @@ -24,5 +24,6 @@
<set-property name="gwt.logging.enabled" value="TRUE"/> <set-property name="gwt.logging.enabled" value="TRUE"/>
<entry-point class="com.google.javascript.jscomp.gwt.client.GwtRunner"/> <entry-point class="com.google.javascript.jscomp.gwt.client.GwtRunner"/>
<public path="javascript/jscomp/gwt/public"/> <public path="javascript/jscomp/gwt/public"/>
<add-linker name="sso"/> <define-linker name="min" class="com.google.javascript.jscomp.gwt.linker.MinimalLinker"/>
<add-linker name="min"/>
</module> </module>
138 changes: 121 additions & 17 deletions src/com/google/javascript/jscomp/gwt/client/GwtRunner.java
Expand Up @@ -19,25 +19,29 @@
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.javascript.jscomp.BasicErrorManager;
import com.google.javascript.jscomp.CheckLevel;
import com.google.javascript.jscomp.CompilationLevel; import com.google.javascript.jscomp.CompilationLevel;
import com.google.javascript.jscomp.Compiler; import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.CompilerOptions; import com.google.javascript.jscomp.CompilerOptions;
import com.google.javascript.jscomp.CompilerOptions.LanguageMode; import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
import com.google.javascript.jscomp.DiagnosticType;
import com.google.javascript.jscomp.JSError;
import com.google.javascript.jscomp.SourceFile; import com.google.javascript.jscomp.SourceFile;
import com.google.javascript.jscomp.WarningLevel; import com.google.javascript.jscomp.WarningLevel;


import jsinterop.annotations.JsPackage; import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsProperty; import jsinterop.annotations.JsProperty;
import jsinterop.annotations.JsType; import jsinterop.annotations.JsType;


import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;


/** /**
* Runner for the GWT-compiled JSCompiler * Runner for the GWT-compiled JSCompiler as a single exported method.
*
* @author moz@google.com (Michael Zhou)
*/ */
@JsType(namespace = JsPackage.GLOBAL, name = "JSCompiler")
public final class GwtRunner implements EntryPoint { public final class GwtRunner implements EntryPoint {


private static final Map<String, CompilationLevel> COMPILATION_LEVEL_MAP = private static final Map<String, CompilationLevel> COMPILATION_LEVEL_MAP =
Expand All @@ -62,12 +66,7 @@ public final class GwtRunner implements EntryPoint {
"VERBOSE", "VERBOSE",
WarningLevel.VERBOSE); WarningLevel.VERBOSE);


private final Compiler compiler; private GwtRunner() {}

public GwtRunner() {
compiler = new Compiler();
compiler.disableThreads();
}


@JsType(namespace = JsPackage.GLOBAL, name = "Object", isNative = true) @JsType(namespace = JsPackage.GLOBAL, name = "Object", isNative = true)
private interface Flags { private interface Flags {
Expand All @@ -94,6 +93,44 @@ private interface Flags {


@JsProperty @JsProperty
boolean getRewritePolyfills(); boolean getRewritePolyfills();

@JsProperty
File[] getJsCode();

@JsProperty
File[] getExterns();
}

@JsType(namespace = JsPackage.GLOBAL, name = "Object", isNative = true)
private interface File {
@JsProperty String getName();
@JsProperty String getSource();
}

@JsType(namespace = JsPackage.GLOBAL, name = "Object", isNative = true)
private static class ModuleOutput {
@JsProperty String compiledCode;
@JsProperty JavaScriptObject[] errors;
@JsProperty JavaScriptObject[] warnings;
}

private static native JavaScriptObject createError(String file, String description, String type,
int lineNo, int charNo) /*-{
return {file: file, description: description, type: type, lineNo: lineNo, charNo: charNo};
}-*/;

/**
* Convert a list of {@link JSError} instances to a JS array containing plain objects.
*/
private static JavaScriptObject[] toNativeErrorArray(List<JSError> errors) {
JavaScriptObject out[] = new JavaScriptObject[errors.size()];
for (int i = 0; i < errors.size(); ++i) {
JSError error = errors.get(i);
DiagnosticType type = error.getType();
out[i] = createError(error.sourceName, error.description, type != null ? type.key : null,
error.lineNumber, error.getCharno());
}
return out;
} }


private static void applyDefaultOptions(CompilerOptions options) { private static void applyDefaultOptions(CompilerOptions options) {
Expand All @@ -104,7 +141,6 @@ private static void applyDefaultOptions(CompilerOptions options) {
options.setPrettyPrint(true); options.setPrettyPrint(true);
} }


// TODO(moz): Handle most compiler flags and report errors on invalid flags / values.
private static void applyOptionsFromFlags(CompilerOptions options, Flags flags) { private static void applyOptionsFromFlags(CompilerOptions options, Flags flags) {
if (flags == null) { if (flags == null) {
return; return;
Expand Down Expand Up @@ -149,17 +185,85 @@ private static void disableUnsupportedOptions(CompilerOptions options) {
options.getDependencyOptions().setDependencySorting(false); options.getDependencyOptions().setDependencySorting(false);
} }


public String compile(String js, Flags flags) { private static List<SourceFile> fromFileArray(File[] src, String unknownPrefix) {
List<SourceFile> out = new ArrayList<>();
if (src != null) {
for (int i = 0; i < src.length; ++i) {
File file = src[i];
String name = file.getName();
if (name == null) {
name = unknownPrefix + i;
}
String source = file.getSource();
if (source == null) {
source = "";
}
out.add(SourceFile.fromCode(name, source));
}
}
return ImmutableList.copyOf(out);
}

/**
* Public compiler call. Exposed in {@link #exportCompile}.
*/
public static ModuleOutput compile(Flags flags) {
CompilerOptions options = new CompilerOptions(); CompilerOptions options = new CompilerOptions();
applyDefaultOptions(options); applyDefaultOptions(options);
applyOptionsFromFlags(options, flags); applyOptionsFromFlags(options, flags);
disableUnsupportedOptions(options); disableUnsupportedOptions(options);
SourceFile src = SourceFile.fromCode("src.js", js);
SourceFile externs = SourceFile.fromCode("externs.js", "var window;"); NodeErrorManager errorManager = new NodeErrorManager();
compiler.compile(ImmutableList.of(externs), ImmutableList.of(src), options); Compiler compiler = new Compiler();
return compiler.toSource(); compiler.setErrorManager(errorManager);

List<SourceFile> externs = fromFileArray(flags.getExterns(), "Extern_");
List<SourceFile> jsCode = fromFileArray(flags.getJsCode(), "Input_");
compiler.compile(externs, jsCode, options);

ModuleOutput output = new ModuleOutput();
output.compiledCode = compiler.toSource();
output.errors = toNativeErrorArray(errorManager.errors);
output.warnings = toNativeErrorArray(errorManager.warnings);
return output;
} }


/**
* Exports the {@link #compile} method via JSNI.
*
* This will be placed on {@code module.exports} or {@code this}.
*/
public native void exportCompile() /*-{
var fn = $entry(@com.google.javascript.jscomp.gwt.client.GwtRunner::compile(*));
if (typeof module !== 'undefined' && module.exports) {
module.exports = fn;
} else {
this.compile = fn;
}
}-*/;

@Override @Override
public void onModuleLoad() {} public void onModuleLoad() {
exportCompile();
}

/**
* Custom {@link BasicErrorManager} to record {@link JSError} instances.
*/
private static class NodeErrorManager extends BasicErrorManager {
final List<JSError> errors = new ArrayList<>();
final List<JSError> warnings = new ArrayList<>();

@Override
public void println(CheckLevel level, JSError error) {
if (level == CheckLevel.ERROR) {
errors.add(error);
} else if (level == CheckLevel.WARNING) {
warnings.add(error);
}
}

@Override
public void printSummary() {}
}
} }

0 comments on commit ee8f67f

Please sign in to comment.