cljs.proxy/builder

functionsince v1.12.116Edit
(builder)
(builder key-fn)

Source docstring:
EXPERIMENTAL: Returns a JavaScript Proxy ctor fn with the provided
key-fn. Invoking the returned fn on ClojureScript maps and vectors
will returned proxied values that can be used transparently as
JavaScript objects and arrays:

  (def proxy (builder))

  (def proxied-map (proxy {:foo 1 :bar 2}))
  (goog.object/get proxied-map "foo") ;; => 1

  (def proxied-vec (proxy [1 2 3 4]))
  (aget proxied-vec 1) ;; => 2

Access patterns from JavaScript on these proxied values will lazily,
recursively return further proxied values:

  (def nested-proxies (proxy [{:foo 1 :bar 2}]))
  (-> nested-proxies (aget 0) (goog.object/get "foo")) ;; => 1

Note key-fn is only used for proxied ClojureScript maps. This
function should map strings to the appropriate key
representation. If unspecified, key-fn defaults to keyword. All maps
proxied from the same ctor fn will share the same key-fn cache.
Source code @ clojurescript:src/main/cljs/cljs/proxy.cljs
(defn builder
  ([]
   (builder keyword))
  ([key-fn]
   (js* "var __ctor")
   (let [cache-key-fn (write-through key-fn)
         vec-handler  #js {:get (fn [^cljs.core/IIndexed target prop receiver]
                                  (if (identical? prop "length")
                                    (-count ^cljs.core/ICounted target)
                                    (let [n (js* "+~{}" prop)]
                                      (when (and (number? n)
                                                 (not (isNaN n)))
                                        (js/__ctor (-nth target n nil))))))

                           :has (fn [^cljs.core/IAssociative target prop]
                                  (if (identical? prop "length")
                                    true
                                    (let [n (js* "+~{}" prop)]
                                      (and (number? n)
                                           (not (isNaN n))
                                           (<= 0 n)
                                           (< n (-count ^cljs.core/ICounted target))))))

                           :getPrototypeOf
                           (fn [target] nil)

                           :ownKeys
                           (fn [target] #js ["length"])

                           :getOwnPropertyDescriptor
                           (fn [target prop] desc)}
         map-handler #js {:get (fn [^cljs.core/ILookup target prop receiver]
                                 (js/__ctor (-lookup target (cache-key-fn prop))))

                          :has (fn [^cljs.core/IAssociative target prop]
                                 (-contains-key? target (cache-key-fn prop)))

                          :getPrototypeOf
                          (fn [target] nil)

                          :ownKeys
                          (fn [target]
                            (when (nil? (.-cljs$cachedOwnKeys target))
                              (set! (. target -cljs$cachedOwnKeys)
                                (into-array (map -name (keys target)))))
                            (.-cljs$cachedOwnKeys target))

                          :getOwnPropertyDescriptor
                          (fn [target prop] desc)}
         __ctor (fn [target]
                  (cond
                    (implements? IMap target) (Proxy. target map-handler)
                    (implements? IVector target) (Proxy. target vec-handler)
                    :else target))] 
     __ctor)))