require'd namespace is undefined on nodejs

Description

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"}}}

watch.clj

And the cljs and js files copied from those instructions

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,

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

Environment

mac os, clj 1.9, nodejs repl

Activity

Show:
Filipe Silva
June 4, 2019, 1:56 AM
Edited

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

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

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.

Filipe Silva
June 4, 2019, 7:55 AM

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:

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

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.

Filipe Silva
June 4, 2019, 7:38 PM

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.

Assignee

Unassigned

Reporter

import

Labels

Approval

None

Patch

None

Priority

Major