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

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?.
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.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: