hoplon

2023-11-11T23:10:21.317439Z

This ☝️ PR adds a provider that uses the dom apis directly. I added an experimental :smart-class attribute that can remove classes when using strings or vectors. But it doesn't compose well as multiple calls would remove classes that shouldn't be removed.

✨ 3
borkdude 2023-11-13T12:48:35.873189Z

Wouldn't it make sense to load that dom namespace by default? It's not like it's going to add much extra weight to the library? I wonder if removing the multimethod indirection altogether would make stuff perform better. It seems the multimethod was only there to offer a choice between jquery and goog but now that isn't necessary anymore?

borkdude 2023-11-13T12:49:22.514049Z

I'm not sure if applied-science.js-interop adds more size to the bundle, but probably not since they are mostly macros that emit direct JS interop code when used properly

2023-11-13T13:00:48.065779Z

I did a build report and the dom provider is smaller than goog and js-interop adds 45 bytes.

borkdude 2023-11-13T13:05:24.877709Z

this 45 bytes is probably a mis-representation, because it's just a dummy module that refers to its real function in another module

borkdude 2023-11-13T13:05:37.645019Z

you have to expand all the sections to see where those functions were moved

borkdude 2023-11-13T13:05:50.530349Z

I can take a look if you tell me how to build

2023-11-13T13:06:53.434479Z

> Wouldn't it make sense to load that dom namespace by default? It's not like it's going to add much extra weight to the library? I wonder if removing the multimethod indirection altogether would make stuff perform better. It seems the multimethod was only there to offer a choice between jquery and goog but now that isn't necessary anymore? That would be a potential breaking change for projects that depend on jquery that is the current default so I want to make sure that this is working as it should before changing it. Multimethods predate the goog provider and are a mechanism for users to add custom attributes and I'm not sure of a good way to provide that without using them (considering the ergonomics of using this extension mechanism).

borkdude 2023-11-13T13:07:35.621539Z

understood

2023-11-13T13:13:48.658709Z

> I can take a look if you tell me how to build The way I'm testing this is not something I'm proud yet but it works 😅 • clone hoplon locally https://github.com/hoplon/hoplon and checkout the dom-provider branch • clone hoplon-demos locally https://github.com/hoplon/demos and checkout the hoplon-local-counter branch. • go to the counters directory on hoplon-demos: ◦ npm installnpx shadow-cljs watch app

borkdude 2023-11-13T13:14:26.335679Z

I mean the build report, you do this with npx shadow-cljs build app with some flag?

borkdude 2023-11-13T13:14:59.725339Z

I didn't port that since this file wasn't reachable from nextjournal.clojure-mode

borkdude 2023-11-13T13:15:11.480589Z

but I can have a stab at it

borkdude 2023-11-13T13:15:18.880339Z

whoops wrong channel

2023-11-13T13:16:12.663259Z

The file src/demo/counter.cljs on the counters demo has the requires for the providers. I comment the providers that I don't want and leave only the one I want. To build the report the command is npx shadow-cljs run shadow.cljs.build-report app report.html

borkdude 2023-11-13T13:20:49.177889Z

you're right, only 45 bytes for applied-science.js-interop, amazing :)

borkdude 2023-11-13T13:21:44.889139Z

well, good job, hope the PR gets merged

2023-11-13T13:21:54.940119Z

I think that the core namespace could be bigger because of the macro expansion, but not sure about how to confirm this.

borkdude 2023-11-13T13:22:30.108799Z

I think the js-interop macros do their best to generate compact code

borkdude 2023-11-13T13:23:34.485909Z

although in some cases, like get-in you will get bigger code because of nil checks:

cljs.user=> (macroexpand '(j/get-in x [:foo :bar]))
(let* [obj1617 (clojure.core/let [obj1616 x] (if (clojure.core/some? obj1616) (cljs.core/unchecked-get obj1616 "foo") js/undefined))] (if (clojure.core/some? obj1617) (cljs.core/unchecked-get obj1617 "bar") js/undefined))

2023-11-13T13:23:57.197379Z

> well, good job, hope the PR gets merged Thanks! It will. I will revert the namespace change on the goog provider and will merge it soon and make a release.

borkdude 2023-11-13T13:24:22.466699Z

rather than (.. x -foo -bar)

2023-11-13T13:24:33.995849Z

I could use !get-in I think.

borkdude 2023-11-13T13:25:45.121289Z

cljs.user=> (str (fn [x] (.. x -foo -bar)))
"function (x){\nreturn x.foo.bar;\n}"

borkdude 2023-11-13T13:25:51.710249Z

that is by far the shortest you will get

borkdude 2023-11-13T13:26:20.141939Z

also slightly more performant

2023-11-13T13:26:32.750459Z

I probably should remove js-interop too. I will do before merging.

borkdude 2023-11-13T13:28:14.039889Z

it is convenient, but maybe for a library it's nice to have little dependencies

2023-11-13T13:32:33.101129Z

I wanted to replace goog.obj/set. I will see what would be other options for that. To access attributes, I will not use js-interop anymore.

borkdude 2023-11-13T13:32:49.065139Z

you can do this by using unchecked-set

borkdude 2023-11-13T13:33:10.893219Z

(unchecked-set obj "foo" 1)

borkdude 2023-11-13T13:33:33.059089Z

cljs.user=> (str (fn [obj] (unchecked-set obj "foo" 1)))
"function (obj){\nreturn (obj[\"foo\"] = (1));\n}"

borkdude 2023-11-13T13:35:18.909639Z

or:

cljs.user=> (str (fn [obj] (set! (.-foo obj) 1)))
"function (obj){\nreturn (obj.foo = (1));\n}"

2023-11-13T13:40:08.405699Z

Oh, this is great, thank you!

2023-11-13T13:40:47.098739Z

Is there a difference between set! and unchecked-set?

borkdude 2023-11-13T13:41:38.350839Z

unchecked-set bypasses advanced compilation, but I think if you add a ^js type hint for the argument you pass to set it will also do the same. shadow-cljs will warn you if it can't infer that it is a JS value or not

borkdude 2023-11-13T13:42:00.527179Z

testing with advanced compilation in CI is a necessity imo

2023-11-13T13:43:11.234319Z

Yeah, I added tests using advanced compilation to the ci in this pr for all providers.

borkdude 2023-11-13T13:44:12.292979Z

👍