Skip to content

Commit 402d47e

Browse files
committed
CLJS-3123: 'for' loop silently ignores extra forms in body
1 parent 83a1da8 commit 402d47e

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

src/main/clojure/cljs/analyzer.cljc

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3595,6 +3595,11 @@
35953595
(and (record-tag? tag)
35963596
(contains? (record-basis tag) field)))
35973597

3598+
(defn- invalid-arity? [argc method-params variadic max-fixed-arity]
3599+
(and (not (valid-arity? argc method-params))
3600+
(or (not variadic)
3601+
(and variadic (< argc max-fixed-arity)))))
3602+
35983603
(defn parse-invoke*
35993604
[env [f & args :as form]]
36003605
(let [enve (assoc env :context :expr)
@@ -3623,9 +3628,7 @@
36233628
(when (and #?(:cljs (not (and (gstring/endsWith (str cur-ns) "$macros")
36243629
(symbol-identical? cur-ns ns)
36253630
(true? macro))))
3626-
(not (valid-arity? argc method-params))
3627-
(or (not variadic)
3628-
(and variadic (< argc max-fixed-arity))))
3631+
(invalid-arity? argc method-params variadic max-fixed-arity))
36293632
(warning :fn-arity env {:name name :argc argc}))))
36303633
(when (and kw? (not (or (== 1 argc) (== 2 argc))))
36313634
(warning :fn-arity env {:name (first form) :argc argc}))
@@ -3822,6 +3825,17 @@
38223825
(catch #?(:clj Throwable :cljs :default) e
38233826
(throw (ex-info nil (error-data env :macro-syntax-check (var->sym mac-var)) e))))))))
38243827

3828+
#?(:cljs
3829+
(defn- check-macro-arity [mac-var form]
3830+
(let [mac-sym (.-sym mac-var)]
3831+
(when-let [{:keys [variadic? max-fixed-arity method-params]}
3832+
(get-in @env/*compiler* [::namespaces (symbol (namespace mac-sym)) :defs (symbol (name mac-sym))])]
3833+
(let [argc (count (rest form))
3834+
offset (if (= '&form (ffirst method-params)) 2 0)]
3835+
(when (invalid-arity? argc (map #(nthrest %1 offset) method-params)
3836+
variadic? (when max-fixed-arity (- max-fixed-arity offset)))
3837+
(throw (js/Error. (error-message :fn-arity {:argc argc, :name mac-sym})))))))))
3838+
38253839
(defn macroexpand-1*
38263840
[env form]
38273841
(let [op (first form)]
@@ -3836,6 +3850,7 @@
38363850
:cljs [do])
38373851
(do-macroexpand-check env form mac-var)
38383852
(let [form' (try
3853+
#?(:cljs (check-macro-arity mac-var form))
38393854
(apply @mac-var form env (rest form))
38403855
#?(:clj (catch ArityException e
38413856
(throw (ArityException. (- (.actual e) 2) (.name e)))))

src/test/self/self_host/test.cljs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,64 @@
14991499
(is (empty? (js-keys value)))
15001500
(inc! l)))))))
15011501

1502+
(deftest test-cljs-3129
1503+
(async done
1504+
(let [l (latch 1 done)]
1505+
(let [st (cljs/empty-state)]
1506+
(cljs/eval-str st
1507+
"(ns cljs.user (:require-macros foo-3129-1.core))"
1508+
nil
1509+
{:eval node-eval
1510+
:load (fn [_ cb] (cb {:lang :clj :source "(ns foo-3129-1.core) (defmacro add [a b] `(+ ~a ~b))"}))}
1511+
(fn [{:keys [value error]}]
1512+
(is (nil? error))
1513+
(cljs/eval-str st
1514+
"(foo-3129-1.core/add 1)"
1515+
nil
1516+
{:eval node-eval
1517+
:context :expr}
1518+
(fn [{:keys [error value]}]
1519+
(is (nil? value))
1520+
(is (= "Wrong number of args (1) passed to foo-3129-1.core$macros/add"
1521+
(ex-message (ex-cause (ex-cause error)))))
1522+
(inc! l))))))
1523+
(let [st (cljs/empty-state)]
1524+
(cljs/eval-str st
1525+
"(ns cljs.user (:require-macros foo-3129-2.core))"
1526+
nil
1527+
{:eval node-eval
1528+
:load (fn [_ cb] (cb {:lang :clj :source "(ns foo-3129-2.core) (defmacro add [a b] `(+ ~a ~b))"}))}
1529+
(fn [{:keys [value error]}]
1530+
(is (nil? error))
1531+
(cljs/eval-str st
1532+
"(foo-3129-2.core/add 1 2 3)"
1533+
nil
1534+
{:eval node-eval
1535+
:context :expr}
1536+
(fn [{:keys [error value]}]
1537+
(is (nil? value))
1538+
(is (= "Wrong number of args (3) passed to foo-3129-2.core$macros/add"
1539+
(ex-message (ex-cause (ex-cause error)))))
1540+
(inc! l))))))
1541+
(let [st (cljs/empty-state)]
1542+
(cljs/eval-str st
1543+
"(ns cljs.user (:require-macros foo-3129-3.core))"
1544+
nil
1545+
{:eval node-eval
1546+
:load (fn [_ cb] (cb {:lang :clj :source "(ns foo-3129-3.core) (defmacro when [test & body])"}))}
1547+
(fn [{:keys [value error]}]
1548+
(is (nil? error))
1549+
(cljs/eval-str st
1550+
"(foo-3129-3.core/when)"
1551+
nil
1552+
{:eval node-eval
1553+
:context :expr}
1554+
(fn [{:keys [error value]}]
1555+
(is (nil? value))
1556+
(is (= "Wrong number of args (0) passed to foo-3129-3.core$macros/when"
1557+
(ex-message (ex-cause (ex-cause error)))))
1558+
(inc! l)))))))))
1559+
15021560
(defn -main [& args]
15031561
(run-tests))
15041562

0 commit comments

Comments
 (0)