Skip to content

Commit 309de72

Browse files
anmonteirodnolen
authored andcommitted
CLJS-1600: Destructuring defprotocol fn args causes defrecord impls to silently fail
1 parent d994f88 commit 309de72

2 files changed

Lines changed: 52 additions & 14 deletions

File tree

src/main/clojure/cljs/core.cljc

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,20 +1939,27 @@
19391939
(core/str "Invalid protocol, " psym
19401940
" defines method " mname " with arity 0"))))))
19411941
expand-sig (core/fn [fname slot sig]
1942-
`(~sig
1943-
(if (and (not (nil? ~(first sig)))
1944-
(not (nil? (. ~(first sig) ~(symbol (core/str "-" slot)))))) ;; Property access needed here.
1945-
(. ~(first sig) ~slot ~@sig)
1946-
(let [x# (if (nil? ~(first sig)) nil ~(first sig))
1947-
m# (aget ~(fqn fname) (goog/typeOf x#))]
1948-
(if-not (nil? m#)
1949-
(m# ~@sig)
1950-
(let [m# (aget ~(fqn fname) "_")]
1951-
(if-not (nil? m#)
1952-
(m# ~@sig)
1953-
(throw
1954-
(missing-protocol
1955-
~(core/str psym "." fname) ~(first sig))))))))))
1942+
(core/let [sig (core/if-not (every? core/symbol? sig)
1943+
(mapv (core/fn [arg]
1944+
(core/cond
1945+
(core/symbol? arg) arg
1946+
(core/and (map? arg) (some? (:as arg))) (:as arg)
1947+
:else (gensym))) sig)
1948+
sig)]
1949+
`(~sig
1950+
(if (and (not (nil? ~(first sig)))
1951+
(not (nil? (. ~(first sig) ~(symbol (core/str "-" slot)))))) ;; Property access needed here.
1952+
(. ~(first sig) ~slot ~@sig)
1953+
(let [x# (if (nil? ~(first sig)) nil ~(first sig))
1954+
m# (aget ~(fqn fname) (goog/typeOf x#))]
1955+
(if-not (nil? m#)
1956+
(m# ~@sig)
1957+
(let [m# (aget ~(fqn fname) "_")]
1958+
(if-not (nil? m#)
1959+
(m# ~@sig)
1960+
(throw
1961+
(missing-protocol
1962+
~(core/str psym "." fname) ~(first sig)))))))))))
19561963
psym (core/-> psym
19571964
(vary-meta update-in [:jsdoc] conj
19581965
"@interface")

src/test/cljs/cljs/core_test.cljs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3262,6 +3262,37 @@
32623262
(is (= (get #js [\h \i] 1.7 :not-found) \i))
32633263
(is (= (get "hi" 1.7 :not-found) \i)))
32643264

3265+
(defprotocol CLJS-1600-IFoo
3266+
(foo-fn [_ {:keys [a b] :as x}]))
3267+
3268+
(defrecord CLJS-1600-Foo []
3269+
CLJS-1600-IFoo
3270+
(foo-fn [_ {:keys [a b] :as args}]
3271+
args))
3272+
3273+
(deftest test-cljs-1600
3274+
(let [foo (reify
3275+
CLJS-1600-IFoo
3276+
(foo-fn [_ {:keys [a b] :as args}]
3277+
args))]
3278+
(is (= (foo-fn (->CLJS-1600-Foo) {:a 1 :b 2})
3279+
{:a 1 :b 2}))
3280+
(is (= (foo-fn foo {:a 1 :b 2})
3281+
{:a 1 :b 2})))
3282+
;; test that the destructuring works
3283+
(let [foo (reify
3284+
CLJS-1600-IFoo
3285+
(foo-fn [_ {:keys [a b] :as args}]
3286+
{:a a :b b}))]
3287+
(is (= (foo-fn foo {:a 1 :b 2})
3288+
{:a 1 :b 2})))
3289+
(let [foo (reify
3290+
CLJS-1600-IFoo
3291+
(foo-fn [_ {:keys [a b c] :or {c 3}}]
3292+
{:c c}))]
3293+
(is (= (foo-fn foo {:a 1 :b 2})
3294+
{:c 3}))))
3295+
32653296
(comment
32663297
;; ObjMap
32673298
;; (let [ks (map (partial str "foo") (range 500))

0 commit comments

Comments
 (0)