Add obj and munging to interop

.' and .! now behaves just like builtin interop, except that
they work the same under advanced compilation.
This commit is contained in:
Dan Holmsand 2015-09-25 11:48:50 +02:00
parent 55a4b4e1df
commit 64d1e11966
2 changed files with 70 additions and 7 deletions

View File

@ -20,16 +20,44 @@
names (-> (if (symbol? member)
(string/replace n #"^-" "")
n)
(string/split #"\."))]
(string/split #"\."))
names (map munge names)]
[field? names]))
(defmacro obj
"Create a javascript object in a Closure-safe way. The arguments
are expected to be key-value pairs, where the keys should be either
keywords or strings.
(obj :foo 1)
is equivalent to
(let [o (js-obj)]
(set! (.-foo o) 1)
o)
except that it gives the same result under advanced compilation."
[& args]
(assert (= 0 (mod (count args) 2))
"Even number of arguments expected")
(let [munged (map-indexed (fn [i x]
(if (odd? i)
x
(if (keyword? x)
(munge (name x))
x)))
args)]
`(cljs.core/js-obj ~@munged)))
(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 '.'."
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
@ -43,7 +71,10 @@
"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 '.'."
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))

View File

@ -1,19 +1,28 @@
(ns reagenttest.testinterop
(:require [cljs.test :as t :refer-macros [is deftest]]
[reagent.debug :refer-macros [dbg]]
[reagent.interop :refer-macros [.' .!]]))
[reagent.interop :refer-macros [.' .! obj]]))
(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 "barfoo"}]
(let [o (obj :foo "foo"
:foobar (obj :bar "bar"
:bar-foo "bar-foo")
:bar-foo "barfoo")]
(is (= "foo" (.' o :foo)))
(is (= "bar" (.' o :foobar.bar)))
(is (= "barfoo" (.' o :bar-foo)))
(when-not is-adv
(is (= "barfoo" (.-bar-foo o))))
(is (= "foo" (.' o -foo)))
(is (= "bar" (.' o -foobar.bar)))
(is (= "bar-foo" (.' o -foobar.bar-foo)))
(is (= "bar-foo" (.' o :foobar.bar-foo)))
(is (= "barfoo" (.' o -bar-foo)))
(.! o :foo "foo1")
@ -48,3 +57,26 @@
(is (= "1bar2" (.' (.' o :foo)
call o 1)))))
(deftest interop-munge
(let [o (obj :foo-bar "foo-bar"
:foo? "foo?"
:foo$ "foo$"
:foo! "foo!"
:foo><*+% "foo><*+%")]
(is (= (.' o :foo-bar) "foo-bar"))
(is (= (.' o :foo?) "foo?"))
(is (= (.' o :foo$) "foo$"))
(is (= (.' o -foo!) "foo!"))
(is (= (.' o :foo><*+%) "foo><*+%"))
(when-not is-adv
(is (= (.-foo-bar o) "foo-bar"))
(is (= (.-foo? o) "foo?"))
(is (= (.-foo$ o) "foo$"))
(is (= (.-foo><*+% o) "foo><*+%"))
(let [x (js-obj)]
(.! x -foo-bar "foo-bar")
(is (= (.-foo-bar x) "foo-bar"))
(set! (.-foo? x) "foo?")
(is (= (.' x :foo?) "foo?"))))))