ClojureScript

Support `export ... from ...` syntax

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: 1.10.238
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

Affects: 1.9.1033+

I have a minimal repro repo here: https://github.com/au-phiware/cljs-2818

Description of problem

Prior to the update to Closure compiler in CLJS-2389, ES6 modules that used the {{export { x as y } from './x'}} or {{export { default as y } from './x'}} syntax compiled correctly. Other forms of this syntax, such as {{export { default } from './x'}}, did not.

Since 1.9.1033, the compiler no longer emits the goog.require statements nor does it emit a complete set of goog.addDependency statements in cljs_deps.js.

Steps to reproduce the problem

Consider the following source files:

src/foo/core.cljs
(ns foo.core (:require [hello :refer [helloGreet]]))                                 

(def ^:export sayHello
    (helloGreet "World"))

(sayHello)
es6/hello.js
export {
    default as helloGreet
} from "./greet";
es6/greet.js
export default function greet(m) {
    document.write("\nHello, " + m);
};
build.clj
(require 'cljs.build.api)

(cljs.build.api/build
  "src"
  {:main 'foo.core
   :output-to "target/main.js"
   :output-dir "target/main.out"
   :asset-path "main.out"
   :foreign-libs [{:file "es6/hello.js"
                   :provides ['hello]
                   :module-type :es6}]
   :verbose true
   :npm-deps {"@cljs-oss/module-deps" "*"}
   :install-deps true})

Execute cljs:

java -cp cljs.jar:src clojure.main build.clj

Expected outcome

cljs should exit cleanly and write the following files (approximately).

target/main.out/cljs_deps.js
goog.addDependency("base.js", ['goog'], []);
goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.Uri', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
goog.addDependency("../es6/greet.js", ['module$usr$src$es6$greet'], []);
goog.addDependency("../es6/hello.js", ['module$usr$src$es6$hello'], ['module$usr$src$es6$greet']);
goog.addDependency("../foo/core.js", ['foo.core'], ['cljs.core', 'module$usr$src$es6$hello']);
target/main.out/es6/hello.js
goog.provide("module$usr$src$es6$hello");
goog.require("module$usr$src$es6$greet");
module$usr$src$es6$hello.helloGreet=module$usr$src$es6$greet["default"]

Actual outcome

The cljs_deps.js is missing the es6/greet.js dependency:

target/main.out/cljs_deps.js
goog.addDependency("base.js", ['goog'], []);
goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.Uri', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']);
goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']);
goog.addDependency("../es6/hello.js", ['module$usr$src$es6$hello'], []);
goog.addDependency("../foo/core.js", ['foo.core'], ['cljs.core', 'module$usr$src$es6$hello']);

And the es6/hello.js file is missing the goog.requires statement:

target/main.out/es6/hello.js
goog.provide("module$usr$src$es6$hello");
var module$usr$src$es6$hello={get helloGreet(){return module$usr$src$es6$greet["default"]}}

Furthermore, the browser console shows:

>>> module$usr$src$es6$hello.helloGreet
hello.js:2 Uncaught ReferenceError: module$usr$src$es6$greet is not defined
    at Object.get helloGreet [as helloGreet] (hello.js:2)
    at <anonymous>:1:65

Attempted workaround

Explicitly adding the :requires option to es6/hello.js :foreign-libs entry did not remedy the problem (nor did using an entry for the whole es6 directory or using an npm module, e.g. d3-scale). Neither did adding [greet] to foo.core's requires.

Activity

Hide
Corin Lawson added a comment -

This appears to be an issue upstream in the Google Closure Compiler...

Show
Corin Lawson added a comment - This appears to be an issue upstream in the Google Closure Compiler...
Hide
Corin Lawson added a comment -

The sample same es6 code compiles just fine with gcc, using java -jar $JAR -O WHITESPACE_ONLY --js_output_file=/dev/stdout -W VERBOSE --module_resolution NODE greet.js hello.js. But when cljs calls upon gcc to convert the es6 code the resulting source is missing the goog.require statement... could it be the module_resolution?

Show
Corin Lawson added a comment - The sample same es6 code compiles just fine with gcc, using java -jar $JAR -O WHITESPACE_ONLY --js_output_file=/dev/stdout -W VERBOSE --module_resolution NODE greet.js hello.js. But when cljs calls upon gcc to convert the es6 code the resulting source is missing the goog.require statement... could it be the module_resolution?
Hide
Corin Lawson added a comment -

I've noticed that gcc with -O BUNDLE --dependency_mode STRICT fails to emit the greet dep... getting a little confused at this point...

Show
Corin Lawson added a comment - I've noticed that gcc with -O BUNDLE --dependency_mode STRICT fails to emit the greet dep... getting a little confused at this point...
Hide
Corin Lawson added a comment - - edited

If I apply this patch to gcc, then it will detect the correct requires of hello.js

diff --git a/src/com/google/javascript/jscomp/CompilerInput.java b/src/com/google/javascript/jscomp/CompilerInput.java
index 62609562b..4e4d3e3dc 100644
--- a/src/com/google/javascript/jscomp/CompilerInput.java
+++ b/src/com/google/javascript/jscomp/CompilerInput.java
@@ -285,7 +285,7 @@ public class CompilerInput extends DependencyInfo.Base implements SourceAst {
 
     // If the code is a JsAst, then it was originally JS code, and is compatible with the
     // regex-based parsing of JsFileParser.
-    if (ast instanceof JsAst && JsFileParser.isSupported()) {
+    if (false && ast instanceof JsAst && JsFileParser.isSupported()) {
       // Look at the source code.
       // Note: it's OK to use getName() instead of
       // getPathRelativeToClosureBase() here because we're not using

But now cljs thinks that greet should be named "module$usr$src$greet" instead of "module$usr$src$es6$greet", but this also seems to be a gcc bug.

Show
Corin Lawson added a comment - - edited If I apply this patch to gcc, then it will detect the correct requires of hello.js
diff --git a/src/com/google/javascript/jscomp/CompilerInput.java b/src/com/google/javascript/jscomp/CompilerInput.java
index 62609562b..4e4d3e3dc 100644
--- a/src/com/google/javascript/jscomp/CompilerInput.java
+++ b/src/com/google/javascript/jscomp/CompilerInput.java
@@ -285,7 +285,7 @@ public class CompilerInput extends DependencyInfo.Base implements SourceAst {
 
     // If the code is a JsAst, then it was originally JS code, and is compatible with the
     // regex-based parsing of JsFileParser.
-    if (ast instanceof JsAst && JsFileParser.isSupported()) {
+    if (false && ast instanceof JsAst && JsFileParser.isSupported()) {
       // Look at the source code.
       // Note: it's OK to use getName() instead of
       // getPathRelativeToClosureBase() here because we're not using
But now cljs thinks that greet should be named "module$usr$src$greet" instead of "module$usr$src$es6$greet", but this also seems to be a gcc bug.

People

Vote (0)
Watch (2)

Dates

  • Created:
    Updated: