From 7bcd13785caeda541f1ef979768849946dda905a Mon Sep 17 00:00:00 2001 From: Roman Gonzalez Date: Thu, 22 Nov 2012 22:55:31 +0000 Subject: [PATCH] CLJS-426 Fix on subvec inconsitent behavior when using invalid ranges --- src/cljs/cljs/core.cljs | 19 ++++++++++++++----- test/cljs/cljs/core_test.cljs | 17 ++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/cljs/cljs/core.cljs b/src/cljs/cljs/core.cljs index 561746f..a62e3e4 100644 --- a/src/cljs/cljs/core.cljs +++ b/src/cljs/cljs/core.cljs @@ -3184,7 +3184,7 @@ reduces them without incurring seq initialization" (pr-str this)) IWithMeta - (-with-meta [coll meta] (Subvec. meta v start end __hash)) + (-with-meta [coll meta] (build-subvec meta v start end __hash)) IMeta (-meta [coll] meta) @@ -3195,11 +3195,11 @@ reduces them without incurring seq initialization" (-pop [coll] (if (== start end) (throw (js/Error. "Can't pop empty vector")) - (Subvec. meta v start (dec end) nil))) + (build-subvec meta v start (dec end) nil))) ICollection (-conj [coll o] - (Subvec. meta (-assoc-n v end o) start (inc end) nil)) + (build-subvec meta (-assoc-n v end o) start (inc end) nil)) IEmptyableCollection (-empty [coll] (with-meta cljs.core.Vector/EMPTY meta)) @@ -3236,7 +3236,7 @@ reduces them without incurring seq initialization" IAssociative (-assoc [coll key val] (let [v-pos (+ start key)] - (Subvec. meta (-assoc v v-pos val) + (build-subvec meta (-assoc v v-pos val) start (max end (inc v-pos)) nil))) @@ -3255,6 +3255,15 @@ reduces them without incurring seq initialization" (-invoke [coll k not-found] (-lookup coll k not-found))) +(defn- build-subvec [meta v start end ^:mutable __hash] + (let [c (count v)] + (when (or (neg? start) + (neg? end) + (> start c) + (> end c)) + (throw (js/Error. "Index out of bounds"))) + (Subvec. meta v start end __hash))) + (defn subvec "Returns a persistent vector of the items in vector from start (inclusive) to end (exclusive). If end is not supplied, @@ -3264,7 +3273,7 @@ reduces them without incurring seq initialization" ([v start] (subvec v start (count v))) ([v start end] - (Subvec. nil v start end nil))) + (build-subvec nil v start end nil))) (defn- tv-ensure-editable [edit node] (if (identical? edit (.-edit node)) diff --git a/test/cljs/cljs/core_test.cljs b/test/cljs/cljs/core_test.cljs index bf425d0..99ef397 100644 --- a/test/cljs/cljs/core_test.cljs +++ b/test/cljs/cljs/core_test.cljs @@ -1007,13 +1007,14 @@ (assert (= 94 (peek stack2)))) ;; subvec - (let [v (vec (range 10)) - s (subvec v 2 8)] + (let [v1 (vec (range 10)) + v2 (vec (range 5)) + s (subvec v1 2 8)] (assert (= s - (-> v + (-> v1 (subvec 2) (subvec 0 6)) - (->> v + (->> v1 (drop 2) (take 6)))) (assert (= 6 (count s))) @@ -1024,7 +1025,13 @@ (conj s 1))) (assert (= 27 (reduce + s))) (assert (= s (vec s))) ; pour into plain vector - (let [m {:x 1}] (assert (= m (meta (with-meta s m)))))) + (let [m {:x 1}] (assert (= m (meta (with-meta s m))))) + ;; go outside ranges + (assert (= :fail (try (subvec v2 0 6) (catch js/Error e :fail)))) + (assert (= :fail (try (subvec v2 6 10) (catch js/Error e :fail)))) + (assert (= :fail (try (subvec v2 6 10) (catch js/Error e :fail)))) + (assert (= :fail (try (subvec v2 3 6) (catch js/Error e :fail)))) + ) ;; TransientVector (let [v1 (vec (range 15 48)) -- 1.7.9.5