Skip to content

Commit

Permalink
CLJS-1600: Destructuring defprotocol fn args causes defrecord impls t…
Browse files Browse the repository at this point in the history
…o silently fail
  • Loading branch information
anmonteiro authored and dnolen committed Sep 16, 2016
1 parent d994f88 commit 309de72
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 14 deletions.
35 changes: 21 additions & 14 deletions src/main/clojure/cljs/core.cljc
Expand Up @@ -1939,20 +1939,27 @@
(core/str "Invalid protocol, " psym
" defines method " mname " with arity 0"))))))
expand-sig (core/fn [fname slot sig]
`(~sig
(if (and (not (nil? ~(first sig)))
(not (nil? (. ~(first sig) ~(symbol (core/str "-" slot)))))) ;; Property access needed here.
(. ~(first sig) ~slot ~@sig)
(let [x# (if (nil? ~(first sig)) nil ~(first sig))
m# (aget ~(fqn fname) (goog/typeOf x#))]
(if-not (nil? m#)
(m# ~@sig)
(let [m# (aget ~(fqn fname) "_")]
(if-not (nil? m#)
(m# ~@sig)
(throw
(missing-protocol
~(core/str psym "." fname) ~(first sig))))))))))
(core/let [sig (core/if-not (every? core/symbol? sig)
(mapv (core/fn [arg]
(core/cond
(core/symbol? arg) arg
(core/and (map? arg) (some? (:as arg))) (:as arg)
:else (gensym))) sig)
sig)]
`(~sig
(if (and (not (nil? ~(first sig)))
(not (nil? (. ~(first sig) ~(symbol (core/str "-" slot)))))) ;; Property access needed here.
(. ~(first sig) ~slot ~@sig)
(let [x# (if (nil? ~(first sig)) nil ~(first sig))
m# (aget ~(fqn fname) (goog/typeOf x#))]
(if-not (nil? m#)
(m# ~@sig)
(let [m# (aget ~(fqn fname) "_")]
(if-not (nil? m#)
(m# ~@sig)
(throw
(missing-protocol
~(core/str psym "." fname) ~(first sig)))))))))))
psym (core/-> psym
(vary-meta update-in [:jsdoc] conj
"@interface")
Expand Down
31 changes: 31 additions & 0 deletions src/test/cljs/cljs/core_test.cljs
Expand Up @@ -3262,6 +3262,37 @@
(is (= (get #js [\h \i] 1.7 :not-found) \i))
(is (= (get "hi" 1.7 :not-found) \i)))

(defprotocol CLJS-1600-IFoo
(foo-fn [_ {:keys [a b] :as x}]))

(defrecord CLJS-1600-Foo []
CLJS-1600-IFoo
(foo-fn [_ {:keys [a b] :as args}]
args))

(deftest test-cljs-1600
(let [foo (reify
CLJS-1600-IFoo
(foo-fn [_ {:keys [a b] :as args}]
args))]
(is (= (foo-fn (->CLJS-1600-Foo) {:a 1 :b 2})
{:a 1 :b 2}))
(is (= (foo-fn foo {:a 1 :b 2})
{:a 1 :b 2})))
;; test that the destructuring works
(let [foo (reify
CLJS-1600-IFoo
(foo-fn [_ {:keys [a b] :as args}]
{:a a :b b}))]
(is (= (foo-fn foo {:a 1 :b 2})
{:a 1 :b 2})))
(let [foo (reify
CLJS-1600-IFoo
(foo-fn [_ {:keys [a b c] :or {c 3}}]
{:c c}))]
(is (= (foo-fn foo {:a 1 :b 2})
{:c 3}))))

(comment
;; ObjMap
;; (let [ks (map (partial str "foo") (range 500))
Expand Down

0 comments on commit 309de72

Please sign in to comment.