Welcome! Please see the About page for a little more info on how this works.

0 votes
in ClojureScript by
Hi folks, I'm getting errors when {{require}}-ing foreign libs in version 1.10.439

My project is set up according to https://clojurescript.org/guides/javascript-modules, but without leiningen.

So, there's deps.edn, {{\{:deps {org.clojure/clojurescript \{:mvn/version "1.9.908"\}\}\}}}

{code:title=watch.clj}
(require '[cljs.build.api :as b])

(b/watch "src"
  {:output-to    "main.js"
   :output-dir   "out"
   :main         'hello-es6.core
   :target       :nodejs
   :foreign-libs [{:file "src"
                   :module-type :es6}] ;; or :commonjs / :amd
   :verbose      true})


And the cljs and js files copied from those instructions

src/
├── hello_es6
│   └── core.cljs
└── js
    └── hello.js


Then I can do {{clj ./watch.clj}} (with clojure 1.9) and it works great, {{node main.js}} prints the expected message. But if I just change deps.edn to {{\{:deps \{org.clojure/clojurescript \{:mvn/version "1.10.439"\}\}\}}}, it breaks. First there's an error about clj-oss/module-deps, which, ok I wanted to use npm anyway so I install that, And then after a clean and a recompile, it fails with,


$ node main.js
/Users/jb/src/hello-es6/out/hello_es6/core.js:28
return module$Users$jb$src$hello_es6$src$js$hello.sayHello();
                                                  ^

TypeError: module$Users$jb$src$hello_es6$src$js$hello.sayHello is not a function
    at Function.cljs$core$IFn$_invoke$arity$variadic (/Users/jb/src/hello-es6/out/hello_es6/core.js:28:51)
    at hello_es6$core$_main (/Users/jb/src/hello-es6/out/hello_es6/core.js:24:29)
    at Object.cljs$core$apply_to [as apply_to] (/Users/jb/src/hello-es6/out/cljs/core.js:12956:81)
    at Function.cljs$core$IFn$_invoke$arity$2 (/Users/jb/src/hello-es6/out/cljs/core.js:13400:18)
    at cljs$core$apply (/Users/jb/src/hello-es6/out/cljs/core.js:13358:24)
    at Object.<anonymous> (/Users/jb/src/hello-es6/out/AEF573C.js:10:17)
    at Module._compile (internal/modules/cjs/loader.js:722:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:733:10)
    at Module.load (internal/modules/cjs/loader.js:620:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:560:12)


The error persists after adding {{:npm-deps true}} to the compiler options.

4 Answers

0 votes
by

Comment made by: filipematossilva

Heya, following your steps I can reproduce what you are seeing.

There's actually a warning when running {{clj ./watch.clj}}:

WARNING: JavaScript file found on classpath for library `js.hello`, but does not contain a corresponding `goog.provide` declaration: file:/D:/sandbox/cljs/modules/src/js/hello.js

I fiddled around in the generated JS, running {{node ./main.js}}, and found that:
- {{./out/src/js/hello.js}} is loaded
- {{module$D$sandbox$cljs$modules$src$js$hello}} in {{main.js}} is defined but is an empty object
- altering {{module$D
$sandbox$cljs$modules$src$js$hello}} in {{./out/src/js/hello.js}} does not alter it in {{main.js}
- removing {{var module$D_$sandbox$cljs$modules$src$js$hello={};}} from {{./out/src/js/hello.js}} makes the program run correctly

So it seems like the generated {{./out/src/js/hello.js}} is declaring a local variable that shadows the GCC namespace object, which then causes local assignments to not use the real namespace object.

0 votes
by

Comment made by: filipematossilva

Looked a bit further into this. There's a test that should cover it in https://github.com/clojure/clojurescript/blob/master/src/test/clojure/cljs/build_api_tests.clj#L540-L563.

But the problem doesn't manifest itself at build time, only at run time. I tested modified the output of that test to not remove the out and node_modules dir, and added the following build options:

`

          :target       :nodejs
          :output-to "main.js"
          :main 'foreign-libs-cljs-2334.core

`

Then ran the test, and ran the result with node:

kamik@RED-X1C6 MINGW64 /d/sandbox/cljs/clojurescript (master) $ node main.js mylib: #js {}

This test was meant to print the content of a js library that exports a function, but prints an empty object. This is similar to what happens in the repro above.

To detect this kind of failure, the test suites would have needed to also execute the output with node, or a browser.

As far as I can tell, both master and the {{1.10.516}} version (latest) produce non-working code for this case.

It's not clear where the problem comes from though. Perhaps it is GCC, of configuration for it.

0 votes
by

Comment made by: filipematossilva

There's a test for this functionality in https://github.com/clojure/clojurescript/blob/c4a5120294aa83b8f69d35ce10e5d03c951d99ea/.travis.yml#L24-L46, but that test doesn't seem to be failing Travis (https://travis-ci.org/mfikes/clojurescript/builds/540710982#L2084). I think the regression was accidentally introduced because it didn't fail CI.

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJS-2992 (reported by alex+import)
...