Add fvar macro

This commit is contained in:
Dan Holmsand 2014-03-25 11:33:15 +01:00
parent 6389a3889a
commit 976cf8ef0b
3 changed files with 47 additions and 2 deletions

View File

@ -49,6 +49,37 @@
`(aset ~object ~@names ~value)))
(defn- has-fvar [] *assert*)
(defmacro fvar
[f]
(assert (symbol? f))
(if-not (has-fvar)
f
(let [fref (str *ns* "/" f)]
`(let [f# (aget reagent.interop/fvars ~fref)]
(if-not (nil? f#)
f#
(do
(assert (not (nil? ~f))
~(str "undefined fn: " f))
(let [old# (aget ~f "-fvar")
v# (if (not (nil? old#))
old#
(doto #(.apply ~f nil (~'js* "arguments"))
(aset "name" (.-name ~f))
(aset "fvar" true)))]
(aset ~f "-fvar" v#)
(aset reagent.interop/fvars ~fref v#))))))))
(defmacro fvar?
[f]
(if (has-fvar)
`(and (fn? ~f)
(not (nil? (aget ~f "fvar"))))
`(fn? f)))
(defn- kwd [k]
(if (keyword? k) (name k) k))

View File

@ -1,3 +1,4 @@
(ns reagent.interop)
;; Empty file, to allow require with :refer-macros
(def fvars #js {})

View File

@ -1,7 +1,7 @@
(ns testinterop
(:require [cemerick.cljs.test :as t :refer-macros [is deftest]]
[reagent.debug :refer-macros [dbg]]
[reagent.interop :refer-macros [.' .! oget oset odo]]))
[reagent.interop :refer-macros [.' .! fvar fvar? oget oset odo]]))
(deftest interop-basic
(let [o #js{:foo "foo"
@ -88,3 +88,16 @@
(is (= "1bar2" (.' (.' o :foo)
call o 1)))))
(def f nil)
(deftest interop-fvar
(set! f (fn [] "foo"))
(let [f' (fvar f)]
(is (= "foo" (f')))
(set! f (fn [] "foobar"))
(is (= "foobar" (f')))
(is (identical? f' (fvar f)))))