🎉 Add facility to define custom js class

This commit is contained in:
Andrey Antukh 2025-05-07 11:41:26 +02:00
parent 99e325acaf
commit 1bcfa4b8dc

View file

@ -93,6 +93,51 @@
(when (some? obj)
(js* "Object.entries(~{}).reduce((a, [k,v]) => (v == null ? a : (a[k]=v, a)), {}) " obj))))
#?(:cljs
(defn plain-object?
^boolean
[o]
(and (some? o)
(identical? (.getPrototypeOf js/Object o)
(.-prototype js/Object)))))
;; EXPERIMENTAL: unsafe, does not checks and not validates the input,
;; should be improved over time, for now it works for define a class
;; extending js/Error that is more than enought for a first, quick and
;; dirty macro impl for generating classes.
(defmacro class
"Create a class instance"
[& {:keys [name extends constructor]}]
(let [params
(if (and constructor (= 'fn (first constructor)))
(into [] (drop 1) (second constructor))
[])
constructor-sym
(symbol name)
constructor
(if constructor
constructor
`(fn ~name [~'this]
(.call ~extends ~'this)))]
`(let [konstructor# ~constructor
extends# ~extends
~constructor-sym
(fn ~constructor-sym ~params
(cljs.core/this-as ~'this
(konstructor# ~'this ~@params)))]
(set! (.-prototype ~constructor-sym)
(js/Object.create (.-prototype extends#)))
(set! (.-constructor (.-prototype ~constructor-sym))
konstructor#)
~constructor-sym)))
(defmacro add-properties!
"Adds properties to an object using `.defineProperty`"
[rsym & properties]