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

0 votes
in ClojureScript by
{code:title=mylib.js}
mylib = { abc: 3 }


{code:title=co.edn}
{:foreign-libs [{:file "mylib.js"
                 :provides ["my-lib"]
                 :global-exports {my-lib mylib}}]}


Repro:


$ clj -m cljs.main -co co.edn -r
ClojureScript 1.10.339
cljs.user=> (require 'my-lib)

cljs.user=> my-lib/abc
TypeError: Cannot read property 'abc' of undefined
     (<NO_SOURCE_FILE>)
cljs.user=> (require 'my-lib)

cljs.user=> my-lib/abc
3


This doesn't occur in the Node and Nashorn REPLs.

7 Answers

0 votes
by

Comment made by: mfikes

The problem is that browser requires are asynchronous (at least in the REPL), so the bit of code that sets up the global export races with the require code loading.

CLJS-2854-0.patch explores a way to solve this (without yet including tests, etc), by conditionally queueing code (when in the browser REPL) and then executing it after the load queue drains.

0 votes
by

Comment made by: mfikes

CLJS-2854-1.patch introduces a mechanism whereby REPLs can indicate whether they have a way to queue post load activity, and has the browser REPL participate in this mechanism. The names used could be cleaned up, especially if this leads to public API that REPLs could use.

0 votes
by

Comment made by: mfikes

With this code

`
(ns foo.core
(:require my-lib))

(def x my-lib/abc)
`

things work with the patch:

`
$ clj -m cljs.main -co co.edn -r
cljs.user=> (require 'foo.core)

cljs.user=> foo.core/x
3
`

0 votes
by

Comment made by: dnolen

To clarify the problem a bit - the issue is that {{(require ...)}} forms in the REPL are implicitly in {{cljs.user}}, this means that direct requires of libraries with global exports will race because that lib's export mapping comes right after that lib's {{goog.require}}, however that will be an async load, so it won't work. This doesn't affect the transitive case.

0 votes
by

Comment made by: mfikes

CLJS-2854-2.patch tries to keep the logic in the compiler code by simply using a timeout to try to avoid the race.

0 votes
by

Comment made by: mfikes

CLJS-2854-2.patch no longer applies.

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJS-2854 (reported by mfikes)
...