Fork me on GitHub
#clojurescript
<
2022-03-08
>
markbastian00:03:31

How would I add a static method to a clojurescript deftype (or any other common mechanism - defrecord or protocols are also ok)? I’m trying to convert this fragment to cljs:

class SimpleImage {
  static get toolbox() {
    return {
      title: 'Image',
      icon: '<svg width="17" height="15" viewBox="0 0 336 276" xmlns=""><path d="M291 150V79c0-19-15-34-34-34H79c-19 0-34 15-34 34v42l67-44 81 72 56-29 42 30zm0 52l-43-30-56 30-81-67-66 39v23c0 19 15 34 34 34h178c17 0 31-13 34-29zM79 0h178c44 0 79 35 79 79v118c0 44-35 79-79 79H79c-44 0-79-35-79-79V79C0 35 35 0 79 0z"/></svg>'
    };
  }

  render(){
    return document.createElement('input');
  }
}
In cljs it appears to work fine for non-static methods to just do:
(deftype Foo []
  (render [this] ....))
I just don’t know how to register the static get toolbox function. Any ideas? Thanks!

Sam Ritchie00:03:53

Why not create a separate defn outside the deftype?

markbastian00:03:49

The calling API is expecting a static class method.

markbastian01:03:42

Figured it out… (set! (. Foo -toolbox) result)

metal 2
dvingo03:03:56

I think you can also use (specify! with object. kind of hard to search github for it, but this came up: https://github.com/clojure/clojurescript/blob/a4673b880756531ac5690f7b4721ad76c0810327/src/test/clojure/cljs/compiler_tests.clj#L227

pez14:03:21

Consider writing a small blog post or tweet about it, @U0JUR9FPH. It might seem like silly, but it'll help the next dev with a similar question.

❤️ 2
henryw37418:03:43

Somehow having clojurescript in deps (*clojure cli ver 1.10.3.1087)* is causing the wrong version of clojure.data.json to be in the classpath: as expected, with just current data.json

clj -Sdeps '{:deps { org.clojure/data.json {:mvn/version "2.4.0"}}}'

Clojure 1.10.3
user=> (require 'clojure.data.json)
nil
user=> (clojure.data.json/write-str (java.time.Instant/now))
"\"2022-03-08T18:34:30.019053Z\""
with cljs in the classpath:
clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "RELEASE" :exclusions [org.clojure/data.json]} org.clojure/data.json {:mvn/version "2.4.0"}}}'

Clojure 1.10.3
user=> (require 'clojure.data.json)
nil
user=> (clojure.data.json/write-str (java.time.Instant/now))
Execution error at clojure.data.json/write-generic (json.clj:385).
Don't know how to write JSON of class java.time.Instant
tl;dr I can see it's getting an old version of data.json, apparently the one clojurescript depends on. using the -Stree clojure option it shows the 2.4.0 version is selected. even calling http://clojure.java.io/resource on the data.json ns shows it being in the 2.4.0 jar on the classpath. I see cljs on master has now upgraded to data.json 2.4.0, but still, it'd be good to know what's going on here. possibly not really a clojurescript issue per se, but is this a known thing?

Alex Miller (Clojure team)18:03:32

ClojureScript embeds a version of data.json

Alex Miller (Clojure team)18:03:15

because it's embedded, it's not visible to external dependency version selectors and where it ends up on the classpath will affect what version is used

henryw37419:03:20

Thanks Alex. I wonder if that can be fixed

dnolen19:03:29

@henryw374 I believe there is a non-AOT artifact? I can't remember \cc @alexmiller

Alex Miller (Clojure team)20:03:11

non-AOT artifact for ClojureScript?

Alex Miller (Clojure team)20:03:40

for data.json, there are both and cljs uses the AOT but that's really orthogonal to this problem

Alex Miller (Clojure team)20:03:19

clojurescript is a bad actor here in "hiding" a copy of a dep inside itself such that it's not visible to version selectors outside the libs. really, you should never do that in published artifacts without shading to move it to a custom ns (like org.clojurescript.data.json or whatever) - at that point there is a copy but no conflict, users can use both and everyone is fine

Alex Miller (Clojure team)20:03:46

this has not historically been an issue primarily because data.json did not change its api, but now there have been additions so that difference is visible

dnolen21:03:10

I'm not against shading it - I thought ClojureScript had a sources only jar?

dnolen21:03:23

slim or whatever

p-himik21:03:43

No, it does include a compiled version of data.json.

dnolen21:03:04

@p-himik I mean there is another artifact

henryw37411:03:55

I had a look through artifacts in https://mvnrepository.com/artifact/org.clojure but I cannot see any non-aot jar. Anyway, now I understand what's happening I can work around it. Thanks for the help everyone. FYI I wrote up a summary here: https://widdindustries.com/clojurescript-jar-embeds-other-libs/

Alex Miller (Clojure team)12:03:10

The other artifact is same coords but classifier slim

Alex Miller (Clojure team)12:03:56

In deps, you refer to that with $ in the lib name - org.clojure/clojurescript$slim {:mvn/version “1.11.4”}

dnolen21:03:19

it used to be you had to ask for the aot one

p-himik21:03:30

Ah, gotcha.

p-himik21:03:21

But practically speaking - seems like everybody adds org.clojure/clojurescript to their dependencies, so everybody ends up having those AOT artifacts. And it's not just data.json.

Alex Miller (Clojure team)21:03:47

also includes tools.reader and transit-clj and transit-java

👍 1
henryw37411:03:55

I had a look through artifacts in https://mvnrepository.com/artifact/org.clojure but I cannot see any non-aot jar. Anyway, now I understand what's happening I can work around it. Thanks for the help everyone. FYI I wrote up a summary here: https://widdindustries.com/clojurescript-jar-embeds-other-libs/