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

0 votes
in ClojureScript by

I've been chasing an issue where we are seeing StackOverflows when compiling a CLJS project on some developer machines but not others.

I think it comes down to the fact that cljs.js-deps/dependency-order is adding an extra require when doing the topological sort of dependencies.

(require '[cljs.js-deps :as deps])
=> nil
(deps/dependency-order
  '({:file "libs.js", :provides ["react" "cljsjs.react"], :requires [] :foreign true}
    {:file "libs.js", :provides ["react" "react-dom" "webpack.bundle"] :foreign true}
    {:file "libs.js" :provides ["react-dom" "cljsjs.react.dom"], :requires ["react"] :foreign true}))
=>
({:file "libs.js", :provides ["react" "cljsjs.react"], :requires [], :foreign true}
 {:file "libs.js", :provides ["react" "react-dom" "webpack.bundle"], :foreign true, :requires ["react"]}
 {:file "libs.js", :provides ["react-dom" "cljsjs.react.dom"], :requires ["react"], :foreign true})

Note the extra :requires ["react"] on the second map of the output, it was not present in the input.
If the order of the inputs is switched, then the extra require does not get added:

  (deps/dependency-order
    '({:file "libs.js", :provides ["react" "react-dom" "webpack.bundle"] :foreign true}
      {:file "libs.js", :provides ["react" "cljsjs.react"], :requires [] :foreign true}
      {:file "libs.js" :provides ["react-dom" "cljsjs.react.dom"], :requires ["react"] :foreign true}))
  =>
  ({:file "libs.js", :provides ["react" "react-dom" "webpack.bundle"], :foreign true, :requires []}
   {:file "libs.js", :provides ["react" "cljsjs.react"], :requires [], :foreign true}
   {:file "libs.js", :provides ["react-dom" "cljsjs.react.dom"], :requires ["react"], :foreign true})

Is this a valid issue?

1 Answer

0 votes
by

David Nolan helped me diagnose what was going on via Slack.

The project included this config:

:foreign-libs [{:file "libs.js"
             :global-exports {react React
                              react-dom ReactDOM}
             :provides ["react" "react-dom" "webpack.bundle"]}]

Where "react" and "react-dom" were being provided by an external JS file that had been bundled by webpack.

It turns out one of the other dependencies in the project was also bringing in "react" and "react-dom" via cljsjs.

The extra inclusions of react/react-dom was causing the inputs to deps/dependency-order to be incorrect.

Adding exclusions in the deps.edn fixed the issue:

re-graph/re-graph {:mvn/version "0.1.15"
                     :exclusions [cljsjs/react cljsjs/react-dom]}

I think the bug deps/dependency-order is a valid one (it should only sort the dependencies, not add extra requires to them), but fixing the core issue (having cljsjs/react and react present in the same project) was enough to sidestep the issue.

I'm adding the output of the original StackOverflow error here for Googleability:

[Figwheel:WARNING] java.lang.StackOverflowError
                    clojure.lang.RT/seqFrom at RT.java(543)
                        clojure.lang.RT/seq at RT.java(537)
        clojure.core$seq__5402/invokeStatic at core.clj(137)
          clojure.core$reduce1/invokeStatic at core.clj(930)
           clojure.core$get_in/invokeStatic at core.clj(6142)
                 clojure.core$get_in/invoke at core.clj(6142)
    cljs.module_graph$deps_for/invokeStatic at module_graph.cljc(150)
          cljs.module_graph$deps_for/invoke at module_graph.cljc(147)
             clojure.lang.AFn/applyToHelper at AFn.java(160)
                   clojure.lang.AFn/applyTo at AFn.java(144)
            clojure.core$apply/invokeStatic at core.clj(665)
     clojure.core$memoize$fn__6877/doInvoke at core.clj(6353)
                 clojure.lang.RestFn/invoke at RestFn.java(436)
 cljs.module_graph$deps_for$fn__4858/invoke at module_graph.cljc(151
...