Deprecate reagent.interop ns, fixes #419

This commit is contained in:
Juho Teperi 2019-01-04 11:45:32 +02:00
parent 1678887627
commit d4038cb911
5 changed files with 152 additions and 4 deletions

View File

@ -13,10 +13,8 @@ to normalize and combine `:class` values (similar to `classnames` JS library)
- Fix comparing Reagent `PartialFn` to `nil` ([#385](https://github.com/reagent-project/reagent/issues/385))
- Reagent no longer abuses `aget` or `aset` for accessing objects, and instead
uses correct Object interop forms, allowing use of ClojureScript `:checked-arrays :warn` option. ([#325](https://github.com/reagent-project/reagent/issues/325))
- **Removed `reagent.interop` namespace**
- These macros where bad practice and don't work properly if
React code is optimized by Closure. Proper object interop forms or `goog.object` functions
should be used instead.
- Deprecated `reagent.interop` namespace
- It is better to use proper object interop forms or `goog.object` functions instead.
## 0.8.1 (2018-05-15)

91
src/reagent/interop.clj Normal file
View File

@ -0,0 +1,91 @@
(ns reagent.interop
(:require [clojure.string :as string :refer [join]]))
; taken from cljs.core
; https://github.com/binaryage/cljs-oops/issues/14
(defmacro unchecked-aget
([array idx]
(list 'js* "(~{}[~{}])" array idx))
([array idx & idxs]
(let [astr (apply str (repeat (count idxs) "[~{}]"))]
`(~'js* ~(str "(~{}[~{}]" astr ")") ~array ~idx ~@idxs))))
; taken from cljs.core
; https://github.com/binaryage/cljs-oops/issues/14
(defmacro unchecked-aset
([array idx val]
(list 'js* "(~{}[~{}] = ~{})" array idx val))
([array idx idx2 & idxv]
(let [n (dec (count idxv))
astr (apply str (repeat n "[~{}]"))]
`(~'js* ~(str "(~{}[~{}][~{}]" astr " = ~{})") ~array ~idx ~idx2 ~@idxv))))
(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]))
(defonce $-warning
(delay
(try
(cljs.util/debug-prn "WARNING: reagent.interop/$ has been deprecated. Consider using ClojureScript JS-interop forms or goog.object namespace instead.")
(catch Exception _ nil))))
(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)."
{:deprecated true}
[object member & args]
@$-warning
(let [[field names] (dot-args object member)]
(if field
(do
(assert (empty? args)
(str "Passing args to field doesn't make sense: " member))
`(unchecked-aget ~object ~@names))
(js-call (list* 'reagent.interop/unchecked-aget object names) args))))
(defonce $!-warning
(delay
(try
(cljs.util/debug-prn "WARNING: reagent.interop/$! has been deprecated. Consider using ClojureScript JS-interop forms or goog.object namespace instead.")
(catch Exception _ nil))))
(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."
{:deprecated true}
[object field value]
@$!-warning
(let [[field names] (dot-args object field)]
(assert field (str "Field name must start with - in " field))
`(unchecked-aset ~object ~@names ~value)))

2
src/reagent/interop.cljs Normal file
View File

@ -0,0 +1,2 @@
(ns reagent.interop
(:require-macros [reagent.interop]))

View File

@ -6,6 +6,7 @@
[reagenttest.testtrack]
[reagenttest.testwithlet]
[reagenttest.testwrap]
[reagenttest.testinterop]
[reagent.impl.template-test]
[reagent.impl.util-test]
[cljs.test :as test]

View File

@ -0,0 +1,56 @@
(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)))))