From 51fe34e4b7eebd04c12e37c407ab4a30f0b2f33a Mon Sep 17 00:00:00 2001 From: Antonio Nuno Monteiro Date: Thu, 3 Aug 2017 13:52:46 -0700 Subject: [PATCH] Add browser and module field support to package.json processing Closes https://github.com/google/closure-compiler/pull/2598 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=164176438 --- .../javascript/jscomp/CompilerOptions.java | 18 ++++++++++ .../jscomp/RewriteJsonToModule.java | 16 ++++++--- .../jscomp/RewriteJsonToModuleTest.java | 34 +++++++++++++++---- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/com/google/javascript/jscomp/CompilerOptions.java b/src/com/google/javascript/jscomp/CompilerOptions.java index 366696bcbfc..f4529c6dd56 100644 --- a/src/com/google/javascript/jscomp/CompilerOptions.java +++ b/src/com/google/javascript/jscomp/CompilerOptions.java @@ -1169,6 +1169,15 @@ public void setWrapGoogModulesForWhitespaceOnly(boolean enable) { /** Which algorithm to use for locating ES6 and CommonJS modules */ ModuleLoader.ResolutionMode moduleResolutionMode; + /** Which entries to look for in package.json files when processing modules */ + List packageJsonEntryNames; + + /** + * Needed by {@link RewriteJsonToModule}, but defined here because RewriteJsonToModule is not + * part of the core build. + */ + public static final String PACKAGE_JSON_MAIN = "main"; + /** * Should the compiler print its configuration options to stderr when they are initialized? * @@ -1194,6 +1203,7 @@ public CompilerOptions() { // Modules moduleResolutionMode = ModuleLoader.ResolutionMode.BROWSER; + packageJsonEntryNames = ImmutableList.of(CompilerOptions.PACKAGE_JSON_MAIN); // Checks skipNonTranspilationPasses = false; @@ -2781,6 +2791,14 @@ public void setModuleResolutionMode(ModuleLoader.ResolutionMode mode) { this.moduleResolutionMode = mode; } + public List getPackageJsonEntryNames() { + return this.packageJsonEntryNames; + } + + public void setPackageJsonEntryNames(List names) { + this.packageJsonEntryNames = names; + } + /** Serializes compiler options to a stream. */ @GwtIncompatible("ObjectOutputStream") public void serialize(OutputStream objectOutputStream) throws IOException { diff --git a/src/com/google/javascript/jscomp/RewriteJsonToModule.java b/src/com/google/javascript/jscomp/RewriteJsonToModule.java index 30d05c914b8..e5c8dbe1dcc 100644 --- a/src/com/google/javascript/jscomp/RewriteJsonToModule.java +++ b/src/com/google/javascript/jscomp/RewriteJsonToModule.java @@ -21,6 +21,7 @@ import com.google.javascript.rhino.IR; import com.google.javascript.rhino.Node; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -35,7 +36,6 @@ public class RewriteJsonToModule extends NodeTraversal.AbstractPostOrderCallback implements CompilerPass { public static final DiagnosticType JSON_UNEXPECTED_TOKEN = DiagnosticType.error("JSC_JSON_UNEXPECTED_TOKEN", "Unexpected JSON token"); - private final Map packageJsonMainEntries; private final AbstractCompiler compiler; @@ -136,10 +136,16 @@ private void visitScript(NodeTraversal t, Node n, Node parent) { String inputPath = t.getInput().getSourceFile().getOriginalPath(); if (inputPath.endsWith("/package.json") && jsonObject.isObjectLit()) { - Node main = NodeUtil.getFirstPropMatchingKey(jsonObject, "main"); - if (main != null && main.isString()) { - String dirName = inputPath.substring(0, inputPath.length() - "package.json".length()); - packageJsonMainEntries.put(inputPath, dirName + main.getString()); + List possibleMainEntries = compiler.getOptions().getPackageJsonEntryNames(); + + for (String entryName : possibleMainEntries) { + Node entry = NodeUtil.getFirstPropMatchingKey(jsonObject, entryName); + + if (entry != null && entry.isString()) { + String dirName = inputPath.substring(0, inputPath.length() - "package.json".length()); + packageJsonMainEntries.put(inputPath, dirName + entry.getString()); + break; + } } } diff --git a/test/com/google/javascript/jscomp/RewriteJsonToModuleTest.java b/test/com/google/javascript/jscomp/RewriteJsonToModuleTest.java index b7d6f2dc427..91a63a4cc6c 100644 --- a/test/com/google/javascript/jscomp/RewriteJsonToModuleTest.java +++ b/test/com/google/javascript/jscomp/RewriteJsonToModuleTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.common.collect.ImmutableList; import com.google.javascript.jscomp.deps.ModuleLoader; import com.google.javascript.rhino.Node; @@ -40,6 +41,8 @@ protected CompilerOptions getOptions() { // Trigger module processing after parsing. options.setProcessCommonJSModules(true); options.setModuleResolutionMode(ModuleLoader.ResolutionMode.NODE); + options.setPackageJsonEntryNames( + ImmutableList.of("browser", CompilerOptions.PACKAGE_JSON_MAIN)); return options; } @@ -50,18 +53,18 @@ protected int getNumRepetitions() { public void testJsonFile() { test( - srcs(SourceFile.fromCode("/test.json", "{ \"foo\": \"bar\"}")), - expected("goog.provide('module$test_json'); var module$test_json = { \"foo\": \"bar\"};")); + srcs(SourceFile.fromCode("/test.json", "{ 'foo': 'bar'}")), + expected("goog.provide('module$test_json'); var module$test_json = { 'foo': 'bar'};")); assertEquals(0, getLastCompiler().getModuleLoader().getPackageJsonMainEntries().size()); } public void testPackageJsonFile() { test( - srcs(SourceFile.fromCode("/package.json", "{ \"main\": \"foo/bar/baz.js\"}")), + srcs(SourceFile.fromCode("/package.json", "{ 'main': 'foo/bar/baz.js'}")), expected(lines( "goog.provide('module$package_json')", - "var module$package_json = {\"main\": \"foo/bar/baz.js\"};"))); + "var module$package_json = {'main': 'foo/bar/baz.js'};"))); assertEquals(1, getLastCompiler().getModuleLoader().getPackageJsonMainEntries().size()); assert (getLastCompiler() @@ -74,11 +77,30 @@ public void testPackageJsonFile() { public void testPackageJsonWithoutMain() { test( - srcs(SourceFile.fromCode("/package.json", "{\"other\": { \"main\": \"foo/bar/baz.js\"}}")), + srcs(SourceFile.fromCode("/package.json", "{'other': { 'main': 'foo/bar/baz.js'}}")), expected(lines( "goog.provide('module$package_json')", - "var module$package_json = {\"other\": { \"main\": \"foo/bar/baz.js\"}};"))); + "var module$package_json = {'other': { 'main': 'foo/bar/baz.js'}};"))); assertEquals(0, getLastCompiler().getModuleLoader().getPackageJsonMainEntries().size()); } + + public void testPackageJsonFileBrowserField() { + test( + srcs( + SourceFile.fromCode( + "/package.json", + "{ 'main': 'foo/bar/baz.js', 'browser': 'browser/foo.js' }")), + expected( + lines( + "goog.provide('module$package_json')", + "var module$package_json = {", + " 'main': 'foo/bar/baz.js',", + " 'browser': 'browser/foo.js'", + "};"))); + + assertThat(getLastCompiler().getModuleLoader().getPackageJsonMainEntries()).hasSize(1); + assertThat(getLastCompiler().getModuleLoader().getPackageJsonMainEntries()) + .containsEntry("/package.json", "/browser/foo.js"); + } }