binaryage / cljs-oops

ClojureScript macros for convenient native Javascript object access.
Other
350 stars 13 forks source link

Don't warn in `oset!` if var is `:const` #23

Closed AndreTheHunter closed 4 years ago

AndreTheHunter commented 5 years ago

In ClojureScript 1.9.655, :const variables are inlined. See https://blog.fikesfarm.com/posts/2017-06-28-clojurescript-const-var-inlining.html and https://dev.clojure.org/jira/browse/CLJS-2093.

Since the variable value is inlined, it should be usable by cljs-oops:

(defonce ^:const ks [:oops :i :did :it :again])
(defonce ^:const strs (mapv #(str \! (name %)) ks))
;["!oops" "!i" "!did" "!it" "!again"]

(oset! #js {} strs true)
;Error: Oops, Unexpected dynamic selector usage (consider using oset!+)

Using [binaryage/oops "0.6.4"] running in browser tests via [thheller/shadow-cljs "2.8.35"] (https://shadow-cljs.github.io/docs/UsersGuide.html#target-browser-test)

darwin commented 5 years ago

I wasn't aware of ^:const. It looks like a useful optimization. But your example seems to not be " compile-time static edn value".

From Mike's article:

If you define a ^:const Var initialized with something that is not a compile-time static edn value, then the value will not be inlined (but the no re-definition rule will still apply).

In other words. My macro code in oset! must see "strs" as inlined value ["!oops" "!i" "!did" "!it" "!again"] which is not the case in your example because of str and mapv usage.