Skip to content

Commit

Permalink
Allow the transpiler to take URIs so that URLs may be used. Useful fo…
Browse files Browse the repository at this point in the history
…r servers that output sourcemaps to ensure the sourcemap points to a server file and not one on disc.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=196520921
  • Loading branch information
johnplaisted authored and blickly committed May 15, 2018
1 parent b5809fb commit 18c9a69
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 126 deletions.
2 changes: 1 addition & 1 deletion src/com/google/javascript/jscomp/CommandLineRunner.java
Expand Up @@ -1078,7 +1078,7 @@ List<SourceMap.LocationMapping> getSourceMapLocationMappings() throws CmdLineExc
ImmutableMap<String, String> split = splitPipeParts(
sourceMapLocationMapping, "--source_map_location_mapping");
for (Map.Entry<String, String> mapping : split.entrySet()) {
locationMappings.add(new SourceMap.LocationMapping(mapping.getKey(),
locationMappings.add(new SourceMap.PrefixLocationMapping(mapping.getKey(),
mapping.getValue()));
}

Expand Down
4 changes: 2 additions & 2 deletions src/com/google/javascript/jscomp/CompilerOptions.java
Expand Up @@ -1081,7 +1081,7 @@ public void setTracerOutput(PrintStream out) {
*/
boolean resolveSourceMapAnnotations = true;

public List<SourceMap.LocationMapping> sourceMapLocationMappings =
public List<? extends SourceMap.LocationMapping> sourceMapLocationMappings =
Collections.emptyList();

/**
Expand Down Expand Up @@ -2656,7 +2656,7 @@ public void setSourceMapFormat(SourceMap.Format sourceMapFormat) {
}

public void setSourceMapLocationMappings(
List<SourceMap.LocationMapping> sourceMapLocationMappings) {
List<? extends SourceMap.LocationMapping> sourceMapLocationMappings) {
this.sourceMapLocationMappings = sourceMapLocationMappings;
}

Expand Down
43 changes: 31 additions & 12 deletions src/com/google/javascript/jscomp/SourceMap.java
Expand Up @@ -95,27 +95,47 @@ public static enum DetailLevel implements Predicate<Node> {
}

/**
* A simple pair of path prefixes to the desired "destination" location to use within the source
* map.
* Function that mape a "destination" location to use within the source map. Should return null
* if the value is not mapped.
*/
public static final class LocationMapping {
@FunctionalInterface
public interface LocationMapping {
/**
* @param location the location to transform
* @return the transformed location or null if not transformed
*/
@Nullable
String map(String location);
}

/**
* Simple {@link LocationMapping} that strips a prefix from a location.
*/
public static final class PrefixLocationMapping implements LocationMapping {
final String prefix;
final String replacement;
public LocationMapping(String prefix, String replacement) {
public PrefixLocationMapping(String prefix, String replacement) {
this.prefix = prefix;
this.replacement = replacement;
}

@Override
public String map(String location) {
if (location.startsWith(prefix)) {
return replacement + location.substring(prefix.length());
}
return null;
}

public String toString() {
return "(" + prefix + "|" + replacement + ")";
}

@Override
public boolean equals(Object other) {
if (other instanceof LocationMapping) {
return ((LocationMapping) other).prefix.equals(prefix)
&& ((LocationMapping) other).replacement.equals(replacement);
if (other instanceof PrefixLocationMapping) {
return ((PrefixLocationMapping) other).prefix.equals(prefix)
&& ((PrefixLocationMapping) other).replacement.equals(replacement);
} else {
return false;
}
Expand All @@ -128,7 +148,7 @@ public int hashCode() {
}

private final SourceMapGenerator generator;
private List<LocationMapping> prefixMappings = Collections.emptyList();
private List<? extends LocationMapping> prefixMappings = Collections.emptyList();
private final Map<String, String> sourceLocationFixupCache =
new HashMap<>();
/**
Expand Down Expand Up @@ -206,9 +226,8 @@ private String fixupSourceLocation(String sourceFile) {

// Replace the first prefix found with its replacement
for (LocationMapping mapping : prefixMappings) {
if (sourceFile.startsWith(mapping.prefix)) {
fixed = mapping.replacement + sourceFile.substring(
mapping.prefix.length());
fixed = mapping.map(sourceFile);
if (fixed != null) {
break;
}
}
Expand Down Expand Up @@ -246,7 +265,7 @@ public void validate(boolean validate) {
/**
* @param sourceMapLocationMappings
*/
public void setPrefixMappings(List<LocationMapping> sourceMapLocationMappings) {
public void setPrefixMappings(List<? extends LocationMapping> sourceMapLocationMappings) {
this.prefixMappings = sourceMapLocationMappings;
}

Expand Down
4 changes: 2 additions & 2 deletions src/com/google/javascript/jscomp/ant/CompileTask.java
Expand Up @@ -32,7 +32,7 @@
import com.google.javascript.jscomp.SourceFile;
import com.google.javascript.jscomp.SourceMap;
import com.google.javascript.jscomp.SourceMap.Format;
import com.google.javascript.jscomp.SourceMap.LocationMapping;
import com.google.javascript.jscomp.SourceMap.PrefixLocationMapping;
import com.google.javascript.jscomp.WarningLevel;
import java.io.File;
import java.io.FileOutputStream;
Expand Down Expand Up @@ -476,7 +476,7 @@ private CompilerOptions createCompilerOptions() {

if (!Strings.isNullOrEmpty(sourceMapLocationMapping)) {
String[] tokens = sourceMapLocationMapping.split("\\|", -1);
LocationMapping lm = new LocationMapping(tokens[0], tokens[1]);
PrefixLocationMapping lm = new PrefixLocationMapping(tokens[0], tokens[1]);
options.setSourceMapLocationMappings(Arrays.asList(lm));
}

Expand Down
10 changes: 8 additions & 2 deletions src/com/google/javascript/jscomp/deps/ClosureBundler.java
Expand Up @@ -23,8 +23,9 @@
import com.google.javascript.jscomp.transpile.Transpiler;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

Expand Down Expand Up @@ -135,7 +136,12 @@ public String getSourceMap(String path) {
}

private String transpile(String s, Transpiler t) {
TranspileResult result = t.transpile(Paths.get(path), s);
TranspileResult result;
try {
result = t.transpile(new URI(path), s);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
sourceMapCache.put(path, result.sourceMap());
return result.transpiled();
}
Expand Down
23 changes: 17 additions & 6 deletions src/com/google/javascript/jscomp/transpile/BaseTranspiler.java
Expand Up @@ -35,7 +35,8 @@
import com.google.javascript.jscomp.bundle.TranspilationException;
import com.google.javascript.rhino.Node;
import java.io.IOException;
import java.nio.file.Path;
import java.net.URI;
import java.net.URISyntaxException;

/**
* Basic Transpiler implementation for outputting ES5 code.
Expand All @@ -51,7 +52,7 @@ public final class BaseTranspiler implements Transpiler {
}

@Override
public TranspileResult transpile(Path path, String code) {
public TranspileResult transpile(URI path, String code) {
CompileResult result = compilerSupplier.compile(path, code);
if (!result.transpiled) {
return new TranspileResult(path, code, code, "");
Expand Down Expand Up @@ -84,7 +85,7 @@ public String runtime() {
* time when we're in single-file mode.
*/
public static class CompilerSupplier {
public CompileResult compile(Path path, String code) {
public CompileResult compile(URI path, String code) {
Compiler compiler = compiler();
Result result =
compiler.compile(EXTERNS, SourceFile.fromCode(path.toString(), code), options());
Expand Down Expand Up @@ -149,9 +150,19 @@ protected void setOptions(CompilerOptions options) {
options.setSourceMapOutputPath("/dev/null");
options.setSourceMapIncludeSourcesContent(true);
// Make sourcemaps use absolute paths, so that the path is not duplicated if a build tool adds
// a sourceurl.
// a sourceurl. Exception: if the location has a scheme (like http:) then leave the path
// intact. This makes this usable from web servers.
options.setSourceMapLocationMappings(
ImmutableList.of(new SourceMap.LocationMapping("", "/")));
ImmutableList.of((location) -> {
try {
if (new URI(location).getScheme() != null) {
return location;
}
} catch (URISyntaxException e) {
// Swallow, return the absolute version below.
}
return new SourceMap.PrefixLocationMapping("", "/").map(location);
}));
}

protected static final SourceFile EXTERNS =
Expand All @@ -167,7 +178,7 @@ protected void setOptions(CompilerOptions options) {
*/
public static class EsmToCjsCompilerSupplier extends CompilerSupplier {
@Override
public CompileResult compile(Path path, String code) {
public CompileResult compile(URI path, String code) {
CompilerOptions options = new CompilerOptions();
options.setLanguageIn(LanguageMode.ECMASCRIPT_NEXT);
options.setEmitUseStrict(false);
Expand Down
Expand Up @@ -25,7 +25,7 @@
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.javascript.jscomp.bundle.TranspilationException;
import java.nio.file.Path;
import java.net.URI;
import java.util.Objects;

/**
Expand All @@ -51,7 +51,7 @@ public TranspileResult load(Key key) {
}

@Override
public TranspileResult transpile(Path path, String code) {
public TranspileResult transpile(URI path, String code) {
try {
return cache.getUnchecked(new Key(path, code));
} catch (UncheckedExecutionException e) {
Expand All @@ -72,9 +72,10 @@ public String runtime() {
}

private static final class Key {
private final Path path;
private final URI path;
private final String code;
Key(Path path, String code) {

Key(URI path, String code) {
this.path = checkNotNull(path);
this.code = checkNotNull(code);
}
Expand Down
Expand Up @@ -20,7 +20,7 @@

import com.google.common.escape.Escaper;
import com.google.common.net.PercentEscaper;
import java.nio.file.Path;
import java.net.URI;
import java.util.Objects;

/**
Expand All @@ -29,19 +29,19 @@
*/
public final class TranspileResult {

private final Path path;
private final URI path;
private final String original;
private final String transpiled;
private final String sourceMap;

public TranspileResult(Path path, String original, String transpiled, String sourceMap) {
public TranspileResult(URI path, String original, String transpiled, String sourceMap) {
this.path = checkNotNull(path);
this.original = checkNotNull(original);
this.transpiled = checkNotNull(transpiled);
this.sourceMap = checkNotNull(sourceMap);
}

public Path path() {
public URI path() {
return path;
}

Expand Down
34 changes: 15 additions & 19 deletions src/com/google/javascript/jscomp/transpile/Transpiler.java
Expand Up @@ -16,7 +16,7 @@

package com.google.javascript.jscomp.transpile;

import java.nio.file.Path;
import java.net.URI;

/**
* Common interface for a transpiler.
Expand All @@ -39,11 +39,8 @@
* </ol>
*/
public interface Transpiler {
/**
* Transforms the given chunk of code. The input should be an entire file
* worth of code.
*/
TranspileResult transpile(Path path, String code);
/** Transforms the given chunk of code. The input should be an entire file worth of code. */
TranspileResult transpile(URI path, String code);

/**
* Returns any necessary runtime code as a string. This should include
Expand All @@ -52,18 +49,17 @@ public interface Transpiler {
*/
String runtime();

/**
* Null implementation that does no transpilation at all.
*/
Transpiler NULL = new Transpiler() {
@Override
public TranspileResult transpile(Path path, String code) {
return new TranspileResult(path, code, code, "");
}
/** Null implementation that does no transpilation at all. */
Transpiler NULL =
new Transpiler() {
@Override
public TranspileResult transpile(URI path, String code) {
return new TranspileResult(path, code, code, "");
}

@Override
public String runtime() {
return "";
}
};
@Override
public String runtime() {
return "";
}
};
}
9 changes: 5 additions & 4 deletions test/com/google/javascript/jscomp/CommandLineRunnerTest.java
Expand Up @@ -1033,9 +1033,9 @@ public void testSourceMapLocationsTranslations1() {
args.add("--source_map_location_mapping=foo/|http://bar");
testSame("var x = 3;");

List<LocationMapping> mappings = lastCompiler.getOptions().sourceMapLocationMappings;
List<? extends LocationMapping> mappings = lastCompiler.getOptions().sourceMapLocationMappings;
assertThat(ImmutableSet.copyOf(mappings))
.containsExactly(new LocationMapping("foo/", "http://bar"));
.containsExactly(new SourceMap.PrefixLocationMapping("foo/", "http://bar"));
}

public void testSourceMapLocationsTranslations2() {
Expand All @@ -1046,11 +1046,12 @@ public void testSourceMapLocationsTranslations2() {
args.add("--source_map_location_mapping=xxx/|http://yyy");
testSame("var x = 3;");

List<LocationMapping> mappings = lastCompiler.getOptions()
List<? extends LocationMapping> mappings = lastCompiler.getOptions()
.sourceMapLocationMappings;
assertThat(ImmutableSet.copyOf(mappings))
.containsExactly(
new LocationMapping("foo/", "http://bar"), new LocationMapping("xxx/", "http://yyy"));
new SourceMap.PrefixLocationMapping("foo/", "http://bar"),
new SourceMap.PrefixLocationMapping("xxx/", "http://yyy"));
}

public void testSourceMapLocationsTranslations3() {
Expand Down

0 comments on commit 18c9a69

Please sign in to comment.