mirror of https://github.com/status-im/reagent.git
Fix aget/aset use with objects
This removes the interop macros which used aget/aset and prevented Closure naming mangling, now normal property and method access is used where possible, and goog.object used when using variable keys. Further testing is needed to ensure this works correctly with Closure, as there are some properties that are used with goog.object in one place, and as property in another. Fixes #324
This commit is contained in:
parent
1c5d361070
commit
b7304d0f3f
|
@ -2,8 +2,7 @@
|
|||
(:require [clojure.string :as string]
|
||||
[goog.events :as evt]
|
||||
[reagent.core :as r]
|
||||
[reagent.debug :refer-macros [dbg log dev?]]
|
||||
[reagent.interop :as i :refer-macros [$ $!]])
|
||||
[reagent.debug :refer-macros [dbg log dev?]])
|
||||
(:import goog.History
|
||||
[goog.history Html5History EventType]))
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@
|
|||
:output-dir "target/cljsbuild/client/public/js/out"
|
||||
:output-to "target/cljsbuild/client/public/js/main.js"
|
||||
:asset-path "js/out"
|
||||
:npm-deps false}}
|
||||
:npm-deps false
|
||||
:checked-arrays :warn}}
|
||||
|
||||
:client-npm
|
||||
{:source-paths ["demo"]
|
||||
|
@ -68,7 +69,8 @@
|
|||
:main "reagentdemo.dev"
|
||||
:output-dir "target/cljsbuild/client-npm/public/js/out"
|
||||
:output-to "target/cljsbuild/client-npm/public/js/main.js"
|
||||
:asset-path "js/out"}}
|
||||
:asset-path "js/out"
|
||||
:checked-arrays :warn}}
|
||||
|
||||
:test
|
||||
{:source-paths ["test"]
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
assert-some assert-component
|
||||
assert-js-object assert-new-state
|
||||
assert-callable]]
|
||||
[reagent.interop :refer-macros [$ $!]]
|
||||
[reagent.dom :as dom]))
|
||||
|
||||
(def is-client util/is-client)
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
[reagent.impl.template :as tmpl]
|
||||
[reagent.impl.batching :as batch]
|
||||
[reagent.ratom :as ratom]
|
||||
[reagent.debug :refer-macros [dbg]]
|
||||
[reagent.interop :refer-macros [$ $!]]))
|
||||
[reagent.debug :refer-macros [dbg]]))
|
||||
|
||||
(defonce ^:private imported nil)
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
(:require ["react-dom/server" :as dom-server]
|
||||
[reagent.impl.util :as util]
|
||||
[reagent.impl.template :as tmpl]
|
||||
[reagent.ratom :as ratom]
|
||||
[reagent.interop :refer-macros [$ $!]]))
|
||||
[reagent.ratom :as ratom]))
|
||||
|
||||
(defonce ^:private imported nil)
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
(ns reagent.impl.batching
|
||||
(:refer-clojure :exclude [flush])
|
||||
(:require [reagent.debug :refer-macros [dbg assert-some]]
|
||||
[reagent.interop :refer-macros [$ $!]]
|
||||
[reagent.impl.util :refer [is-client]]
|
||||
[clojure.string :as string]))
|
||||
[clojure.string :as string]
|
||||
[goog.object :as gobj]))
|
||||
|
||||
;;; Update batching
|
||||
|
||||
|
@ -19,15 +19,15 @@
|
|||
(if-not is-client
|
||||
fake-raf
|
||||
(let [w js/window]
|
||||
(or ($ w :requestAnimationFrame)
|
||||
($ w :webkitRequestAnimationFrame)
|
||||
($ w :mozRequestAnimationFrame)
|
||||
($ w :msRequestAnimationFrame)
|
||||
(or (.-requestAnimationFrame w)
|
||||
(.-webkitRequestAnimationFrame w)
|
||||
(.-mozRequestAnimationFrame w)
|
||||
(.-msRequestAnimationFrame w)
|
||||
fake-raf))))
|
||||
|
||||
(defn compare-mount-order [c1 c2]
|
||||
(- ($ c1 :cljsMountOrder)
|
||||
($ c2 :cljsMountOrder)))
|
||||
(- (.-cljsMountOrder c1)
|
||||
(.-cljsMountOrder c2)))
|
||||
|
||||
(defn run-queue [a]
|
||||
;; sort components by mount order, to make sure parents
|
||||
|
@ -35,8 +35,8 @@
|
|||
(.sort a compare-mount-order)
|
||||
(dotimes [i (alength a)]
|
||||
(let [c (aget a i)]
|
||||
(when (true? ($ c :cljsIsDirty))
|
||||
($ c forceUpdate)))))
|
||||
(when (true? (.-cljsIsDirty c))
|
||||
(.forceUpdate c)))))
|
||||
|
||||
|
||||
;; Set from ratom.cljs
|
||||
|
@ -46,16 +46,16 @@
|
|||
Object
|
||||
(enqueue [this k f]
|
||||
(assert-some f "Enqueued function")
|
||||
(when (nil? (aget this k))
|
||||
(aset this k (array)))
|
||||
(.push (aget this k) f)
|
||||
(when (nil? (gobj/get this k))
|
||||
(gobj/set this k (array)))
|
||||
(.push (gobj/get this k) f)
|
||||
(.schedule this))
|
||||
|
||||
(run-funs [this k]
|
||||
(when-some [fs (aget this k)]
|
||||
(aset this k nil)
|
||||
(when-some [^array fs (gobj/get this k)]
|
||||
(gobj/set this k nil)
|
||||
(dotimes [i (alength fs)]
|
||||
((aget fs i)))))
|
||||
((gobj/get fs i)))))
|
||||
|
||||
(schedule [this]
|
||||
(when-not scheduled?
|
||||
|
@ -81,8 +81,8 @@
|
|||
(flush-queues [this]
|
||||
(.run-funs this "beforeFlush")
|
||||
(ratom-flush)
|
||||
(when-some [cs (aget this "componentQueue")]
|
||||
(aset this "componentQueue" nil)
|
||||
(when-some [cs (.-componentQueue this)]
|
||||
(set! (.-componentQueue this) nil)
|
||||
(run-queue cs))
|
||||
(.flush-after-render this)))
|
||||
|
||||
|
@ -95,12 +95,12 @@
|
|||
(.flush-after-render render-queue))
|
||||
|
||||
(defn queue-render [c]
|
||||
(when-not ($ c :cljsIsDirty)
|
||||
($! c :cljsIsDirty true)
|
||||
(when-not (.-cljsIsDirty c)
|
||||
(set! (.-cljsIsDirty c) true)
|
||||
(.queue-render render-queue c)))
|
||||
|
||||
(defn mark-rendered [c]
|
||||
($! c :cljsIsDirty false))
|
||||
(set! (.-cljsIsDirty c) false))
|
||||
|
||||
(defn do-before-flush [f]
|
||||
(.add-before-flush render-queue f))
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
[reagent.impl.util :as util]
|
||||
[reagent.impl.batching :as batch]
|
||||
[reagent.ratom :as ratom]
|
||||
[reagent.interop :refer-macros [$ $!]]
|
||||
[reagent.debug :refer-macros [dbg prn dev? warn error warn-unless
|
||||
assert-callable]]))
|
||||
assert-callable]]
|
||||
[goog.object :as gobj]))
|
||||
|
||||
(declare ^:dynamic *current-component*)
|
||||
|
||||
|
@ -16,10 +16,12 @@
|
|||
(defn shallow-obj-to-map [o]
|
||||
(let [ks (js-keys o)
|
||||
len (alength ks)]
|
||||
(loop [m {} i 0]
|
||||
(loop [m {}
|
||||
i 0]
|
||||
(if (< i len)
|
||||
(let [k (aget ks i)]
|
||||
(recur (assoc m (keyword k) (aget o k)) (inc i)))
|
||||
(recur (assoc m (keyword k) (gobj/get o k))
|
||||
(inc i)))
|
||||
m))))
|
||||
|
||||
(defn extract-props [v]
|
||||
|
@ -33,52 +35,52 @@
|
|||
(subvec v first-child))))
|
||||
|
||||
(defn props-argv [c p]
|
||||
(if-some [a ($ p :argv)]
|
||||
(if-some [a (.-argv p)]
|
||||
a
|
||||
[(.-constructor c) (shallow-obj-to-map p)]))
|
||||
|
||||
(defn get-argv [c]
|
||||
(props-argv c ($ c :props)))
|
||||
(props-argv c (.-props c)))
|
||||
|
||||
(defn get-props [c]
|
||||
(let [p ($ c :props)]
|
||||
(if-some [v ($ p :argv)]
|
||||
(let [p (.-props c)]
|
||||
(if-some [v (.-argv p)]
|
||||
(extract-props v)
|
||||
(shallow-obj-to-map p))))
|
||||
|
||||
(defn get-children [c]
|
||||
(let [p ($ c :props)]
|
||||
(if-some [v ($ p :argv)]
|
||||
(let [p (.-props c)]
|
||||
(if-some [v (.-argv p)]
|
||||
(extract-children v)
|
||||
(->> ($ p :children)
|
||||
(->> (.-children p)
|
||||
(react/Children.toArray)
|
||||
(into [])))))
|
||||
|
||||
(defn ^boolean reagent-class? [c]
|
||||
(and (fn? c)
|
||||
(some? (some-> c .-prototype ($ :reagentRender)))))
|
||||
(some? (some-> c .-prototype (.-reagentRender)))))
|
||||
|
||||
(defn ^boolean react-class? [c]
|
||||
(and (fn? c)
|
||||
(some? (some-> c .-prototype ($ :render)))))
|
||||
(some? (some-> c .-prototype (.-render)))))
|
||||
|
||||
(defn ^boolean reagent-component? [c]
|
||||
(some? ($ c :reagentRender)))
|
||||
(some? (.-reagentRender c)))
|
||||
|
||||
(defn cached-react-class [c]
|
||||
($ c :cljsReactClass))
|
||||
(.-cljsReactClass c))
|
||||
|
||||
(defn cache-react-class [c constructor]
|
||||
($! c :cljsReactClass constructor))
|
||||
(set! (.-cljsReactClass c) constructor))
|
||||
|
||||
|
||||
;;; State
|
||||
|
||||
(defn state-atom [this]
|
||||
(let [sa ($ this :cljsState)]
|
||||
(let [sa (.-cljsState this)]
|
||||
(if-not (nil? sa)
|
||||
sa
|
||||
($! this :cljsState (ratom/atom nil)))))
|
||||
(set! (.-cljsState this) (ratom/atom nil)))))
|
||||
|
||||
;; avoid circular dependency: this gets set from template.cljs
|
||||
(defonce as-element nil)
|
||||
|
@ -87,9 +89,9 @@
|
|||
;;; Rendering
|
||||
|
||||
(defn wrap-render [c]
|
||||
(let [f ($ c :reagentRender)
|
||||
(let [f (.-reagentRender c)
|
||||
_ (assert-callable f)
|
||||
res (if (true? ($ c :cljsLegacyRender))
|
||||
res (if (true? (.-cljsLegacyRender c))
|
||||
(.call f c c)
|
||||
(let [v (get-argv c)
|
||||
n (count v)]
|
||||
|
@ -106,7 +108,7 @@
|
|||
(fn [& args]
|
||||
(as-element (apply vector res args)))
|
||||
res)]
|
||||
($! c :reagentRender f)
|
||||
(set! (.-reagentRender c) f)
|
||||
(recur c))
|
||||
:else res)))
|
||||
|
||||
|
@ -137,7 +139,7 @@
|
|||
(fn render []
|
||||
(this-as c (if util/*non-reactive*
|
||||
(do-render c)
|
||||
(let [rat ($ c :cljsRatom)]
|
||||
(let [rat (.-cljsRatom c)]
|
||||
(batch/mark-rendered c)
|
||||
(if (nil? rat)
|
||||
(ratom/run-in-reaction #(do-render c) c "cljsRatom"
|
||||
|
@ -163,8 +165,8 @@
|
|||
(this-as c
|
||||
;; Don't care about nextstate here, we use forceUpdate
|
||||
;; when only when state has changed anyway.
|
||||
(let [old-argv ($ c :props.argv)
|
||||
new-argv ($ nextprops :argv)
|
||||
(let [old-argv (.. c -props -argv)
|
||||
new-argv (.-argv nextprops)
|
||||
noargv (or (nil? old-argv) (nil? new-argv))]
|
||||
(cond
|
||||
(nil? f) (or noargv (not= old-argv new-argv))
|
||||
|
@ -182,7 +184,7 @@
|
|||
:componentWillMount
|
||||
(fn componentWillMount []
|
||||
(this-as c
|
||||
($! c :cljsMountOrder (batch/next-mount-count))
|
||||
(set! (.-cljsMountOrder c) (batch/next-mount-count))
|
||||
(when-not (nil? f)
|
||||
(.call f c c))))
|
||||
|
||||
|
@ -193,7 +195,7 @@
|
|||
:componentWillUnmount
|
||||
(fn componentWillUnmount []
|
||||
(this-as c
|
||||
(some-> ($ c :cljsRatom)
|
||||
(some-> (.-cljsRatom c)
|
||||
ratom/dispose!)
|
||||
(batch/mark-rendered c)
|
||||
(when-not (nil? f)
|
||||
|
@ -255,7 +257,7 @@
|
|||
(defn map-to-js [m]
|
||||
(reduce-kv (fn [o k v]
|
||||
(doto o
|
||||
(aset (name k) v)))
|
||||
(gobj/set (name k) v)))
|
||||
#js{} m))
|
||||
|
||||
(defn cljsify [body]
|
||||
|
@ -273,10 +275,10 @@
|
|||
|
||||
(defn fiber-component-path [fiber]
|
||||
(let [name (some-> fiber
|
||||
($ :type)
|
||||
($ :displayName))
|
||||
(.-type)
|
||||
(.-displayName))
|
||||
parent (some-> fiber
|
||||
($ :return))
|
||||
(.-:return))
|
||||
path (some-> parent
|
||||
fiber-component-path
|
||||
(str " > "))
|
||||
|
@ -286,18 +288,18 @@
|
|||
(defn component-path [c]
|
||||
;; Alternative branch for React 16
|
||||
;; Try both original name (for UMD foreign-lib) and manged name (property access, for Closure optimized React)
|
||||
(if-let [fiber (or (some-> c ($ :_reactInternalFiber))
|
||||
(if-let [fiber (or (some-> c (gobj/get "_reactInternalFiber"))
|
||||
(some-> c (.-_reactInternalFiber)))]
|
||||
(fiber-component-path fiber)
|
||||
(let [instance (or (some-> c ($ :_reactInternalInstance))
|
||||
(let [instance (or (some-> c (gobj/get "_reactInternalInstance"))
|
||||
(some-> c (.-_reactInternalInstance))
|
||||
c)
|
||||
elem (or (some-> instance ($ :_currentElement))
|
||||
elem (or (some-> instance (gobj/get "_currentElement"))
|
||||
(some-> instance (.-_currentElement)))
|
||||
name (some-> elem
|
||||
($ :type)
|
||||
($ :displayName))
|
||||
owner (or (some-> elem ($ :_owner))
|
||||
(.-type)
|
||||
(.-displayName))
|
||||
owner (or (some-> elem (gobj/get "_owner"))
|
||||
(some-> elem (.-_owner)))
|
||||
path (some-> owner
|
||||
component-path
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
[reagent.impl.component :as comp]
|
||||
[reagent.impl.batching :as batch]
|
||||
[reagent.ratom :as ratom]
|
||||
[reagent.interop :refer-macros [$ $!]]
|
||||
[reagent.debug :refer-macros [dbg prn println log dev?
|
||||
warn warn-unless]]))
|
||||
warn warn-unless]]
|
||||
[goog.object :as gobj]))
|
||||
|
||||
(declare as-element)
|
||||
|
||||
|
@ -44,14 +44,15 @@
|
|||
|
||||
(defn cache-get [o k]
|
||||
(when ^boolean (.hasOwnProperty o k)
|
||||
(aget o k)))
|
||||
(gobj/get o k)))
|
||||
|
||||
(defn cached-prop-name [k]
|
||||
(if (named? k)
|
||||
(if-some [k' (cache-get prop-name-cache (name k))]
|
||||
k'
|
||||
(aset prop-name-cache (name k)
|
||||
(util/dash-to-camel k)))
|
||||
(let [v (util/dash-to-camel k)]
|
||||
(gobj/set prop-name-cache (name k))
|
||||
v))
|
||||
k))
|
||||
|
||||
(defn ^boolean js-val? [x]
|
||||
|
@ -61,8 +62,7 @@
|
|||
|
||||
(defn kv-conv [o k v]
|
||||
(doto o
|
||||
(aset (cached-prop-name k)
|
||||
(convert-prop-value v))))
|
||||
(gobj/set (cached-prop-name k) (convert-prop-value v))))
|
||||
|
||||
(defn convert-prop-value [x]
|
||||
(cond (js-val? x) x
|
||||
|
@ -82,8 +82,7 @@
|
|||
(if (named? k)
|
||||
(if-some [k' (cache-get custom-prop-name-cache (name k))]
|
||||
k'
|
||||
(aset prop-name-cache (name k)
|
||||
(util/dash-to-camel k)))
|
||||
(gobj/set prop-name-cache (name k) (util/dash-to-camel k)))
|
||||
k))
|
||||
|
||||
(defn custom-kv-conv [o k v]
|
||||
|
@ -101,18 +100,18 @@
|
|||
:else (clj->js x)))
|
||||
|
||||
(defn oset [o k v]
|
||||
(doto (if (nil? o) #js{} o)
|
||||
(aset k v)))
|
||||
(doto (if (nil? o) #js {} o)
|
||||
(gobj/set k v)))
|
||||
|
||||
(defn oget [o k]
|
||||
(if (nil? o) nil (aget o k)))
|
||||
(if (nil? o) nil (gobj/get o k)))
|
||||
|
||||
(defn set-id-class
|
||||
"Takes the id and class from tag keyword, and adds them to the
|
||||
other props. Parsed tag is JS object with :id and :class properties."
|
||||
[props id-class]
|
||||
(let [id ($ id-class :id)
|
||||
class ($ id-class :class)]
|
||||
(let [id (.-id id-class)
|
||||
class (.-className id-class)]
|
||||
(cond-> props
|
||||
;; Only use ID from tag keyword if no :id in props already
|
||||
(and (some? id)
|
||||
|
@ -136,7 +135,7 @@
|
|||
(let [props (-> props
|
||||
stringify-class
|
||||
(set-id-class id-class))]
|
||||
(if ($ id-class :custom)
|
||||
(if (.-custom id-class)
|
||||
(convert-custom-prop-value props)
|
||||
(convert-prop-value props))))
|
||||
|
||||
|
@ -159,14 +158,14 @@
|
|||
|
||||
(defn input-node-set-value
|
||||
[node rendered-value dom-value component {:keys [on-write]}]
|
||||
(if-not (and (identical? node ($ js/document :activeElement))
|
||||
(has-selection-api? ($ node :type))
|
||||
(if-not (and (identical? node (.-activeElement js/document))
|
||||
(has-selection-api? (.-type node))
|
||||
(string? rendered-value)
|
||||
(string? dom-value))
|
||||
;; just set the value, no need to worry about a cursor
|
||||
(do
|
||||
($! component :cljsDOMValue rendered-value)
|
||||
($! node :value rendered-value)
|
||||
(set! (.-cljsDOMValue component) rendered-value)
|
||||
(set! (.-value node) rendered-value)
|
||||
(when (fn? on-write)
|
||||
(on-write rendered-value)))
|
||||
|
||||
|
@ -191,37 +190,37 @@
|
|||
;; So this is just a warning. The code below is simple
|
||||
;; enough, but if you are tempted to change it, be aware of
|
||||
;; all the scenarios you have handle.
|
||||
(let [node-value ($ node :value)]
|
||||
(let [node-value (.-value node)]
|
||||
(if (not= node-value dom-value)
|
||||
;; IE has not notified us of the change yet, so check again later
|
||||
(batch/do-after-render #(input-component-set-value component))
|
||||
(let [existing-offset-from-end (- (count node-value)
|
||||
($ node :selectionStart))
|
||||
(.-selectionStart node))
|
||||
new-cursor-offset (- (count rendered-value)
|
||||
existing-offset-from-end)]
|
||||
($! component :cljsDOMValue rendered-value)
|
||||
($! node :value rendered-value)
|
||||
(set! (.-cljsDOMValue component) rendered-value)
|
||||
(set! (.-value node) rendered-value)
|
||||
(when (fn? on-write)
|
||||
(on-write rendered-value))
|
||||
($! node :selectionStart new-cursor-offset)
|
||||
($! node :selectionEnd new-cursor-offset))))))
|
||||
(set! (.-selectionStart node) new-cursor-offset)
|
||||
(set! (.-selectionEnd node) new-cursor-offset))))))
|
||||
|
||||
(defn input-component-set-value [this]
|
||||
(when ($ this :cljsInputLive)
|
||||
($! this :cljsInputDirty false)
|
||||
(let [rendered-value ($ this :cljsRenderedValue)
|
||||
dom-value ($ this :cljsDOMValue)
|
||||
(when (.-cljsInputLive this)
|
||||
(set! (.-cljsInputDirty this) false)
|
||||
(let [rendered-value (.-cljsRenderedValue this)
|
||||
dom-value (.-cljsDOMValue this)
|
||||
;; Default to the root node within this component
|
||||
node (find-dom-node this)]
|
||||
(when (not= rendered-value dom-value)
|
||||
(input-node-set-value node rendered-value dom-value this {})))))
|
||||
|
||||
(defn input-handle-change [this on-change e]
|
||||
($! this :cljsDOMValue (-> e .-target .-value))
|
||||
(set! (.-cljsDOMValue this) (-> e .-target .-value))
|
||||
;; Make sure the input is re-rendered, in case on-change
|
||||
;; wants to keep the value unchanged
|
||||
(when-not ($ this :cljsInputDirty)
|
||||
($! this :cljsInputDirty true)
|
||||
(when-not (.-cljsInputDirty this)
|
||||
(set! (.-cljsInputDirty this) true)
|
||||
(batch/do-after-render #(input-component-set-value this)))
|
||||
(on-change e))
|
||||
|
||||
|
@ -234,21 +233,20 @@
|
|||
(.hasOwnProperty jsprops "value"))
|
||||
(assert find-dom-node
|
||||
"reagent.dom needs to be loaded for controlled input to work")
|
||||
(let [v ($ jsprops :value)
|
||||
(let [v (.-value jsprops)
|
||||
value (if (nil? v) "" v)
|
||||
on-change ($ jsprops :onChange)]
|
||||
(when-not ($ this :cljsInputLive)
|
||||
on-change (.-onChange jsprops)]
|
||||
(when-not (.-cljsInputLive this)
|
||||
;; set initial value
|
||||
($! this :cljsInputLive true)
|
||||
($! this :cljsDOMValue value))
|
||||
($! this :cljsRenderedValue value)
|
||||
(set! (.-cljsInputLive this) true)
|
||||
(set! (.-cljsDOMValue this) value))
|
||||
(set! (.-cljsRenderedValue this) value)
|
||||
(js-delete jsprops "value")
|
||||
(doto jsprops
|
||||
($! :defaultValue value)
|
||||
($! :onChange #(input-handle-change this on-change %))))))
|
||||
(set! (.-defaultValue jsprops) value)
|
||||
(set! (.-onChange jsprops) #(input-handle-change this on-change %)))))
|
||||
|
||||
(defn input-unmount [this]
|
||||
($! this :cljsInputLive nil))
|
||||
(set! (.-cljsInputLive this) nil))
|
||||
|
||||
(defn ^boolean input-component? [x]
|
||||
(case x
|
||||
|
@ -308,9 +306,9 @@
|
|||
|
||||
(defn reag-element [tag v]
|
||||
(let [c (comp/as-class tag)
|
||||
jsprops #js{:argv v}]
|
||||
jsprops #js {:argv v}]
|
||||
(when-some [key (key-from-vec v)]
|
||||
($! jsprops :key key))
|
||||
(set! (.-key jsprops) key))
|
||||
(react/createElement c jsprops)))
|
||||
|
||||
(defn fragment-element [argv]
|
||||
|
@ -324,33 +322,36 @@
|
|||
|
||||
(defn adapt-react-class
|
||||
[c]
|
||||
(doto (->NativeWrapper)
|
||||
($! :name c)
|
||||
($! :id nil)
|
||||
($! :class nil)))
|
||||
(let [x (->NativeWrapper)]
|
||||
(set! (.-name x) c)
|
||||
(set! (.-id x) nil)
|
||||
(set! (.-class x) nil)
|
||||
x))
|
||||
|
||||
(def tag-name-cache #js{})
|
||||
|
||||
(defn cached-parse [x]
|
||||
(if-some [s (cache-get tag-name-cache x)]
|
||||
s
|
||||
(aset tag-name-cache x (parse-tag x))))
|
||||
(let [v (parse-tag x)]
|
||||
(gobj/set tag-name-cache x v)
|
||||
v)))
|
||||
|
||||
(defn native-element [parsed argv first]
|
||||
(let [comp ($ parsed :name)]
|
||||
(let [props (nth argv first nil)
|
||||
hasprops (or (nil? props) (map? props))
|
||||
jsprops (convert-props (if hasprops props) parsed)
|
||||
first-child (+ first (if hasprops 1 0))]
|
||||
(if (input-component? comp)
|
||||
(-> [(reagent-input) argv comp jsprops first-child]
|
||||
(with-meta (meta argv))
|
||||
as-element)
|
||||
(let [key (-> (meta argv) get-key)
|
||||
p (if (nil? key)
|
||||
jsprops
|
||||
(oset jsprops "key" key))]
|
||||
(make-element argv comp p first-child))))))
|
||||
(let [comp (.-name parsed)
|
||||
props (nth argv first nil)
|
||||
hasprops (or (nil? props) (map? props))
|
||||
jsprops (convert-props (if hasprops props) parsed)
|
||||
first-child (+ first (if hasprops 1 0))]
|
||||
(if (input-component? comp)
|
||||
(-> [(reagent-input) argv comp jsprops first-child]
|
||||
(with-meta (meta argv))
|
||||
as-element)
|
||||
(let [key (-> (meta argv) get-key)
|
||||
p (if (nil? key)
|
||||
jsprops
|
||||
(oset jsprops "key" key))]
|
||||
(make-element argv comp p first-child)))))
|
||||
|
||||
(defn str-coll [coll]
|
||||
(if (dev?)
|
||||
|
@ -423,7 +424,7 @@
|
|||
(let [val (aget a i)]
|
||||
(when (and (vector? val)
|
||||
(nil? (key-from-vec val)))
|
||||
($! o :no-key true))
|
||||
(set! (.-no-key o) true))
|
||||
(aset a i (as-element val))))
|
||||
a))
|
||||
|
||||
|
@ -433,7 +434,7 @@
|
|||
(when derefed
|
||||
(warn (hiccup-err x "Reactive deref not supported in lazy seq, "
|
||||
"it should be wrapped in doall")))
|
||||
(when ($ ctx :no-key)
|
||||
(when (.-no-key ctx)
|
||||
(warn (hiccup-err x "Every element in a seq should have a unique :key")))
|
||||
res))
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
(ns reagent.impl.util
|
||||
(:require [reagent.debug :refer-macros [dbg log warn]]
|
||||
[reagent.interop :refer-macros [$ $!]]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(def is-client (and (exists? js/window)
|
||||
(-> js/window ($ :document) nil? not)))
|
||||
(-> (.-document js/window) nil? not)))
|
||||
|
||||
(def ^:dynamic ^boolean *non-reactive* false)
|
||||
|
||||
|
@ -40,8 +39,8 @@
|
|||
|
||||
(defn fun-name [f]
|
||||
(let [n (or (and (fn? f)
|
||||
(or ($ f :displayName)
|
||||
($ f :name)))
|
||||
(or (.-displayName f)
|
||||
(.-name f)))
|
||||
(and (implements? INamed f)
|
||||
(name f))
|
||||
(let [m (meta f)]
|
||||
|
@ -137,5 +136,5 @@
|
|||
(defn force-update [comp deep]
|
||||
(if deep
|
||||
(binding [*always-update* true]
|
||||
($ comp forceUpdate))
|
||||
($ comp forceUpdate)))
|
||||
(.forceUpdate comp))
|
||||
(.forceUpdate comp)))
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
(ns reagent.interop
|
||||
(:require [clojure.string :as string :refer [join]]))
|
||||
|
||||
(defn- js-call [f args]
|
||||
(let [argstr (->> (repeat (count args) "~{}")
|
||||
(join ","))]
|
||||
(list* 'js* (str "~{}(" argstr ")") f args)))
|
||||
|
||||
(defn- dot-args [object member]
|
||||
(assert (or (symbol? member)
|
||||
(keyword? member))
|
||||
(str "Symbol or keyword expected, not " (pr-str member)))
|
||||
(assert (or (not (symbol? object))
|
||||
(not (re-find #"\." (name object))))
|
||||
(str "Dot not allowed in " object))
|
||||
(let [n (name member)
|
||||
field? (or (keyword? member)
|
||||
(= (subs n 0 1) "-"))
|
||||
names (-> (if (symbol? member)
|
||||
(string/replace n #"^-" "")
|
||||
n)
|
||||
(string/split #"\."))]
|
||||
[field? names]))
|
||||
|
||||
(defmacro $
|
||||
"Access member in a javascript object, in a Closure-safe way.
|
||||
'member' is assumed to be a field if it is a keyword or if
|
||||
the name starts with '-', otherwise the named function is
|
||||
called with the optional args.
|
||||
'member' may contain '.', to allow access in nested objects.
|
||||
If 'object' is a symbol it is not allowed contain '.'.
|
||||
|
||||
($ o :foo) is equivalent to (.-foo o), except that it gives
|
||||
the same result under advanced compilation.
|
||||
($ o foo arg1 arg2) is the same as (.foo o arg1 arg2)."
|
||||
[object member & args]
|
||||
(let [[field names] (dot-args object member)]
|
||||
(if field
|
||||
(do
|
||||
(assert (empty? args)
|
||||
(str "Passing args to field doesn't make sense: " member))
|
||||
`(aget ~object ~@names))
|
||||
(js-call (list* 'aget object names) args))))
|
||||
|
||||
(defmacro $!
|
||||
"Set field in a javascript object, in a Closure-safe way.
|
||||
'field' should be a keyword or a symbol starting with '-'.
|
||||
'field' may contain '.', to allow access in nested objects.
|
||||
If 'object' is a symbol it is not allowed contain '.'.
|
||||
|
||||
($! o :foo 1) is equivalent to (set! (.-foo o) 1), except that it
|
||||
gives the same result under advanced compilation."
|
||||
[object field value]
|
||||
(let [[field names] (dot-args object field)]
|
||||
(assert field (str "Field name must start with - in " field))
|
||||
`(aset ~object ~@names ~value)))
|
|
@ -1,2 +0,0 @@
|
|||
(ns reagent.interop
|
||||
(:require-macros [reagent.interop]))
|
|
@ -4,7 +4,8 @@
|
|||
(:require [reagent.impl.util :as util]
|
||||
[reagent.debug :refer-macros [dbg log warn error dev? time]]
|
||||
[reagent.impl.batching :as batch]
|
||||
[clojure.set :as s]))
|
||||
[clojure.set :as s]
|
||||
[goog.object :as obj]))
|
||||
|
||||
(declare ^:dynamic *ratom-context*)
|
||||
(defonce ^boolean debug false)
|
||||
|
@ -176,7 +177,7 @@
|
|||
(def ^{:private true :const true} cache-key "reagReactionCache")
|
||||
|
||||
(defn- cached-reaction [f o k obj destroy]
|
||||
(let [m (aget o cache-key)
|
||||
(let [m (obj/get o cache-key)
|
||||
m (if (nil? m) {} m)
|
||||
r (m k nil)]
|
||||
(cond
|
||||
|
@ -185,15 +186,15 @@
|
|||
:else (let [r (make-reaction
|
||||
f :on-dispose (fn [x]
|
||||
(when debug (swap! -running dec))
|
||||
(as-> (aget o cache-key) _
|
||||
(as-> (obj/get o cache-key) _
|
||||
(dissoc _ k)
|
||||
(aset o cache-key _))
|
||||
(obj/set o cache-key _))
|
||||
(when (some? obj)
|
||||
(set! (.-reaction obj) nil))
|
||||
(when (some? destroy)
|
||||
(destroy x))))
|
||||
v (-deref r)]
|
||||
(aset o cache-key (assoc m k r))
|
||||
(obj/set o cache-key (assoc m k r))
|
||||
(when debug (swap! -running inc))
|
||||
(when (some? obj)
|
||||
(set! (.-reaction obj) r))
|
||||
|
@ -507,7 +508,7 @@
|
|||
(._set-opts r opts)
|
||||
(set! (.-f r) f)
|
||||
(set! (.-auto-run r) #(run obj))
|
||||
(aset obj key r))
|
||||
(obj/set obj key r))
|
||||
res))
|
||||
|
||||
(defn check-derefs [f]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
(ns reagenttest.runtests
|
||||
(:require [reagenttest.testreagent]
|
||||
[reagenttest.testcursor]
|
||||
[reagenttest.testinterop]
|
||||
[reagenttest.testratom]
|
||||
[reagenttest.testratomasync]
|
||||
[reagenttest.testtrack]
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
(ns reagenttest.testinterop
|
||||
(:require [cljs.test :as t :refer-macros [is deftest]]
|
||||
[reagent.debug :refer-macros [dbg]]
|
||||
[reagent.interop :refer-macros [$ $!]]))
|
||||
|
||||
;; (def is-adv (let [o #js{}]
|
||||
;; (set! (.-somethinglong o) true)
|
||||
;; (not= (aget (.keys js/Object o) 0) "somethinglong")))
|
||||
|
||||
(deftest iterop-quote
|
||||
(let [o #js{:foo "foo"
|
||||
:foobar #js{:bar "bar"
|
||||
:bar-foo "bar-foo"}
|
||||
:bar-foo "barfoo"}]
|
||||
|
||||
(is (= "foo" ($ o :foo)))
|
||||
(is (= "bar" ($ o :foobar.bar)))
|
||||
(is (= "barfoo" ($ o :bar-foo)))
|
||||
|
||||
(is (= "foo" ($ o -foo)))
|
||||
(is (= "bar" ($ o -foobar.bar)))
|
||||
(is (= "bar-foo" ($ o -foobar.bar-foo)))
|
||||
(is (= "bar-foo" ($ o :foobar.bar-foo)))
|
||||
|
||||
($! o :foo "foo1")
|
||||
(is (= "foo1" ($ o :foo)))
|
||||
|
||||
($! o -foo "foo2")
|
||||
(is (= "foo2" ($ o -foo)))
|
||||
|
||||
($! o :foobar.bar "bar1")
|
||||
(is (= "bar1" ($ o :foobar.bar)))
|
||||
|
||||
($! o -foobar.bar "bar1")
|
||||
(is (= "bar1" ($ o -foobar.bar)))))
|
||||
|
||||
(deftest interop-quote-call
|
||||
(let [o #js{:bar "bar1"
|
||||
:foo (fn [x]
|
||||
(this-as this
|
||||
(str x ($ this :bar))))}
|
||||
o2 #js{:o o}]
|
||||
(is (= "ybar1" ($ o foo "y")))
|
||||
(is (= "xxbar1" ($ o2 o.foo "xx")))
|
||||
(is (= "abar1" (-> o2
|
||||
($ :o)
|
||||
($ foo "a"))))
|
||||
|
||||
(is (= "bar1" ($ o foo)))
|
||||
(is (= "bar1" ($ o2 o.foo)))
|
||||
|
||||
($! o :bar "bar2")
|
||||
(is (= "bar2" ($ o foo)))
|
||||
|
||||
(is (= "1bar2" ($ ($ o :foo)
|
||||
call o 1)))))
|
|
@ -4,7 +4,6 @@
|
|||
[create-react-class :as create-react-class]
|
||||
[reagent.ratom :as rv :refer-macros [reaction]]
|
||||
[reagent.debug :as debug :refer-macros [dbg println log dev?]]
|
||||
[reagent.interop :refer-macros [$ $!]]
|
||||
[reagent.core :as r]
|
||||
[reagent.dom.server :as server]
|
||||
[reagent.impl.util :as util]
|
||||
|
@ -448,8 +447,8 @@
|
|||
(this-as
|
||||
this
|
||||
(r/create-element
|
||||
"div" #js{:className ($ this :props.className)}
|
||||
($ this :props.children))))}))
|
||||
"div" #js{:className (.. this -props -className)}
|
||||
(.. this -props -children))))}))
|
||||
|
||||
(deftest test-adapt-class
|
||||
(let [d1 (r/adapt-react-class ndiv)
|
||||
|
@ -1055,7 +1054,7 @@
|
|||
(let [old @spy]
|
||||
(is (nil? (r/after-render
|
||||
(fn []
|
||||
(is (= "DIV" ($ @node :tagName)))
|
||||
(is (= "DIV" (.-tagName @node)))
|
||||
(swap! spy inc)))))
|
||||
(is (= old @spy))
|
||||
(is (= @exp @val))
|
||||
|
|
Loading…
Reference in New Issue