Skip to content

Instantly share code, notes, and snippets.

@mneise
Last active September 12, 2015 15:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mneise/dc00508e5e9303fed12d to your computer and use it in GitHub Desktop.
Save mneise/dc00508e5e9303fed12d to your computer and use it in GitHub Desktop.
ES6ModuleLoader with overlapping module-roots

Problem

When you instantiate the ES6ModuleLoader the paths of the compiler inputs are normalized against the first module root that completely matches the beginning of the compiler input and saved in an instance variable called moduleUris. Later, when trying to locate a required module, if the module path is not relative, meaning it doesn't start with ./ or ../, the ES6ModuleLoader will try to normalize the required module path against the module roots and if this is not successfull the ES6ModuleLoader will just check the moduleUris for a match.

(def first-file (SourceFile/fromFile
                 (clojure.java.io/file "node_modules/react/react.js")))
(def second-file (SourceFile/fromFile
                  (clojure.java.io/file "node_modules/react/lib/EventConstants.js")))
(def first-input (CompilerInput. first-file))
(def second-input (CompilerInput. second-file))

(ES6ModuleLoader. (list "./node_modules" "./node_modules/react") (list first-input second-input))

In the example above, the moduleUris will be: [react/react.js react/lib/EventConstants.js]. So trying to locate react/lib/EventConstants will succeed, but trying to locate react will fail since it doesn't match any of the moduleUris.

If we switch the order of the module roots when instantiating the ES6ModuleLoader, e.g. (ES6ModuleLoader. (list "./node_modules/react" "./node_modules") (list first-input second-input)), the moduleUris will be [react.js lib/EventConstants.js], so trying to locate react will succeed, but trying to locate react/lib/EventConstants will fail.

Thoughts

Currently, I don't see a straightforward solution to this problem, since I am not sure what the right strategy should be to normalize a compiler input against overlapping module roots. In addition to locating required modules, the ES6ModuleLoader also determines the new module name by normalizing the path of a module against the module roots. This means, that the logic to locate a required module needs to result in the same path as when the path of a module is normalized against the module roots. For example,

URI loadAddress = loader.locateCommonJsModule(requireName, input);
String moduleName = ES6ModuleLoader.toModuleName(loadAddress);

needs to result in the same module name as:

ES6ModuleLoader.toModuleName(loader.normalizeInputAddress(input))

Would definitely be good to get some advice on the Google Closure compiler mailing list. I think the ES6ModuleLoader aims to implement how require works with respect to the CommonJS specification (http://wiki.commonjs.org/wiki/Modules/1.1) and not how require works in Node.js (https://nodejs.org/api/modules.html#modules_module_require_id).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment