Uploaded image for project: 'ClojureScript'
  1. CLJS-3056

runtime namespace load order is independent from ordering in ns macro :require form


    • Type: Bug
    • Status: Open
    • Priority: Minor
    • Resolution: Unresolved
    • Affects versions: 1.10.238, 1.9.908
    • Fix versions: None
    • Labels:
    • Patch:


      The order that namespaces are loaded at runtime is independent of the order that the namespaces are {{require}}d in user code. This seems to affect all optimization levels. This means that developers can't rely on side-effectful code in a given namespace to be run before another namespace that depends on the side effect is loaded.

      Reproduction steps:

      Running the command

      clj --main cljs.main --compile-opts '{:target :nodejs :main a}' --compile a

      will compile the a namespace defined in a.cljs. That namespace requires—via the :require form of the ns macro—namespaces b through g in alphabetical order.

      After compiling, observe the following:

      • The goog.addDependency call for a.js in the output out/cljs_deps.js file includes its dependencies in an arbitrary order. For example, one run on my machine resulted in:
      goog.addDependency("../a.js", ['a'], ['cljs.core', 'e', 'c', 'g', 'b', 'd', 'f']);
      • The console output given by running the compiled code with node out/main.js indicates that the runtime load order is identical to the ordering reflected in out/cljs_deps.js
      body of e
      body of c
      body of g
      body of b 
      body of d
      body of f


      It looks like some work to ensure the ordering at compile time was done as part of CLJS-1453 Closed (https://dev.clojure.org/jira/browse/CLJS-1453), but it seems that things can get out of order by the time cljs_deps.js is emitted.

      It seems that the output in cljs_deps.js for a given ClojureScript file is ultimately determined by the output of cljs.compiler/emit-source. The code there removes duplicate deps in the same way that the 'ns parse method in cljs.analyzer did prior to CLJS-1453 Closed .

      The attached patch resolves the issue for my narrow use case, but I believe the underlying functions are passing the `:uses` and `:requires` around as maps, so more work may be needed for a full solution.


        1. a.cljs
          0.1 kB
        2. b.cljs
          0.0 kB
        3. c.cljs
          0.0 kB
        4. CLJS-3056.patch
          3 kB
        5. d.cljs
          0.0 kB
        6. deps.edn
          0.1 kB
        7. e.cljs
          0.0 kB
        8. f.cljs
          0.0 kB
        9. g.cljs
          0.0 kB



            • Assignee:
              chancerussell Chance Russell
            • Votes:
              1 Vote for this issue
              3 Start watching this issue


              • Created: