This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-04-01
Channels
- # announcements (11)
- # babashka (21)
- # beginners (57)
- # biff (5)
- # calva (75)
- # clj-commons (20)
- # cljs-dev (27)
- # clojars (88)
- # clojure (18)
- # clojure-europe (11)
- # clojure-germany (1)
- # clojurescript (52)
- # datalevin (25)
- # emacs (2)
- # graphql (2)
- # gratitude (4)
- # off-topic (6)
- # pathom (16)
- # reagent (3)
- # releases (4)
- # shadow-cljs (7)
- # spacemacs (9)
- # transit (3)
- # xtdb (5)
I'm storing a collection of symbols in a set. The collection looks like this:
(def core-vars '#{_PLUS_, inc, ...})
etc.
I always compared the munged name of the symbols. But in some projects, this collection gets printed as
#{+, inc, ..}
only under advanced compilation. I've had a similar bug once with shadow-cljs: https://github.com/thheller/shadow-cljs/issues/1063 which was fixed, but I'm getting this bug with vanilla CLJS now.
Note that not all symbols display as the unmunged version, only +
in this case...
This bug causes (contains the-set '_PLUS_)
to fail under advanced compilation. Does CLJS do comparable optimizations for symbols as shadow? Any pointers to where this might happen?
@thheller suggested:
I guess :optimize-constants
works similarly to what shadow-cljs did before, so I guess its the same munging issuethe problem in shadow-cljs was that it creates var cljs$cst$munged_symbol = new cljs.core.Symbol(null, "munged-symbol");
references and sometimes that ended up using the same name
so var cljs$cst$_EQ_ = new cljs.core.Symbol(null, "=");
and var cljs$cst$_EQ_ = new cljs.core.Symbol(null, "_EQ_");
ah yes: https://github.com/clojure/clojurescript/blob/30171a3c423ee265e0aa814f2063ebb042931b75/src/main/clojure/cljs/compiler.cljc#L407-L411 I'll provide an issue + fix for it
A repro:
(ns test.project)
(def x '+)
(def y '_PLUS_)
(defn -main [& _args]
(prn [x y])
(prn (= x y)))
(set! *main-cli-fn* -main)
$clj -M -m cljs.main --target nodejs -O simple -c test.project
$ node .cljs_node_repl/main.js
[+ _PLUS_]
false
$ clj -M -m cljs.main --target nodejs -O advanced -c test.project
$ node .cljs_node_repl/main.js
[+ +]
true
@dnolen @thheller I've got a fix here which solves the problem in the above repro and I double-checked that the symbols are still properly shortened with advanced compilation: https://github.com/borkdude/clojurescript/commit/0ec3e6c9ead7930861f036fc24ccac9fd14be662
Re=new Qb(null,"_PLUS_","_PLUS_",-89880507,null)
Se=new Qb(null,"+","+",-740910886,null)
I would appreciate your feedback before I make a proper patch. Also I wonder if I should add a test for this or not, and if so, where/how. I could move the "index table" into the env instead of making it global, not sure if that's important.
I think that'll fail with caching? can't remember how or even if there is any cache though
a simpler option may be just md5 hashing the source name and using that as a variable name. no munging conflicts that way and :advanced
will turn it into something more gzip friendly anyways
I remember proposing something like that to you too :) We could also do a hex64 encoding
it seems the compiler already uses stuff like this: (symbol (str "cljs.user.source$form$" (util/content-sha (pr-str src) 7)))
in various places
yeah only issue is that md5 or any hash is pretty hostile for gzipping, so less than ideal if :advanced
is not used
@thheller how likely is it that people would use :optimize-constants
without :advanced
?
otherwise I see no reason why you'd disable it, shadow-cljs doesn't even allow you to disable
Created the issue: https://clojure.atlassian.net/browse/CLJS-3401
I wonder if we could just use the original string length as the extra "index" since:
+ -> _PLUS_ ;;=> 1 (vs 6 munged) ==> cst$sym$1$_PLUS_
_PLUS_ ;;=> 6 (vs 6 munged) ==> cst$sym$6$_PLUS_
Since the munging always makes the original string longer it would avoid the conflict. But perhaps I'm missing some case where you could have the same munged string with the same original length for different symbols?