ClojureScript

cljs.core/resolve fails under :advanced compilation (regression)

Details

  • Type: Defect Defect
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Not Reproducible
  • Affects Version/s: 1.10.238
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Approval:
    Screened

Description

The macro cljs.core/resolve does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

deps.edn
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
build.edn
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
src/demo/a.cljs
(ns demo.a)

(resolve 'demo.foo.b/bar)
src/demo/foo/b.cljs
(ns demo.foo.b)

(defn bar [] :bar)
index.html
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>

The repro can be compiled by running clj -m cljs.main -co build.edn -c

Activity

David Nolen made changes -
Field Original Value New Value
Approval Screened [ 10004 ]
David Nolen made changes -
Description The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

Specifically, 1.10.238 (and master) produces {{nil}} for meta at this point https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3292 while it
produces the correct value in 1.9.946 (meta with arglists etc.).

The cause seems to be that when using the macro {{cljs.core/resolve}} with code splitting (:modules functionality) that there are conditions where it is possible that a module (A) that triggers the load of another module (B) is compiled before the defs of module B have been processed into {{cljs.env/\*compiler\*}}.

This results in the defs in module B being empty at this point (https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L802) during the compilation of module A and causes the attempt at {{cljs.core/resolve}} to fail here https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3288 .

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.clj|borderStyle=solid}
(require '[cljs.build.api :as cljs])

(cljs/build
  "src"
  '{:output-dir "out"
    :optimizations :none
    :modules
    {:a {:output-to "out/a.js"
         :entries [demo.a]}
     :b {:output-to "out/b.js"
         :entries [demo.foo.b]
         :depends-on #{:a}}}
    :verbose true})
   
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

The repro can be compiled by running {{clj build.clj}} . Observe that for {{out/demo/a.js}} the {{cljs.core/resolve}} macro did not produce the correct meta for the demo.foo.b/bar var.

Changing the clojurescript dependency in deps.edn to 1.9.946 produces the correct output in {{out/demo/a.js}}.
The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

Specifically, 1.10.238 (and master) produces {{nil}} for meta at this point https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3292 while it
produces the correct value in 1.9.946 (meta with arglists etc.).

The cause seems to be that when using the macro {{cljs.core/resolve}} with code splitting (:modules functionality) that there are conditions where it is possible that a module (A) that triggers the load of another module (B) is compiled before the defs of module B have been processed into {{cljs.env/\*compiler\*}}.

This results in the defs in module B being empty at this point (https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L802) during the compilation of module A and causes the attempt at {{cljs.core/resolve}} to fail here https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3288 .

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

The repro can be compiled by running {{clj build.clj}} . Observe that for {{out/demo/a.js}} the {{cljs.core/resolve}} macro did not produce the correct meta for the demo.foo.b/bar var.

Changing the clojurescript dependency in deps.edn to 1.9.946 produces the correct output in {{out/demo/a.js}}.
David Nolen made changes -
Description The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

Specifically, 1.10.238 (and master) produces {{nil}} for meta at this point https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3292 while it
produces the correct value in 1.9.946 (meta with arglists etc.).

The cause seems to be that when using the macro {{cljs.core/resolve}} with code splitting (:modules functionality) that there are conditions where it is possible that a module (A) that triggers the load of another module (B) is compiled before the defs of module B have been processed into {{cljs.env/\*compiler\*}}.

This results in the defs in module B being empty at this point (https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L802) during the compilation of module A and causes the attempt at {{cljs.core/resolve}} to fail here https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3288 .

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

The repro can be compiled by running {{clj build.clj}} . Observe that for {{out/demo/a.js}} the {{cljs.core/resolve}} macro did not produce the correct meta for the demo.foo.b/bar var.

Changing the clojurescript dependency in deps.edn to 1.9.946 produces the correct output in {{out/demo/a.js}}.
The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

Specifically, 1.10.238 (and master) produces {{nil}} for meta at this point https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3292 while it
produces the correct value in 1.9.946 (meta with arglists etc.).

The cause seems to be that when using the macro {{cljs.core/resolve}} with code splitting (:modules functionality) that there are conditions where it is possible that a module (A) that triggers the load of another module (B) is compiled before the defs of module B have been processed into {{cljs.env/\*compiler\*}}.

This results in the defs in module B being empty at this point (https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L802) during the compilation of module A and causes the attempt at {{cljs.core/resolve}} to fail here https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3288 .

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}} . Observe that for {{out/demo/a.js}} the {{cljs.core/resolve}} macro did not produce the correct meta for the demo.foo.b/bar var.

Changing the clojurescript dependency in deps.edn to 1.9.946 produces the correct output in {{out/demo/a.js}}.
David Nolen made changes -
Description The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

Specifically, 1.10.238 (and master) produces {{nil}} for meta at this point https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3292 while it
produces the correct value in 1.9.946 (meta with arglists etc.).

The cause seems to be that when using the macro {{cljs.core/resolve}} with code splitting (:modules functionality) that there are conditions where it is possible that a module (A) that triggers the load of another module (B) is compiled before the defs of module B have been processed into {{cljs.env/\*compiler\*}}.

This results in the defs in module B being empty at this point (https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L802) during the compilation of module A and causes the attempt at {{cljs.core/resolve}} to fail here https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3288 .

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}} . Observe that for {{out/demo/a.js}} the {{cljs.core/resolve}} macro did not produce the correct meta for the demo.foo.b/bar var.

Changing the clojurescript dependency in deps.edn to 1.9.946 produces the correct output in {{out/demo/a.js}}.
The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

Specifically, 1.10.238 (and master) produces {{nil}} for meta at this point https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3292 while it
produces the correct value in 1.9.946 (meta with arglists etc.).

The cause seems to be that when using the macro {{cljs.core/resolve}} with code splitting (:modules functionality) that there are conditions where it is possible that a module (A) that triggers the load of another module (B) is compiled before the defs of module B have been processed into {{cljs.env/\*compiler\*}}.

This results in the defs in module B being empty at this point (https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L802) during the compilation of module A and causes the attempt at {{cljs.core/resolve}} to fail here https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3288 .

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

{code:title=index.html|borderStyle=solid}
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}} . Observe that for {{out/demo/a.js}} the {{cljs.core/resolve}} macro did not produce the correct meta for the demo.foo.b/bar var.

Changing the clojurescript dependency in deps.edn to 1.9.946 produces the correct output in {{out/demo/a.js}}.
David Nolen made changes -
Description The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

Specifically, 1.10.238 (and master) produces {{nil}} for meta at this point https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3292 while it
produces the correct value in 1.9.946 (meta with arglists etc.).

The cause seems to be that when using the macro {{cljs.core/resolve}} with code splitting (:modules functionality) that there are conditions where it is possible that a module (A) that triggers the load of another module (B) is compiled before the defs of module B have been processed into {{cljs.env/\*compiler\*}}.

This results in the defs in module B being empty at this point (https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L802) during the compilation of module A and causes the attempt at {{cljs.core/resolve}} to fail here https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L3288 .

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

{code:title=index.html|borderStyle=solid}
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}} . Observe that for {{out/demo/a.js}} the {{cljs.core/resolve}} macro did not produce the correct meta for the demo.foo.b/bar var.

Changing the clojurescript dependency in deps.edn to 1.9.946 produces the correct output in {{out/demo/a.js}}.
The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

{code:title=index.html|borderStyle=solid}
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}}

Changing the clojurescript dependency in deps.edn to 1.9.946 produces the correct output in {{out/demo/a.js}}.
Summary cljs.core/resolve does not produce sufficient information to invoke a function across module boundaries with :advanced compilation cljs.core/resolve fails under :advanced compilation (regression)
David Nolen made changes -
Description The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

{code:title=index.html|borderStyle=solid}
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}}

Changing the clojurescript dependency in deps.edn to 1.9.946 produces the correct output in {{out/demo/a.js}}.
The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

{code:title=index.html|borderStyle=solid}
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}}
Hide
David Nolen added a comment - - edited

See CLJS-2764, it's now no longer clear what the issue in this ticket is. The above case was simply demonstrating failing exists?.

Show
David Nolen added a comment - - edited See CLJS-2764, it's now no longer clear what the issue in this ticket is. The above case was simply demonstrating failing exists?.
Pieter du Toit made changes -
Description The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

{code:title=index.html|borderStyle=solid}
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}}
The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

{code:title=index.html|borderStyle=solid}
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}}

The incorrect output produced for {{out/demo/a.js}} when run with 1.10.238 is provided below on line 7:

{code:title=out/demo/a.js|borderStyle=solid}
// Compiled by ClojureScript 1.10.238 {}
goog.provide('demo.a');
goog.require('cljs.core');
if(typeof demo.foo.b.bar !== 'undefined'){
(new cljs.core.Var((function (){
return demo.foo.b.bar;
}),cljs.core.with_meta(new cljs.core.Symbol("demo.foo.b","bar","demo.foo.b/bar",-1728256388,null),new cljs.core.PersistentArrayMap(null, 1, [new cljs.core.Keyword("cljs.analyzer","no-resolve","cljs.analyzer/no-resolve",-1872351017),true], null)),null));
} else {
}

//# sourceMappingURL=a.js.map
{code}

The correct output produced for {{out/demo/a.js}} when run with 1.9.946 is provided below on line 7:

{code:title=out/demo/a.js|borderStyle=solid}
// Compiled by ClojureScript 1.9.946 {}
goog.provide('demo.a');
goog.require('cljs.core');
if(typeof demo.foo.b.bar !== 'undefined'){
(new cljs.core.Var((function (){
return demo.foo.b.bar;
}),cljs.core.with_meta(new cljs.core.Symbol("demo.foo.b","bar","demo.foo.b/bar",-1728256388,null),new cljs.core.PersistentArrayMap(null, 1, [new cljs.core.Keyword("cljs.analyzer","no-resolve","cljs.analyzer/no-resolve",-1872351017),true], null)),cljs.core.PersistentHashMap.fromArrays([new cljs.core.Keyword(null,"ns","ns",441598760),new cljs.core.Keyword(null,"name","name",1843675177),new cljs.core.Keyword(null,"file","file",-1269645878),new cljs.core.Keyword(null,"end-column","end-column",1425389514),new cljs.core.Keyword(null,"column","column",2078222095),new cljs.core.Keyword(null,"line","line",212345235),new cljs.core.Keyword(null,"end-line","end-line",1837326455),new cljs.core.Keyword(null,"arglists","arglists",1661989754),new cljs.core.Keyword(null,"doc","doc",1913296891),new cljs.core.Keyword(null,"test","test",577538877)],[new cljs.core.Symbol(null,"demo.foo.b","demo.foo.b",-391443770,null),new cljs.core.Symbol(null,"bar","bar",254284943,null),"/private/tmp/ft/cljs-bad-resolve/src/demo/foo/b.cljs",10,1,3,3,cljs.core.list(cljs.core.PersistentVector.EMPTY),null,(cljs.core.truth_(demo.foo.b.bar)?demo.foo.b.bar.cljs$lang$test:null)])));
} else {
}

//# sourceMappingURL=a.js.map
{code}
David Nolen made changes -
Description The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

{code:title=index.html|borderStyle=solid}
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}}

The incorrect output produced for {{out/demo/a.js}} when run with 1.10.238 is provided below on line 7:

{code:title=out/demo/a.js|borderStyle=solid}
// Compiled by ClojureScript 1.10.238 {}
goog.provide('demo.a');
goog.require('cljs.core');
if(typeof demo.foo.b.bar !== 'undefined'){
(new cljs.core.Var((function (){
return demo.foo.b.bar;
}),cljs.core.with_meta(new cljs.core.Symbol("demo.foo.b","bar","demo.foo.b/bar",-1728256388,null),new cljs.core.PersistentArrayMap(null, 1, [new cljs.core.Keyword("cljs.analyzer","no-resolve","cljs.analyzer/no-resolve",-1872351017),true], null)),null));
} else {
}

//# sourceMappingURL=a.js.map
{code}

The correct output produced for {{out/demo/a.js}} when run with 1.9.946 is provided below on line 7:

{code:title=out/demo/a.js|borderStyle=solid}
// Compiled by ClojureScript 1.9.946 {}
goog.provide('demo.a');
goog.require('cljs.core');
if(typeof demo.foo.b.bar !== 'undefined'){
(new cljs.core.Var((function (){
return demo.foo.b.bar;
}),cljs.core.with_meta(new cljs.core.Symbol("demo.foo.b","bar","demo.foo.b/bar",-1728256388,null),new cljs.core.PersistentArrayMap(null, 1, [new cljs.core.Keyword("cljs.analyzer","no-resolve","cljs.analyzer/no-resolve",-1872351017),true], null)),cljs.core.PersistentHashMap.fromArrays([new cljs.core.Keyword(null,"ns","ns",441598760),new cljs.core.Keyword(null,"name","name",1843675177),new cljs.core.Keyword(null,"file","file",-1269645878),new cljs.core.Keyword(null,"end-column","end-column",1425389514),new cljs.core.Keyword(null,"column","column",2078222095),new cljs.core.Keyword(null,"line","line",212345235),new cljs.core.Keyword(null,"end-line","end-line",1837326455),new cljs.core.Keyword(null,"arglists","arglists",1661989754),new cljs.core.Keyword(null,"doc","doc",1913296891),new cljs.core.Keyword(null,"test","test",577538877)],[new cljs.core.Symbol(null,"demo.foo.b","demo.foo.b",-391443770,null),new cljs.core.Symbol(null,"bar","bar",254284943,null),"/private/tmp/ft/cljs-bad-resolve/src/demo/foo/b.cljs",10,1,3,3,cljs.core.list(cljs.core.PersistentVector.EMPTY),null,(cljs.core.truth_(demo.foo.b.bar)?demo.foo.b.bar.cljs$lang$test:null)])));
} else {
}

//# sourceMappingURL=a.js.map
{code}
The macro {{cljs.core/resolve}} does not produce sufficient information to invoke (when using :advanced compilation) a function across module boundaries under certain conditions.

With :advanced compilation, the attempt of module A to invoke the function in module B after load then fails at runtime. The issue occurs when using 1.10.238, but does not occur when using 1.9.946.

A minimal repro is provided below:

{code:title=deps.edn|borderStyle=solid}
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}}}
{code}

{code:title=build.edn|borderStyle=solid}
{:output-dir "out"
 :optimizations :none
 :modules
 {:a {:output-to "out/a.js"
      :entries [demo.a]}
  :b {:output-to "out/b.js"
      :entries [demo.foo.b]
      :depends-on #{:a}}}
 :verbose true}
{code}


{code:title=src/demo/a.cljs|borderStyle=solid}
(ns demo.a)

(resolve 'demo.foo.b/bar)
{code}

{code:title=src/demo/foo/b.cljs|borderStyle=solid}
(ns demo.foo.b)

(defn bar [] :bar)
{code}

{code:title=index.html|borderStyle=solid}
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
{code}

The repro can be compiled by running {{clj -m cljs.main -co build.edn -c}}
Hide
Pieter du Toit added a comment - - edited

I have narrowed the minimal repro down to React v16 being specified as a foreign lib dependency in the target module. Under :advanced compilation and with React v16, the module's compiled js function definitions are not available after the module is loaded. The attempt by the calling module to then invoke the function in the target module fails with the error "Uncaught TypeError: Cannot read property '$cljs$core$IFn$_invoke$arity$0$' of null" .

A minimal repro that produces the error is provided below:

deps.edn
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}
        cljsjs/react {:mvn/version "16.3.2-0"} }}
src/demo/a.cljs
(ns demo.a
  (:require [cljs.loader]))

(cljs.loader/set-loaded! :a)

(cljs.loader/load :b (fn [e]
                       (.log js/console "Invoking b from a")
                       ((resolve 'demo.foo.b/bar))))
src/demo/foo/b.cljs
(ns demo.foo.b
  (:require [cljsjs.react]
            [cljs.loader]))

(defn bar [] (.log js/console "B has been loaded"))

(cljs.loader/set-loaded! :b)
index.html
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
build.clj
(require '[cljs.build.api :as cljs]
         '[cljs.repl :as repl]
         '[cljs.repl.browser :as browser])

(cljs/build
  "src"
  '{:output-dir "out"
    :optimizations :advanced
    :pseudo-names true
    :pretty-print true 
    :modules {:a {:output-to "out/a.js"
                  :entries [demo.a]}
              :b {:output-to "out/b.js"
                  :entries [demo.foo.b]
                  :depends-on #{:a}}}
    :verbose true})

(repl/repl (browser/repl-env)
  :output-dir "out")

It can be launched by running clj build.clj , once it is launched, observe the error message in the browser's console.

React v16's use of a global scope "use strict" directive seems to be the cause. The minimal repro can also be narrowed down further by removing the React dependency and prepending "use strict"; to out/b.js after compilation.

Show
Pieter du Toit added a comment - - edited I have narrowed the minimal repro down to React v16 being specified as a foreign lib dependency in the target module. Under :advanced compilation and with React v16, the module's compiled js function definitions are not available after the module is loaded. The attempt by the calling module to then invoke the function in the target module fails with the error "Uncaught TypeError: Cannot read property '$cljs$core$IFn$_invoke$arity$0$' of null" . A minimal repro that produces the error is provided below:
deps.edn
{:deps {org.clojure/clojurescript {:mvn/version "1.10.238"}
        cljsjs/react {:mvn/version "16.3.2-0"} }}
src/demo/a.cljs
(ns demo.a
  (:require [cljs.loader]))

(cljs.loader/set-loaded! :a)

(cljs.loader/load :b (fn [e]
                       (.log js/console "Invoking b from a")
                       ((resolve 'demo.foo.b/bar))))
src/demo/foo/b.cljs
(ns demo.foo.b
  (:require [cljsjs.react]
            [cljs.loader]))

(defn bar [] (.log js/console "B has been loaded"))

(cljs.loader/set-loaded! :b)
index.html
<html>
    <body>
        <script src="out/cljs_base.js"></script>
        <script src="out/a.js"></script>
    </body>
</html>
build.clj
(require '[cljs.build.api :as cljs]
         '[cljs.repl :as repl]
         '[cljs.repl.browser :as browser])

(cljs/build
  "src"
  '{:output-dir "out"
    :optimizations :advanced
    :pseudo-names true
    :pretty-print true 
    :modules {:a {:output-to "out/a.js"
                  :entries [demo.a]}
              :b {:output-to "out/b.js"
                  :entries [demo.foo.b]
                  :depends-on #{:a}}}
    :verbose true})

(repl/repl (browser/repl-env)
  :output-dir "out")
It can be launched by running clj build.clj , once it is launched, observe the error message in the browser's console. React v16's use of a global scope "use strict" directive seems to be the cause. The minimal repro can also be narrowed down further by removing the React dependency and prepending "use strict"; to out/b.js after compilation.
Hide
David Nolen added a comment -

See CLJS-2768 for the actual issue.

Show
David Nolen added a comment - See CLJS-2768 for the actual issue.
David Nolen made changes -
Resolution Not Reproducible [ 4 ]
Status Open [ 1 ] Resolved [ 5 ]

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: