Skip to content

Commit 2747012

Browse files
authored
CLJS-3425: Incorrect handling of ##NaN with min/max (#282)
- prefix inlining min/max as unchecked - fix min and max fns to do what Clojure does
1 parent 10fc535 commit 2747012

File tree

3 files changed

+44
-23
lines changed

3 files changed

+44
-23
lines changed

src/main/cljs/cljs/core.cljs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,7 +1608,7 @@ reduces them without incurring seq initialization"
16081608
-1
16091609
(loop [idx (cond
16101610
(pos? start) start
1611-
(neg? start) (max 0 (+ start len))
1611+
(neg? start) (unchecked-max 0 (+ start len))
16121612
:else start)]
16131613
(if (< idx len)
16141614
(if (= (nth coll idx) x)
@@ -1624,7 +1624,7 @@ reduces them without incurring seq initialization"
16241624
(if (zero? len)
16251625
-1
16261626
(loop [idx (cond
1627-
(pos? start) (min (dec len) start)
1627+
(pos? start) (unchecked-min (dec len) start)
16281628
(neg? start) (+ len start)
16291629
:else start)]
16301630
(if (>= idx 0)
@@ -1695,7 +1695,7 @@ reduces them without incurring seq initialization"
16951695

16961696
ICounted
16971697
(-count [_]
1698-
(max 0 (- (alength arr) i)))
1698+
(unchecked-max 0 (- (alength arr) i)))
16991699

17001700
IIndexed
17011701
(-nth [coll n]
@@ -2801,17 +2801,32 @@ reduces them without incurring seq initialization"
28012801
:added "1.11.10"}
28022802
[a] (Math/abs a))
28032803

2804+
(defn NaN?
2805+
"Returns true if num is NaN, else false"
2806+
[val]
2807+
(js/isNaN val))
2808+
28042809
(defn ^number max
28052810
"Returns the greatest of the nums."
28062811
([x] x)
2807-
([x y] (cljs.core/max x y))
2812+
([x y]
2813+
(cond
2814+
(NaN? x) x
2815+
(NaN? y) y
2816+
(> x y) x
2817+
:else y))
28082818
([x y & more]
28092819
(reduce max (cljs.core/max x y) more)))
28102820

28112821
(defn ^number min
28122822
"Returns the least of the nums."
28132823
([x] x)
2814-
([x y] (cljs.core/min x y))
2824+
([x y]
2825+
(cond
2826+
(NaN? x) x
2827+
(NaN? y) y
2828+
(< x y) x
2829+
:else y))
28152830
([x y & more]
28162831
(reduce min (cljs.core/min x y) more)))
28172832

@@ -6156,7 +6171,7 @@ reduces them without incurring seq initialization"
61566171
(let [v-pos (+ start n)]
61576172
(if (or (neg? n) (<= (inc end) v-pos))
61586173
(throw (js/Error. (str_ "Index " n " out of bounds [0," (-count coll) "]")))
6159-
(build-subvec meta (assoc v v-pos val) start (max end (inc v-pos)) nil))))
6174+
(build-subvec meta (assoc v v-pos val) start (unchecked-max end (inc v-pos)) nil))))
61606175

61616176
IReduce
61626177
(-reduce [coll f]
@@ -9924,7 +9939,7 @@ reduces them without incurring seq initialization"
99249939

99259940
IChunkedSeq
99269941
(-chunked-first [rng]
9927-
(IntegerRangeChunk. start step (min cnt 32)))
9942+
(IntegerRangeChunk. start step (unchecked-min cnt 32)))
99289943
(-chunked-rest [rng]
99299944
(if (<= cnt 32)
99309945
()
@@ -10326,7 +10341,7 @@ reduces them without incurring seq initialization"
1032610341
(cons match-vals
1032710342
(lazy-seq
1032810343
(let [post-idx (+ (.-index matches)
10329-
(max 1 (.-length match-str)))]
10344+
(unchecked-max 1 (.-length match-str)))]
1033010345
(when (<= post-idx (.-length s))
1033110346
(re-seq* re (subs s post-idx)))))))))
1033210347

@@ -12163,11 +12178,6 @@ reduces them without incurring seq initialization"
1216312178
[x]
1216412179
(instance? goog.Uri x))
1216512180

12166-
(defn NaN?
12167-
"Returns true if num is NaN, else false"
12168-
[val]
12169-
(js/isNaN val))
12170-
1217112181
(defn ^:private parsing-err
1217212182
"Construct message for parsing for non-string parsing error"
1217312183
[val]
@@ -12296,7 +12306,7 @@ reduces them without incurring seq initialization"
1229612306
-1
1229712307
(loop [idx (cond
1229812308
(pos? start) start
12299-
(neg? start) (max 0 (+ start len))
12309+
(neg? start) (unchecked-max 0 (+ start len))
1230012310
:else start)]
1230112311
(if (< idx len)
1230212312
(if (= (-nth coll idx) x)
@@ -12309,7 +12319,7 @@ reduces them without incurring seq initialization"
1230912319
(if (zero? len)
1231012320
-1
1231112321
(loop [idx (cond
12312-
(pos? start) (min (dec len) start)
12322+
(pos? start) (unchecked-min (dec len) start)
1231312323
(neg? start) (+ len start)
1231412324
:else start)]
1231512325
(if (>= idx 0)

src/main/clojure/cljs/core.cljc

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,17 +1201,21 @@
12011201
(core/defmacro ^::ana/numeric neg? [x]
12021202
`(< ~x 0))
12031203

1204-
(core/defmacro ^::ana/numeric max
1204+
(core/defmacro ^::ana/numeric unchecked-max
12051205
([x] x)
1206-
([x y] `(let [x# ~x, y# ~y]
1207-
(~'js* "((~{} > ~{}) ? ~{} : ~{})" x# y# x# y#)))
1208-
([x y & more] `(max (max ~x ~y) ~@more)))
1206+
([x y]
1207+
`(let [x# ~x, y# ~y]
1208+
(if (> x# y#) x# y#)))
1209+
([x y & more]
1210+
`(max (max ~x ~y) ~@more)))
12091211

1210-
(core/defmacro ^::ana/numeric min
1212+
(core/defmacro ^::ana/numeric unchecked-min
12111213
([x] x)
1212-
([x y] `(let [x# ~x, y# ~y]
1213-
(~'js* "((~{} < ~{}) ? ~{} : ~{})" x# y# x# y#)))
1214-
([x y & more] `(min (min ~x ~y) ~@more)))
1214+
([x y]
1215+
`(let [x# ~x, y# ~y]
1216+
(if (< x# y#) x# y#)))
1217+
([x y & more]
1218+
`(min (min ~x ~y) ~@more)))
12151219

12161220
(core/defmacro ^::ana/numeric js-mod [num div]
12171221
(core/list 'js* "(~{} % ~{})" num div))

src/test/cljs/cljs/core_test.cljs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,3 +1986,10 @@
19861986
(str x obj y "\"foobar\"" 1 :foo nil))]
19871987
(testing "object is stringified using toString"
19881988
(is (= "correct6\"foobar\"1:foo" (str-fn nil (+ 1 2 3)))))))
1989+
1990+
(deftest test-cljs-3425
1991+
(testing "Incorrect min/max handling of ##NaN"
1992+
(is (NaN? (min ##NaN 1)))
1993+
(is (NaN? (min 1 ##NaN)))
1994+
(is (NaN? (max ##NaN 1)))
1995+
(is (NaN? (max 1 ##NaN)))))

0 commit comments

Comments
 (0)