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

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

    Details

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

      Description

      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
      

      Analysis:

      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.

        Attachments

        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

          Activity

            People

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

              Dates

              • Created:
                Updated: