taoensso / encore

Core utils library for Clojure/Script
https://www.taoensso.com/encore
Eclipse Public License 1.0
274 stars 52 forks source link

3.99.0 can't be compiled by shadow-cljs if also required in the JVM of the shadow compiler #74

Closed davidyang closed 5 months ago

davidyang commented 5 months ago

If I start up a JVM clojure with

(ns user
  (:require [taoensso.encore]))

and then try to do a

  (require 'shadow.cljs.devtools.api)
  (shadow.cljs.devtools.api/compile :browser-dev {:verbose true})

I get this error. If I empty out (ns user) then the shadow build completes successfully.

------ ERROR -------------------------------------------------------------------
 File: jar:file:/Users/dyang/.m2/repository/com/taoensso/encore/3.99.0/encore-3.99.0.jar!/taoensso/encore.cljc:733:1
--------------------------------------------------------------------------------
 730 |      (defalias                 taoensso.truss/have!?)
 731 |      (defalias with-truss-data taoensso.truss/with-data)))
 732 |
 733 | (defalias get-truss-data taoensso.truss/get-data)
-------^------------------------------------------------------------------------
Encountered error when macroexpanding taoensso.encore/defalias.
NullPointerException: Cannot invoke "clojure.lang.IFn.invoke(Object, Object)" because "this.resolve_cljs" is null
    taoensso.encore/eval1539/var-info--1540 (encore.cljc:630)
    taoensso.encore/defalias (encore.cljc:655)
    taoensso.encore/defalias (encore.cljc:640)
    clojure.core/apply (core.clj:671)
    clojure.core/apply (core.clj:662)
    cljs.analyzer/macroexpand-1*/fn--3378 (analyzer.cljc:4036)
    cljs.analyzer/macroexpand-1* (analyzer.cljc:4034)
    cljs.analyzer/macroexpand-1* (analyzer.cljc:4020)
    cljs.analyzer/macroexpand-1 (analyzer.cljc:4086)
    cljs.analyzer/macroexpand-1 (analyzer.cljc:4082)
    cljs.analyzer/analyze-seq (analyzer.cljc:4119)
    cljs.analyzer/analyze-seq (analyzer.cljc:4099)
    cljs.analyzer/analyze-form (analyzer.cljc:4308)
    cljs.analyzer/analyze-form (analyzer.cljc:4305)
    cljs.analyzer/analyze* (analyzer.cljc:4361)
    cljs.analyzer/analyze* (analyzer.cljc:4353)
    cljs.analyzer/analyze (analyzer.cljc:4381)
    cljs.analyzer/analyze (analyzer.cljc:4364)
    cljs.analyzer/analyze-seq (analyzer.cljc:4122)
    cljs.analyzer/analyze-seq (analyzer.cljc:4099)
    cljs.analyzer/analyze-form (analyzer.cljc:4308)
    cljs.analyzer/analyze-form (analyzer.cljc:4305)
    cljs.analyzer/analyze* (analyzer.cljc:4361)
    cljs.analyzer/analyze* (analyzer.cljc:4353)
    shadow.build.compiler/analyze/fn--9561 (compiler.clj:387)
    shadow.build.compiler/analyze (compiler.clj:375)
    shadow.build.compiler/analyze (compiler.clj:332)
    shadow.build.compiler/analyze (compiler.clj:334)
    shadow.build.compiler/analyze (compiler.clj:332)
    shadow.build.compiler/default-analyze-cljs (compiler.clj:549)
    shadow.build.compiler/default-analyze-cljs (compiler.clj:534)
    clojure.core/partial/fn--5915 (core.clj:2642)
    shadow.build.compiler/do-analyze-cljs-string (compiler.clj:451)
    shadow.build.compiler/do-analyze-cljs-string (compiler.clj:408)
    shadow.build.compiler/analyze-cljs-string/fn--9662 (compiler.clj:652)
    shadow.build.compiler/analyze-cljs-string (compiler.clj:651)
    shadow.build.compiler/analyze-cljs-string (compiler.clj:649)
    shadow.build.compiler/do-compile-cljs-resource/fn--9690 (compiler.clj:771)
    shadow.build.compiler/do-compile-cljs-resource (compiler.clj:752)
    shadow.build.compiler/do-compile-cljs-resource (compiler.clj:706)
    shadow.build.compiler/maybe-compile-cljs/fn--9794 (compiler.clj:1113)
    shadow.build.compiler/maybe-compile-cljs (compiler.clj:1112)
    shadow.build.compiler/maybe-compile-cljs (compiler.clj:1088)
    shadow.build.compiler/par-compile-one (compiler.clj:1233)
    shadow.build.compiler/par-compile-one (compiler.clj:1188)
    shadow.build.compiler/par-compile-cljs-sources/fn--9834/iter--9856--9860/fn--9861/fn--9862/fn--9863 (compiler.clj:1306)
    clojure.core/apply (core.clj:667)
    clojure.core/with-bindings* (core.clj:1990)
    clojure.core/with-bindings* (core.clj:1990)
    clojure.core/apply (core.clj:671)
    clojure.core/bound-fn*/fn--5825 (core.clj:2020)
    java.util.concurrent.FutureTask.run (FutureTask.java:317)
    java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
    java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
    java.lang.Thread.run (Thread.java:1589)
ptaoussanis commented 5 months ago

@davidyang Hi David,

Could you please clarify what you're actually trying to do?

I'm not familiar with shadow.cljs.devtools.api, so any context you can provide would be helpful.

ptaoussanis commented 5 months ago

I've pushed Encore ~v3.100.1~ v3.100.2 which fixes an incorrect assumption (that cljs.analyzer.api will always be present).

I'm not sure I fully understand exactly what you're trying to do though, so hopefully this is sufficient in your case. If not, please let me know what issue you're still seeing with ~v3.100.1~ v3.100.2.

[For reference] Note extra context from here:

hey all - I’m trying to compile from the API (so that I can do a single jack-in using Calva) but if my user ns requires taoensso.timbre, then shadow-cljs throws an error trying to compile taoensso.encore. If I use the same aliases but don’t include the (ns user) from the alias then shadow can compile.

ptaoussanis commented 5 months ago

Update: please use v3.100.2, not v3.100.1.

davidyang commented 5 months ago

Hi @ptaoussanis - v3.100.2 fixed the issue - thanks so much!

Let me do my best to explain the situation:

I don't think I'm trying to do anything strange with shadow (seems pretty standard to have the Shadow compiler run in the same JVM as the web server app if you're working on both):

My impression briefly looking at the source code is that encore has two ways to detect that it's being compiled by CLJS (both the reader conditional and through &env) and if it's required in the JVM portion AND then later compiled by shadow-cljs there's some state that gets mixed up. Otherwise I don't really understand why cljs.analyzer.api wouldn't be available in the shadow compile. Just a guess though...

I've included my deps.edn and shadow-cljs.edn here https://gist.github.com/davidyang/c0d186e7b52713c2de56a12b91f424ac

Thanks again for your help!

ptaoussanis commented 5 months ago

You're welcome, thanks for the extra context 👍

encore has two ways to detect that it's being compiled by CLJS (both the reader conditional and through &env)

In case you're wondering why - these serve different purposes. &env is checked when generating macros that target Cljs, since reader conditionals aren't helpful in that case.