From eb7d0489342fa5cfab3c05b23cdf4fa1a9e95181 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Tue, 29 Jul 2025 19:17:17 -0400 Subject: [PATCH 001/107] ugh, bring it back --- src/main/cljs/cljs/core.cljs | 369 +++++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 4305440a8..d04fd38db 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12400,3 +12400,372 @@ reduces them without incurring seq initialization" (identical? "window" *global*) (set! goog/global js/window) (identical? "self" *global*) (set! goog/global js/self) (identical? "global" *global*) (set! goog/global js/global))) + +;; ----------------------------------------------------------------------------- +;; Original 2011 Copy-on-Write Types + +;;; Vector + +(deftype Vector [meta array] + IWithMeta + (-with-meta [coll meta] (Vector. meta array)) + + IMeta + (-meta [coll] meta) + + IStack + (-peek [coll] + (let [count (.-length array)] + (when (> count 0) + (aget array (dec count))))) + (-pop [coll] + (if (> (.-length array) 0) + (let [new-array (aclone array)] + (. new-array (pop)) + (Vector. meta new-array)) + (throw (js/Error. "Can't pop empty vector")))) + + ICollection + (-conj [coll o] + (let [new-array (aclone array)] + (.push new-array o) + (Vector. meta new-array))) + + IEmptyableCollection + (-empty [coll] (with-meta (. Vector -EMPTY) meta)) + + ISequential + IEquiv + (-equiv [coll other] (equiv-sequential coll other)) + + IHash + (-hash [coll] (hash-coll coll)) + + ISeqable + (-seq [coll] + (when (> (.-length array) 0) + (let [vector-seq + (fn vector-seq [i] + (lazy-seq + (when (< i (.-length array)) + (cons (aget array i) (vector-seq (inc i))))))] + (vector-seq 0)))) + + ICounted + (-count [coll] (.-length array)) + + IIndexed + (-nth [coll n] + (if (and (<= 0 n) (< n (.-length array))) + (aget array n) + #_(throw (js/Error. (str "No item " n " in vector of length " (.-length array)))))) + (-nth [coll n not-found] + (if (and (<= 0 n) (< n (.-length array))) + (aget array n) + not-found)) + + ILookup + (-lookup [coll k] (-nth coll k nil)) + (-lookup [coll k not-found] (-nth coll k not-found)) + + IAssociative + (-assoc [coll k v] + (let [new-array (aclone array)] + (aset new-array k v) + (Vector. meta new-array))) + + IVector + (-assoc-n [coll n val] (-assoc coll n val)) + + IReduce + (-reduce [v f] + (ci-reduce array f)) + (-reduce [v f start] + (ci-reduce array f start)) + + IFn + (-invoke [coll k] + (-lookup coll k)) + (-invoke [coll k not-found] + (-lookup coll k not-found)) + + IPrintWithWriter + (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "[" " " "]" opts coll))) + +(set! (. Vector -EMPTY) (Vector. nil (array))) + +(set! (. Vector -fromArray) (fn [xs] (Vector. nil xs))) + +; The keys field is an array of all keys of this map, in no particular +; order. Any string, keyword, or symbol key is used as a property name +; to store the value in strobj. If a key is assoc'ed when that same +; key already exists in strobj, the old value is overwritten. If a +; non-string key is assoc'ed, return a HashMap object instead. + +(defn- obj-map-contains-key? + ([k strobj] + (obj-map-contains-key? k strobj true false)) + ([k strobj true-val false-val] + (if (and (goog/isString k) (.hasOwnProperty strobj k)) + true-val + false-val))) + +(defn- obj-map-compare-keys [a b] + (let [a (hash a) + b (hash b)] + (cond + (< a b) -1 + (> a b) 1 + :else 0))) + +(deftype ObjMap [meta keys strobj] + IWithMeta + (-with-meta [coll meta] (ObjMap. meta keys strobj)) + + IMeta + (-meta [coll] meta) + + ICollection + (-conj [coll entry] + (if (vector? entry) + (-assoc coll (-nth entry 0) (-nth entry 1)) + (reduce -conj + coll + entry))) + + IEmptyableCollection + (-empty [coll] (with-meta (. ObjMap -EMPTY) meta)) + + IEquiv + (-equiv [coll other] (equiv-map coll other)) + + IHash + (-hash [coll] (hash-coll coll)) + + ISeqable + (-seq [coll] + (when (pos? (.-length keys)) + (map #(vector % (aget strobj %)) + (.sort keys obj-map-compare-keys)))) + + ICounted + (-count [coll] (.-length keys)) + + ILookup + (-lookup [coll k] (-lookup coll k nil)) + (-lookup [coll k not-found] + (obj-map-contains-key? k strobj (aget strobj k) not-found)) + + IAssociative + (-assoc [coll k v] + (if (goog/isString k) + (let [new-strobj (goog.object/clone strobj) + overwrite? (.hasOwnProperty new-strobj k)] + (aset new-strobj k v) + (if overwrite? + (ObjMap. meta keys new-strobj) ; overwrite + (let [new-keys (aclone keys)] ; append + (.push new-keys k) + (ObjMap. meta new-keys new-strobj)))) + ; non-string key. game over. + (with-meta (into (hash-map k v) (seq coll)) meta))) + (-contains-key? [coll k] + (obj-map-contains-key? k strobj)) + + IMap + (-dissoc [coll k] + (if (and (goog/isString k) (.hasOwnProperty strobj k)) + (let [new-keys (aclone keys) + new-strobj (goog.object/clone strobj)] + (.splice new-keys (scan-array 1 k new-keys) 1) + (js-delete new-strobj k) + (ObjMap. meta new-keys new-strobj)) + coll)) ; key not found, return coll unchanged + + IFn + (-invoke [coll k] + (-lookup coll k)) + (-invoke [coll k not-found] + (-lookup coll k not-found)) + + IPrintWithWriter + (-pr-writer [coll writer opts] + (print-map coll pr-writer writer opts))) + +(set! (. ObjMap -EMPTY) (ObjMap. nil (array) (js-obj))) + +(set! (. ObjMap -fromObject) (fn [ks obj] (ObjMap. nil ks obj))) + +(defn obj-map + "keyval => key val + Returns a new object map with supplied mappings." + [& keyvals] + (let [ks (array) + obj (js-obj)] + (loop [kvs (seq keyvals)] + (if kvs + (do (.push ks (first kvs)) + (gobject/set obj (first kvs) (second kvs)) + (recur (nnext kvs))) + (.fromObject ObjMap ks obj))))) + +; The keys field is an array of all keys of this map, in no particular +; order. Each key is hashed and the result used as a property name of +; hashobj. Each values in hashobj is actually a bucket in order to handle hash +; collisions. A bucket is an array of alternating keys (not their hashes) and +; vals. +(deftype HashMap [meta count hashobj] + IWithMeta + (-with-meta [coll meta] (HashMap. meta count hashobj)) + + IMeta + (-meta [coll] meta) + + ICollection + (-conj [coll entry] + (if (vector? entry) + (-assoc coll (-nth entry 0) (-nth entry 1)) + (reduce -conj + coll + entry))) + + IEmptyableCollection + (-empty [coll] (with-meta (. HashMap -EMPTY) meta)) + + IEquiv + (-equiv [coll other] (equiv-map coll other)) + + IHash + (-hash [coll] (hash-coll coll)) + + ISeqable + (-seq [coll] + (when (pos? count) + (let [hashes (.sort (js-keys hashobj))] + (mapcat #(map vec (partition 2 (aget hashobj %))) + hashes)))) + + ICounted + (-count [coll] count) + + ILookup + (-lookup [coll k] (-lookup coll k nil)) + (-lookup [coll k not-found] + (let [bucket (aget hashobj (hash k)) + i (when bucket (scan-array 2 k bucket))] + (if i + (aget bucket (inc i)) + not-found))) + + IAssociative + (-assoc [coll k v] + (let [h (hash k) + bucket (aget hashobj h)] + (if bucket + (let [new-bucket (aclone bucket) + new-hashobj (goog.object/clone hashobj)] + (aset new-hashobj h new-bucket) + (if-let [i (scan-array 2 k new-bucket)] + (do ; found key, replace + (aset new-bucket (inc i) v) + (HashMap. meta count new-hashobj)) + (do ; did not find key, append + (.push new-bucket k v) + (HashMap. meta (inc count) new-hashobj)))) + (let [new-hashobj (goog.object/clone hashobj)] ; did not find bucket + (aset new-hashobj h (array k v)) + (HashMap. meta (inc count) new-hashobj))))) + (-contains-key? [coll k] + (let [bucket (aget hashobj (hash k)) + i (when bucket (scan-array 2 k bucket))] + (if i + true + false))) + + IMap + (-dissoc [coll k] + (let [h (hash k) + bucket (aget hashobj h) + i (when bucket (scan-array 2 k bucket))] + (if (not i) + coll ; key not found, return coll unchanged + (let [new-hashobj (goog.object/clone hashobj)] + (if (> 3 (.-length bucket)) + (js-delete new-hashobj h) + (let [new-bucket (aclone bucket)] + (.splice new-bucket i 2) + (aset new-hashobj h new-bucket))) + (HashMap. meta (dec count) new-hashobj))))) + + IFn + (-invoke [coll k] + (-lookup coll k)) + (-invoke [coll k not-found] + (-lookup coll k not-found)) + + IPrintWithWriter + (-pr-writer [coll writer opts] + (print-map coll pr-writer writer opts))) + +(set! (. HashMap -EMPTY) (HashMap. nil 0 (js-obj))) + +(set! (. HashMap -fromArrays) (fn [ks vs] + (let [len (.-length ks)] + (loop [i 0, out (. HashMap -EMPTY)] + (if (< i len) + (recur (inc i) (assoc out (aget ks i) (aget vs i))) + out))))) + +(deftype Set [meta hash-map] + IWithMeta + (-with-meta [coll meta] (Set. meta hash-map)) + + IMeta + (-meta [coll] meta) + + ICollection + (-conj [coll o] + (Set. meta (assoc hash-map o nil))) + + IEmptyableCollection + (-empty [coll] (with-meta (. Set -EMPTY) meta)) + + IEquiv + (-equiv [coll other] + (and + (set? other) + (= (count coll) (count other)) + (every? #(contains? coll %) + other))) + + IHash + (-hash [coll] (hash-coll coll)) + + ISeqable + (-seq [coll] (keys hash-map)) + + ICounted + (-count [coll] (count (seq coll))) + + ILookup + (-lookup [coll v] + (-lookup coll v nil)) + (-lookup [coll v not-found] + (if (-contains-key? hash-map v) + v + not-found)) + + ISet + (-disjoin [coll v] + (Set. meta (dissoc hash-map v))) + + IFn + (-invoke [coll k] + (-lookup coll k)) + (-invoke [coll k not-found] + (-lookup coll k not-found)) + + IPrintWithWriter + (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "#{" " " "}" opts coll))) + +(set! (. Set -EMPTY) (Set. nil (hash-map))) From 3105284afa07081db390baee4ca4e9bee42998d3 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Tue, 29 Jul 2025 19:51:58 -0400 Subject: [PATCH 002/107] - remove old ObjMap - update older ObjMap - simple-hash-map to avoid name collision --- src/main/cljs/cljs/core.cljs | 280 ++++++++++------------------------- 1 file changed, 78 insertions(+), 202 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index d04fd38db..479a6a120 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -6561,163 +6561,6 @@ reduces them without incurring seq initialization" i (recur (+ i incr))))))) -; The keys field is an array of all keys of this map, in no particular -; order. Any string, keyword, or symbol key is used as a property name -; to store the value in strobj. If a key is assoc'ed when that same -; key already exists in strobj, the old value is overwritten. If a -; non-string key is assoc'ed, return a HashMap object instead. - -(defn- obj-map-compare-keys [a b] - (let [a (hash a) - b (hash b)] - (cond - (< a b) -1 - (> a b) 1 - :else 0))) - -(defn- obj-map->hash-map [m k v] - (let [ks (.-keys m) - len (alength ks) - so (.-strobj m) - mm (meta m)] - (loop [i 0 - out (transient (.-EMPTY PersistentHashMap))] - (if (< i len) - (let [k (aget ks i)] - (recur (inc i) (assoc! out k (gobject/get so k)))) - (-with-meta (persistent! (assoc! out k v)) mm))))) - -;;; ObjMap - DEPRECATED - -(defn- obj-clone [obj ks] - (let [new-obj (js-obj) - l (alength ks)] - (loop [i 0] - (when (< i l) - (let [k (aget ks i)] - (gobject/set new-obj k (gobject/get obj k)) - (recur (inc i))))) - new-obj)) - -(deftype ObjMap [meta keys strobj update-count ^:mutable __hash] - Object - (toString [coll] - (pr-str* coll)) - (equiv [this other] - (-equiv this other)) - - IWithMeta - (-with-meta [coll new-meta] - (if (identical? new-meta meta) - coll - (ObjMap. new-meta keys strobj update-count __hash))) - - IMeta - (-meta [coll] meta) - - ICollection - (-conj [coll entry] - (if (vector? entry) - (-assoc coll (-nth entry 0) (-nth entry 1)) - (reduce -conj - coll - entry))) - - IEmptyableCollection - (-empty [coll] (-with-meta (.-EMPTY ObjMap) meta)) - - IEquiv - (-equiv [coll other] (equiv-map coll other)) - - IHash - (-hash [coll] (caching-hash coll hash-unordered-coll __hash)) - - ISeqable - (-seq [coll] - (when (pos? (alength keys)) - (map #(vector % (unchecked-get strobj %)) - (.sort keys obj-map-compare-keys)))) - - ICounted - (-count [coll] (alength keys)) - - ILookup - (-lookup [coll k] (-lookup coll k nil)) - (-lookup [coll k not-found] - (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) - (unchecked-get strobj k) - not-found)) - - IAssociative - (-assoc [coll k v] - (if (string? k) - (if (or (> update-count (.-HASHMAP_THRESHOLD ObjMap)) - (>= (alength keys) (.-HASHMAP_THRESHOLD ObjMap))) - (obj-map->hash-map coll k v) - (if-not (nil? (scan-array 1 k keys)) - (let [new-strobj (obj-clone strobj keys)] - (gobject/set new-strobj k v) - (ObjMap. meta keys new-strobj (inc update-count) nil)) ; overwrite - (let [new-strobj (obj-clone strobj keys) ; append - new-keys (aclone keys)] - (gobject/set new-strobj k v) - (.push new-keys k) - (ObjMap. meta new-keys new-strobj (inc update-count) nil)))) - ;; non-string key. game over. - (obj-map->hash-map coll k v))) - (-contains-key? [coll k] - (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) - true - false)) - - IFind - (-find [coll k] - (when (and (string? k) - (not (nil? (scan-array 1 k keys)))) - (MapEntry. k (unchecked-get strobj k) nil))) - - IKVReduce - (-kv-reduce [coll f init] - (let [len (alength keys)] - (loop [keys (.sort keys obj-map-compare-keys) - init init] - (if (seq keys) - (let [k (first keys) - init (f init k (unchecked-get strobj k))] - (if (reduced? init) - @init - (recur (rest keys) init))) - init)))) - - IMap - (-dissoc [coll k] - (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) - (let [new-keys (aclone keys) - new-strobj (obj-clone strobj keys)] - (.splice new-keys (scan-array 1 k new-keys) 1) - (js-delete new-strobj k) - (ObjMap. meta new-keys new-strobj (inc update-count) nil)) - coll)) ; key not found, return coll unchanged - - IFn - (-invoke [coll k] - (-lookup coll k)) - (-invoke [coll k not-found] - (-lookup coll k not-found)) - - IEditableCollection - (-as-transient [coll] - (transient (into (hash-map) coll)))) - -(set! (.-EMPTY ObjMap) (ObjMap. nil (array) (js-obj) 0 empty-unordered-hash)) - -(set! (.-HASHMAP_THRESHOLD ObjMap) 8) - -(set! (.-fromObject ObjMap) (fn [ks obj] (ObjMap. nil ks obj 0 nil))) - ;; Record Iterator (deftype RecordIter [^:mutable i record base-count fields ext-map-iter] Object @@ -9191,19 +9034,6 @@ reduces them without incurring seq initialization" (.createAsIfByAssoc PersistentArrayMap (to-array s)) (if (seq s) (first s) (.-EMPTY PersistentArrayMap)))) -(defn obj-map - "keyval => key val - Returns a new object map with supplied mappings." - [& keyvals] - (let [ks (array) - obj (js-obj)] - (loop [kvs (seq keyvals)] - (if kvs - (do (.push ks (first kvs)) - (gobject/set obj (first kvs) (second kvs)) - (recur (nnext kvs))) - (.fromObject ObjMap ks obj))))) - (defn sorted-map "keyval => key val Returns a new sorted map with supplied mappings." @@ -10855,10 +10685,6 @@ reduces them without incurring seq initialization" MapEntry (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "[" " " "]" opts coll)) - ObjMap - (-pr-writer [coll writer opts] - (print-map coll pr-writer writer opts)) - KeySeq (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "(" " " ")" opts coll)) @@ -12502,14 +12328,6 @@ reduces them without incurring seq initialization" ; key already exists in strobj, the old value is overwritten. If a ; non-string key is assoc'ed, return a HashMap object instead. -(defn- obj-map-contains-key? - ([k strobj] - (obj-map-contains-key? k strobj true false)) - ([k strobj true-val false-val] - (if (and (goog/isString k) (.hasOwnProperty strobj k)) - true-val - false-val))) - (defn- obj-map-compare-keys [a b] (let [a (hash a) b (hash b)] @@ -12518,7 +12336,25 @@ reduces them without incurring seq initialization" (> a b) 1 :else 0))) -(deftype ObjMap [meta keys strobj] +(defn- obj-clone [obj ks] + (let [new-obj (js-obj) + l (alength ks)] + (loop [i 0] + (when (< i l) + (let [k (aget ks i)] + (gobject/set new-obj k (gobject/get obj k)) + (recur (inc i))))) + new-obj)) + +(declare simple-hash-map) + +(deftype ObjMap [meta keys strobj ^:mutable __hash] + Object + (toString [coll] + (pr-str* coll)) + (equiv [this other] + (-equiv this other)) + IWithMeta (-with-meta [coll meta] (ObjMap. meta keys strobj)) @@ -12540,46 +12376,73 @@ reduces them without incurring seq initialization" (-equiv [coll other] (equiv-map coll other)) IHash - (-hash [coll] (hash-coll coll)) + (-hash [coll] (caching-hash coll hash-unordered-coll __hash)) ISeqable (-seq [coll] - (when (pos? (.-length keys)) - (map #(vector % (aget strobj %)) + (when (pos? (alength keys)) + (map #(vector % (unchecked-get strobj %)) (.sort keys obj-map-compare-keys)))) ICounted - (-count [coll] (.-length keys)) + (-count [coll] (alength keys)) ILookup (-lookup [coll k] (-lookup coll k nil)) (-lookup [coll k not-found] - (obj-map-contains-key? k strobj (aget strobj k) not-found)) + (if (and (string? k) + (not (nil? (scan-array 1 k keys)))) + (unchecked-get strobj k) + not-found)) IAssociative (-assoc [coll k v] - (if (goog/isString k) - (let [new-strobj (goog.object/clone strobj) - overwrite? (.hasOwnProperty new-strobj k)] - (aset new-strobj k v) - (if overwrite? - (ObjMap. meta keys new-strobj) ; overwrite - (let [new-keys (aclone keys)] ; append - (.push new-keys k) - (ObjMap. meta new-keys new-strobj)))) + (if (string? k) + (if-not (nil? (scan-array 1 k keys)) + (let [new-strobj (obj-clone strobj keys)] + (gobject/set new-strobj k v) + (ObjMap. meta keys new-strobj nil)) ; overwrite + (let [new-strobj (obj-clone strobj keys) ; append + new-keys (aclone keys)] + (gobject/set new-strobj k v) + (.push new-keys k) + (ObjMap. meta new-keys new-strobj nil))) ; non-string key. game over. - (with-meta (into (hash-map k v) (seq coll)) meta))) + (with-meta (into (simple-hash-map k v) (seq coll)) meta))) (-contains-key? [coll k] - (obj-map-contains-key? k strobj)) + (if (and (string? k) + (not (nil? (scan-array 1 k keys)))) + true + false)) + + IFind + (-find [coll k] + (when (and (string? k) + (not (nil? (scan-array 1 k keys)))) + (MapEntry. k (unchecked-get strobj k) nil))) + + IKVReduce + (-kv-reduce [coll f init] + (let [len (alength keys)] + (loop [keys (.sort keys obj-map-compare-keys) + init init] + (if (seq keys) + (let [k (first keys) + init (f init k (unchecked-get strobj k))] + (if (reduced? init) + @init + (recur (rest keys) init))) + init)))) IMap (-dissoc [coll k] - (if (and (goog/isString k) (.hasOwnProperty strobj k)) + (if (and (string? k) + (not (nil? (scan-array 1 k keys)))) (let [new-keys (aclone keys) - new-strobj (goog.object/clone strobj)] + new-strobj (obj-clone strobj keys)] (.splice new-keys (scan-array 1 k new-keys) 1) (js-delete new-strobj k) - (ObjMap. meta new-keys new-strobj)) + (ObjMap. meta new-keys new-strobj nil)) coll)) ; key not found, return coll unchanged IFn @@ -12588,6 +12451,10 @@ reduces them without incurring seq initialization" (-invoke [coll k not-found] (-lookup coll k not-found)) + ;IEditableCollection + ;(-as-transient [coll] + ; (transient (into (simple-hash-map) coll))) + IPrintWithWriter (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) @@ -12716,6 +12583,15 @@ reduces them without incurring seq initialization" (recur (inc i) (assoc out (aget ks i) (aget vs i))) out))))) +(defn simple-hash-map + "keyval => key val + Returns a new hash map with supplied mappings." + [& keyvals] + (loop [in (seq keyvals), out (. HashMap -EMPTY)] + (if in + (recur (nnext in) (assoc out (first in) (second in))) + out))) + (deftype Set [meta hash-map] IWithMeta (-with-meta [coll meta] (Set. meta hash-map)) From dba928b9334b5df85bf1731d89e704f7f61057ed Mon Sep 17 00:00:00 2001 From: davidnolen Date: Tue, 29 Jul 2025 20:00:41 -0400 Subject: [PATCH 003/107] fix all the ObjMap ctor sites --- src/main/cljs/cljs/core.cljs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 479a6a120..7421b69a2 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12356,7 +12356,7 @@ reduces them without incurring seq initialization" (-equiv this other)) IWithMeta - (-with-meta [coll meta] (ObjMap. meta keys strobj)) + (-with-meta [coll meta] (ObjMap. meta keys strobj __hash)) IMeta (-meta [coll] meta) @@ -12459,9 +12459,9 @@ reduces them without incurring seq initialization" (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) -(set! (. ObjMap -EMPTY) (ObjMap. nil (array) (js-obj))) +(set! (. ObjMap -EMPTY) (ObjMap. nil (array) (js-obj) empty-ordered-hash)) -(set! (. ObjMap -fromObject) (fn [ks obj] (ObjMap. nil ks obj))) +(set! (. ObjMap -fromObject) (fn [ks obj] (ObjMap. nil ks obj nil))) (defn obj-map "keyval => key val From db629371ca6d63295b477a22c58c3eeca91fbeb5 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Tue, 29 Jul 2025 20:27:26 -0400 Subject: [PATCH 004/107] check for :lite-mode? - emit Vector if set --- src/main/cljs/cljs/core.cljs | 14 +++++++------- src/main/clojure/cljs/closure.clj | 2 +- src/main/clojure/cljs/compiler.cljc | 12 +++++++++++- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 7421b69a2..ca32963ba 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12232,9 +12232,9 @@ reduces them without incurring seq initialization" ;;; Vector -(deftype Vector [meta array] +(deftype Vector [meta array ^:mutable __hash] IWithMeta - (-with-meta [coll meta] (Vector. meta array)) + (-with-meta [coll meta] (Vector. meta array __hash)) IMeta (-meta [coll] meta) @@ -12248,14 +12248,14 @@ reduces them without incurring seq initialization" (if (> (.-length array) 0) (let [new-array (aclone array)] (. new-array (pop)) - (Vector. meta new-array)) + (Vector. meta new-array nil)) (throw (js/Error. "Can't pop empty vector")))) ICollection (-conj [coll o] (let [new-array (aclone array)] (.push new-array o) - (Vector. meta new-array))) + (Vector. meta new-array nil))) IEmptyableCollection (-empty [coll] (with-meta (. Vector -EMPTY) meta)) @@ -12298,7 +12298,7 @@ reduces them without incurring seq initialization" (-assoc [coll k v] (let [new-array (aclone array)] (aset new-array k v) - (Vector. meta new-array))) + (Vector. meta new-array nil))) IVector (-assoc-n [coll n val] (-assoc coll n val)) @@ -12318,9 +12318,9 @@ reduces them without incurring seq initialization" IPrintWithWriter (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "[" " " "]" opts coll))) -(set! (. Vector -EMPTY) (Vector. nil (array))) +(set! (. Vector -EMPTY) (Vector. nil (array) nil)) -(set! (. Vector -fromArray) (fn [xs] (Vector. nil xs))) +(set! (. Vector -fromArray) (fn [xs] (Vector. nil xs nil))) ; The keys field is an array of all keys of this map, in no particular ; order. Any string, keyword, or symbol key is used as a property name diff --git a/src/main/clojure/cljs/closure.clj b/src/main/clojure/cljs/closure.clj index b215573f6..147365455 100644 --- a/src/main/clojure/cljs/closure.clj +++ b/src/main/clojure/cljs/closure.clj @@ -211,7 +211,7 @@ :watch :watch-error-fn :watch-fn :install-deps :process-shim :rename-prefix :rename-prefix-namespace :closure-variable-map-in :closure-property-map-in :closure-variable-map-out :closure-property-map-out :stable-names :ignore-js-module-exts :opts-cache :aot-cache :elide-strict :fingerprint :spec-skip-macros - :nodejs-rt :target-fn :deps-cmd :bundle-cmd :global-goog-object&array :node-modules-dirs}) + :nodejs-rt :target-fn :deps-cmd :bundle-cmd :global-goog-object&array :node-modules-dirs :lite-mode?}) (def string->charset {"iso-8859-1" StandardCharsets/ISO_8859_1 diff --git a/src/main/clojure/cljs/compiler.cljc b/src/main/clojure/cljs/compiler.cljc index fcc03ab96..3aedfee88 100644 --- a/src/main/clojure/cljs/compiler.cljc +++ b/src/main/clojure/cljs/compiler.cljc @@ -522,6 +522,9 @@ (and (every? #(= (:op %) :const) keys) (= (count (into #{} keys)) (count keys))))) +(defn lite-mode? [] + (get-in @env/*compiler* [:options :lite-mode?])) + (defn emit-map [keys vals comma-sep distinct-keys?] (cond (zero? (count keys)) @@ -562,10 +565,17 @@ ", 5, cljs.core.PersistentVector.EMPTY_NODE, [" (comma-sep items) "], null)") (emits "cljs.core.PersistentVector.fromArray([" (comma-sep items) "], true)"))))) +(defn emit-lite-vector [items comma-sep] + (if (empty? items) + (emits "cljs.core.Vector.EMPTY") + (emits "new cljs.core.Vector(null, [" (comma-sep items) "], null)"))) + (defmethod emit* :vector [{:keys [items env]}] (emit-wrap env - (emit-vector items comma-sep))) + (if (lite-mode?) + (emit-lite-vector items comma-sep) + (emit-vector items comma-sep)))) (defn distinct-constants? [items] (let [items (map ana/unwrap-quote items)] From 85a36202a59fa9dc21fa0d634a919f715ea5cae4 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Tue, 29 Jul 2025 20:32:49 -0400 Subject: [PATCH 005/107] :lite-mode? -> :lite-mode --- src/main/clojure/cljs/closure.clj | 2 +- src/main/clojure/cljs/compiler.cljc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/clojure/cljs/closure.clj b/src/main/clojure/cljs/closure.clj index 147365455..c0ed3499a 100644 --- a/src/main/clojure/cljs/closure.clj +++ b/src/main/clojure/cljs/closure.clj @@ -211,7 +211,7 @@ :watch :watch-error-fn :watch-fn :install-deps :process-shim :rename-prefix :rename-prefix-namespace :closure-variable-map-in :closure-property-map-in :closure-variable-map-out :closure-property-map-out :stable-names :ignore-js-module-exts :opts-cache :aot-cache :elide-strict :fingerprint :spec-skip-macros - :nodejs-rt :target-fn :deps-cmd :bundle-cmd :global-goog-object&array :node-modules-dirs :lite-mode?}) + :nodejs-rt :target-fn :deps-cmd :bundle-cmd :global-goog-object&array :node-modules-dirs :lite-mode}) (def string->charset {"iso-8859-1" StandardCharsets/ISO_8859_1 diff --git a/src/main/clojure/cljs/compiler.cljc b/src/main/clojure/cljs/compiler.cljc index 3aedfee88..8f7f6414d 100644 --- a/src/main/clojure/cljs/compiler.cljc +++ b/src/main/clojure/cljs/compiler.cljc @@ -523,7 +523,7 @@ (= (count (into #{} keys)) (count keys))))) (defn lite-mode? [] - (get-in @env/*compiler* [:options :lite-mode?])) + (get-in @env/*compiler* [:options :lite-mode])) (defn emit-map [keys vals comma-sep distinct-keys?] (cond From 930fbef3e0d8619929f38438d9567d527a1cfb5d Mon Sep 17 00:00:00 2001 From: davidnolen Date: Tue, 29 Jul 2025 23:01:29 -0400 Subject: [PATCH 006/107] update HashMap and Set --- src/main/cljs/cljs/core.cljs | 40 +++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index ca32963ba..b2a5fecdd 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12481,9 +12481,15 @@ reduces them without incurring seq initialization" ; hashobj. Each values in hashobj is actually a bucket in order to handle hash ; collisions. A bucket is an array of alternating keys (not their hashes) and ; vals. -(deftype HashMap [meta count hashobj] +(deftype HashMap [meta count hashobj ^:mutable __hash] + Object + (toString [coll] + (pr-str* coll)) + (equiv [this other] + (-equiv this other)) + IWithMeta - (-with-meta [coll meta] (HashMap. meta count hashobj)) + (-with-meta [coll meta] (HashMap. meta count hashobj __hash)) IMeta (-meta [coll] meta) @@ -12503,7 +12509,7 @@ reduces them without incurring seq initialization" (-equiv [coll other] (equiv-map coll other)) IHash - (-hash [coll] (hash-coll coll)) + (-hash [coll] (caching-hash coll hash-unordered-coll __hash)) ISeqable (-seq [coll] @@ -12535,13 +12541,13 @@ reduces them without incurring seq initialization" (if-let [i (scan-array 2 k new-bucket)] (do ; found key, replace (aset new-bucket (inc i) v) - (HashMap. meta count new-hashobj)) + (HashMap. meta count new-hashobj nil)) (do ; did not find key, append (.push new-bucket k v) - (HashMap. meta (inc count) new-hashobj)))) + (HashMap. meta (inc count) new-hashobj nil)))) (let [new-hashobj (goog.object/clone hashobj)] ; did not find bucket (aset new-hashobj h (array k v)) - (HashMap. meta (inc count) new-hashobj))))) + (HashMap. meta (inc count) new-hashobj nil))))) (-contains-key? [coll k] (let [bucket (aget hashobj (hash k)) i (when bucket (scan-array 2 k bucket))] @@ -12562,7 +12568,7 @@ reduces them without incurring seq initialization" (let [new-bucket (aclone bucket)] (.splice new-bucket i 2) (aset new-hashobj h new-bucket))) - (HashMap. meta (dec count) new-hashobj))))) + (HashMap. meta (dec count) new-hashobj nil))))) IFn (-invoke [coll k] @@ -12574,7 +12580,7 @@ reduces them without incurring seq initialization" (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) -(set! (. HashMap -EMPTY) (HashMap. nil 0 (js-obj))) +(set! (. HashMap -EMPTY) (HashMap. nil 0 (js-obj) empty-unordered-hash)) (set! (. HashMap -fromArrays) (fn [ks vs] (let [len (.-length ks)] @@ -12592,16 +12598,22 @@ reduces them without incurring seq initialization" (recur (nnext in) (assoc out (first in) (second in))) out))) -(deftype Set [meta hash-map] +(deftype Set [meta hash-map ^:mutable __hash] + Object + (toString [coll] + (pr-str* coll)) + (equiv [this other] + (-equiv this other)) + IWithMeta - (-with-meta [coll meta] (Set. meta hash-map)) + (-with-meta [coll meta] (Set. meta hash-map __hash)) IMeta (-meta [coll] meta) ICollection (-conj [coll o] - (Set. meta (assoc hash-map o nil))) + (Set. meta (assoc hash-map o nil) nil)) IEmptyableCollection (-empty [coll] (with-meta (. Set -EMPTY) meta)) @@ -12615,7 +12627,7 @@ reduces them without incurring seq initialization" other))) IHash - (-hash [coll] (hash-coll coll)) + (-hash [coll] (caching-hash coll hash-unordered-coll __hash)) ISeqable (-seq [coll] (keys hash-map)) @@ -12633,7 +12645,7 @@ reduces them without incurring seq initialization" ISet (-disjoin [coll v] - (Set. meta (dissoc hash-map v))) + (Set. meta (dissoc hash-map v) nil)) IFn (-invoke [coll k] @@ -12644,4 +12656,4 @@ reduces them without incurring seq initialization" IPrintWithWriter (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "#{" " " "}" opts coll))) -(set! (. Set -EMPTY) (Set. nil (hash-map))) +(set! (. Set -EMPTY) (Set. nil (hash-map) empty-unordered-hash)) From 71b1e996da3bb0290a5e26c8f46a5d3c9fa40b42 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 08:26:08 -0400 Subject: [PATCH 007/107] no .toString for :lite-mode, pay for what you use --- src/main/cljs/cljs/core.cljs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index b2a5fecdd..ac125c14f 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12349,12 +12349,6 @@ reduces them without incurring seq initialization" (declare simple-hash-map) (deftype ObjMap [meta keys strobj ^:mutable __hash] - Object - (toString [coll] - (pr-str* coll)) - (equiv [this other] - (-equiv this other)) - IWithMeta (-with-meta [coll meta] (ObjMap. meta keys strobj __hash)) @@ -12482,12 +12476,6 @@ reduces them without incurring seq initialization" ; collisions. A bucket is an array of alternating keys (not their hashes) and ; vals. (deftype HashMap [meta count hashobj ^:mutable __hash] - Object - (toString [coll] - (pr-str* coll)) - (equiv [this other] - (-equiv this other)) - IWithMeta (-with-meta [coll meta] (HashMap. meta count hashobj __hash)) @@ -12599,12 +12587,6 @@ reduces them without incurring seq initialization" out))) (deftype Set [meta hash-map ^:mutable __hash] - Object - (toString [coll] - (pr-str* coll)) - (equiv [this other] - (-equiv this other)) - IWithMeta (-with-meta [coll meta] (Set. meta hash-map __hash)) @@ -12656,4 +12638,4 @@ reduces them without incurring seq initialization" IPrintWithWriter (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "#{" " " "}" opts coll))) -(set! (. Set -EMPTY) (Set. nil (hash-map) empty-unordered-hash)) +(set! (. Set -EMPTY) (Set. nil (simple-hash-map) empty-unordered-hash)) From 90945e63b4ec0747baae0594cdf37142eff0ebc2 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 08:42:04 -0400 Subject: [PATCH 008/107] - something weird about simple-hash-map, leave a note - switch to HashMap/EMPTY --- src/main/cljs/cljs/core.cljs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index ac125c14f..4e01aa341 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12577,6 +12577,8 @@ reduces them without incurring seq initialization" (recur (inc i) (assoc out (aget ks i) (aget vs i))) out))))) +;; FIXME: calling this (simple-hash-map) expands the codesize significantly, +;; not clear why at the moment, seems to do less than (hash-map) (defn simple-hash-map "keyval => key val Returns a new hash map with supplied mappings." @@ -12638,4 +12640,4 @@ reduces them without incurring seq initialization" IPrintWithWriter (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "#{" " " "}" opts coll))) -(set! (. Set -EMPTY) (Set. nil (simple-hash-map) empty-unordered-hash)) +(set! (. Set -EMPTY) (Set. nil (. HashMap -EMPTY) empty-unordered-hash)) From d3beffe57f0da3c728e5b9dd9b501944a4a80303 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 08:44:34 -0400 Subject: [PATCH 009/107] :lite-mode path for maps --- src/main/clojure/cljs/compiler.cljc | 30 +++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/clojure/cljs/compiler.cljc b/src/main/clojure/cljs/compiler.cljc index 8f7f6414d..dcbf11e9e 100644 --- a/src/main/clojure/cljs/compiler.cljc +++ b/src/main/clojure/cljs/compiler.cljc @@ -525,6 +525,27 @@ (defn lite-mode? [] (get-in @env/*compiler* [:options :lite-mode])) +(defn obj-map-key [x] + (if (keyword? x) + (str \" "\\uFDD0" \' + (if (namespace x) + (str (namespace x) "/") "") + (name x) + \") + x)) + +(defn emit-obj-map [str-keys vals comma-sep distinct-keys?] + (if (zero? (count str-keys)) + (emits "cljs.core.ObjMap.EMPTY") + (emits "cljs.core.ObjMap.fromObject([" (comma-sep str-keys) "], {" + (comma-sep (map (fn [k v] (str k ":" (emit-str v))) str-keys vals)) + "})"))) + +(defn emit-lite-map [keys vals comma-sep distinct-keys?] + (if (zero? (count keys)) + (emits "cljs.core.HashMap.EMPTY") + (emits "cljs.core.HashMap.fromArrays([" (comma-sep keys) "], [" (comma-sep vals) "])"))) + (defn emit-map [keys vals comma-sep distinct-keys?] (cond (zero? (count keys)) @@ -547,9 +568,14 @@ "])"))) (defmethod emit* :map - [{:keys [env keys vals]}] + [{:keys [env form keys vals]}] (emit-wrap env - (emit-map keys vals comma-sep distinct-keys?))) + (if (lite-mode?) + (let [form-keys (clojure.core/keys form)] + (if (every? #(or (string? %) (keyword? %)) form-keys) + (emit-obj-map (map obj-map-key form-keys) vals comma-sep distinct-keys?) + (emit-lite-map keys vals comma-sep distinct-keys?))) + (emit-map keys vals comma-sep distinct-keys?)))) (defn emit-list [items comma-sep] (if (empty? items) From 4e3f244e877f4b25abf2ac34c5e107491e241d10 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 16:48:50 -0400 Subject: [PATCH 010/107] always elide toString Object methods in :lite-mode --- src/main/clojure/cljs/core.cljc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/clojure/cljs/core.cljc b/src/main/clojure/cljs/core.cljc index 8393a1a67..de6242553 100644 --- a/src/main/clojure/cljs/core.cljc +++ b/src/main/clojure/cljs/core.cljc @@ -1507,13 +1507,18 @@ ~@body)))) (core/defn- add-obj-methods [type type-sym sigs] - (map (core/fn [[f & meths :as form]] - (core/let [[f meths] (if (vector? (first meths)) - [f [(rest form)]] - [f meths])] - `(set! ~(extend-prefix type-sym f) - ~(with-meta `(fn ~@(map #(adapt-obj-params type %) meths)) (meta form))))) - sigs)) + (->> sigs + ;; Elide all toString methods in :lite-mode + (remove + (core/fn [[f]] + (and (comp/lite-mode?) (= 'toString f)))) + (map + (core/fn [[f & meths :as form]] + (core/let [[f meths] (if (vector? (first meths)) + [f [(rest form)]] + [f meths])] + `(set! ~(extend-prefix type-sym f) + ~(with-meta `(fn ~@(map #(adapt-obj-params type %) meths)) (meta form)))))))) (core/defn- ifn-invoke-methods [type type-sym [f & meths :as form]] (map From ac117358996665a84ed2e533cb705ae8564b974a Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 16:51:40 -0400 Subject: [PATCH 011/107] assoc directly reference array-map, replace w/ literal --- src/main/cljs/cljs/core.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 4e01aa341..1ca45372e 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -2070,7 +2070,7 @@ reduces them without incurring seq initialization" (-assoc coll k v) (if-not (nil? coll) (-assoc coll k v) - (array-map k v)))) + {k v}))) ([coll k v & kvs] (let [ret (assoc coll k v)] (if kvs From 42bb870445cc0fcb9ec8cddd2a1c5573bd453fc8 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 16:52:28 -0400 Subject: [PATCH 012/107] add simple-vector for now, might need to compiler support soon, but can use this util then --- src/main/cljs/cljs/core.cljs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 1ca45372e..7dc9004d6 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12322,6 +12322,12 @@ reduces them without incurring seq initialization" (set! (. Vector -fromArray) (fn [xs] (Vector. nil xs nil))) +(defn simple-vector + [& args] + (if (and (instance? IndexedSeq args) (zero? (.-i args))) + (.fromArray Vector (.-arr args) (not (array? (.-arr args)))) + (vec args))) + ; The keys field is an array of all keys of this map, in no particular ; order. Any string, keyword, or symbol key is used as a property name ; to store the value in strobj. If a key is assoc'ed when that same From ac61da8fc0240ff9d6aebe0aaecccbba00f9fa92 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 16:53:17 -0400 Subject: [PATCH 013/107] - formatting - avoid map in ObjMap for now until we get our ducks in a row --- src/main/cljs/cljs/core.cljs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 7dc9004d6..f3cede02f 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12365,9 +12365,7 @@ reduces them without incurring seq initialization" (-conj [coll entry] (if (vector? entry) (-assoc coll (-nth entry 0) (-nth entry 1)) - (reduce -conj - coll - entry))) + (reduce -conj coll entry))) IEmptyableCollection (-empty [coll] (with-meta (. ObjMap -EMPTY) meta)) @@ -12381,8 +12379,9 @@ reduces them without incurring seq initialization" ISeqable (-seq [coll] (when (pos? (alength keys)) - (map #(vector % (unchecked-get strobj %)) - (.sort keys obj-map-compare-keys)))) + (prim-seq + (.map (.sort keys obj-map-compare-keys) + #(unchecked-get strobj %)) 0))) ICounted (-count [coll] (alength keys)) From e0fb270d64024e88cf260b9fe530aa5b6220e72e Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 16:53:37 -0400 Subject: [PATCH 014/107] - formatting --- src/main/cljs/cljs/core.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index f3cede02f..61474705c 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12417,7 +12417,7 @@ reduces them without incurring seq initialization" IFind (-find [coll k] (when (and (string? k) - (not (nil? (scan-array 1 k keys)))) + (not (nil? (scan-array 1 k keys)))) (MapEntry. k (unchecked-get strobj k) nil))) IKVReduce From ae604a4e9843bbe8b00f6b18a4b9c653ccc48f32 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 16:53:58 -0400 Subject: [PATCH 015/107] - formatting --- src/main/cljs/cljs/core.cljs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 61474705c..d8c219302 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12491,9 +12491,7 @@ reduces them without incurring seq initialization" (-conj [coll entry] (if (vector? entry) (-assoc coll (-nth entry 0) (-nth entry 1)) - (reduce -conj - coll - entry))) + (reduce -conj coll entry))) IEmptyableCollection (-empty [coll] (with-meta (. HashMap -EMPTY) meta)) From f32909773e33942c98720a4e694211e483ca8bea Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 16:54:46 -0400 Subject: [PATCH 016/107] - modernize HashMap --- src/main/cljs/cljs/core.cljs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index d8c219302..ea5718b0d 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12527,7 +12527,7 @@ reduces them without incurring seq initialization" bucket (aget hashobj h)] (if bucket (let [new-bucket (aclone bucket) - new-hashobj (goog.object/clone hashobj)] + new-hashobj (gobject/clone hashobj)] (aset new-hashobj h new-bucket) (if-let [i (scan-array 2 k new-bucket)] (do ; found key, replace @@ -12536,11 +12536,11 @@ reduces them without incurring seq initialization" (do ; did not find key, append (.push new-bucket k v) (HashMap. meta (inc count) new-hashobj nil)))) - (let [new-hashobj (goog.object/clone hashobj)] ; did not find bucket - (aset new-hashobj h (array k v)) + (let [new-hashobj (gobject/clone hashobj)] ; did not find bucket + (unchecked-set new-hashobj h (array k v)) (HashMap. meta (inc count) new-hashobj nil))))) (-contains-key? [coll k] - (let [bucket (aget hashobj (hash k)) + (let [bucket (unchecked-get hashobj (hash k)) i (when bucket (scan-array 2 k bucket))] (if i true @@ -12549,16 +12549,16 @@ reduces them without incurring seq initialization" IMap (-dissoc [coll k] (let [h (hash k) - bucket (aget hashobj h) + bucket (unchecked-get hashobj h) i (when bucket (scan-array 2 k bucket))] (if (not i) coll ; key not found, return coll unchanged - (let [new-hashobj (goog.object/clone hashobj)] - (if (> 3 (.-length bucket)) + (let [new-hashobj (gobject/clone hashobj)] + (if (> 3 (alength bucket)) (js-delete new-hashobj h) (let [new-bucket (aclone bucket)] (.splice new-bucket i 2) - (aset new-hashobj h new-bucket))) + (unchecked-set new-hashobj h new-bucket))) (HashMap. meta (dec count) new-hashobj nil))))) IFn From de3b500c6d8dc3170338035dcdf129170fcd422e Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 17:15:59 -0400 Subject: [PATCH 017/107] - fix bootstrapped --- src/main/clojure/cljs/core.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/clojure/cljs/core.cljc b/src/main/clojure/cljs/core.cljc index de6242553..46445dd31 100644 --- a/src/main/clojure/cljs/core.cljc +++ b/src/main/clojure/cljs/core.cljc @@ -1511,7 +1511,7 @@ ;; Elide all toString methods in :lite-mode (remove (core/fn [[f]] - (and (comp/lite-mode?) (= 'toString f)))) + (core/and (comp/lite-mode?) (core/= 'toString f)))) (map (core/fn [[f & meths :as form]] (core/let [[f meths] (if (vector? (first meths)) From 294073830722f5387ea49e83c5599a78401181e2 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 17:26:00 -0400 Subject: [PATCH 018/107] LITE_MODE goog-define so we can elide chunked logic from std lib --- src/main/cljs/cljs/core.cljs | 12 ++++++++++-- src/main/clojure/cljs/closure.clj | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index ea5718b0d..7d4cb1f67 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -53,6 +53,11 @@ , and \"global\" supported. "} *global* "default") +(goog-define + ^{:doc "Boolean flag for LITE_MODE" + :jsdoc ["@type {boolean}"]} + LITE_MODE false) + (def ^{:dynamic true :doc "Var bound to the current namespace. Only used for bootstrapping." @@ -2262,7 +2267,10 @@ reduces them without incurring seq initialization" (defn chunked-seq? "Return true if x satisfies IChunkedSeq." - [x] (implements? IChunkedSeq x)) + [x] + (if-not ^boolean LITE_MODE + (implements? IChunkedSeq x) + false)) ;;;;;;;;;;;;;;;;;;;; js primitives ;;;;;;;;;;;; (defn js-obj @@ -12506,7 +12514,7 @@ reduces them without incurring seq initialization" (-seq [coll] (when (pos? count) (let [hashes (.sort (js-keys hashobj))] - (mapcat #(map vec (partition 2 (aget hashobj %))) + (mapcat #(map (fn [[k v]] (MapEntry. k v)) (partition 2 (unchecked-get hashobj %))) hashes)))) ICounted diff --git a/src/main/clojure/cljs/closure.clj b/src/main/clojure/cljs/closure.clj index c0ed3499a..5dc7db1a3 100644 --- a/src/main/clojure/cljs/closure.clj +++ b/src/main/clojure/cljs/closure.clj @@ -2519,6 +2519,10 @@ :cache-analysis-format (:cache-analysis-format opts :transit)) (update-in [:preamble] #(into (or % []) ["cljs/imul.js"]))) + (:lite-mode opts) + (assoc-in [:closure-defines (str (comp/munge 'cljs.core/LITE_MODE))] + (:lite-mode opts)) + (:target opts) (assoc-in [:closure-defines (str (comp/munge 'cljs.core/*target*))] (name (:target opts))) From d1a6b1da9619e03ff87cab59e103efd62e42ea35 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 18:00:58 -0400 Subject: [PATCH 019/107] fix MapEntry construction --- src/main/cljs/cljs/core.cljs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 7d4cb1f67..5d2becabc 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12514,7 +12514,7 @@ reduces them without incurring seq initialization" (-seq [coll] (when (pos? count) (let [hashes (.sort (js-keys hashobj))] - (mapcat #(map (fn [[k v]] (MapEntry. k v)) (partition 2 (unchecked-get hashobj %))) + (mapcat #(map (fn [[k v]] (MapEntry. k v nil)) (partition 2 (unchecked-get hashobj %))) hashes)))) ICounted @@ -12588,8 +12588,6 @@ reduces them without incurring seq initialization" (recur (inc i) (assoc out (aget ks i) (aget vs i))) out))))) -;; FIXME: calling this (simple-hash-map) expands the codesize significantly, -;; not clear why at the moment, seems to do less than (hash-map) (defn simple-hash-map "keyval => key val Returns a new hash map with supplied mappings." From fa643f13e9fef2787eafc5a1ca06353eed2b488d Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 18:03:08 -0400 Subject: [PATCH 020/107] ->> to core/->> --- src/main/clojure/cljs/core.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/clojure/cljs/core.cljc b/src/main/clojure/cljs/core.cljc index 46445dd31..eccb58533 100644 --- a/src/main/clojure/cljs/core.cljc +++ b/src/main/clojure/cljs/core.cljc @@ -1507,7 +1507,7 @@ ~@body)))) (core/defn- add-obj-methods [type type-sym sigs] - (->> sigs + (core/->> sigs ;; Elide all toString methods in :lite-mode (remove (core/fn [[f]] From d975d2588e6ace801c7a0015dc73b809a67cf7bc Mon Sep 17 00:00:00 2001 From: davidnolen Date: Wed, 30 Jul 2025 18:35:52 -0400 Subject: [PATCH 021/107] remove call to vec from simple-vector --- src/main/cljs/cljs/core.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 5d2becabc..66074c9c1 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12334,7 +12334,7 @@ reduces them without incurring seq initialization" [& args] (if (and (instance? IndexedSeq args) (zero? (.-i args))) (.fromArray Vector (.-arr args) (not (array? (.-arr args)))) - (vec args))) + (Vector. nil (into-array args) nil))) ; The keys field is an array of all keys of this map, in no particular ; order. Any string, keyword, or symbol key is used as a property name From 614d1800a446a36ea2e6963c4f403c396457e066 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 07:34:15 -0400 Subject: [PATCH 022/107] add simple-vec --- src/main/cljs/cljs/core.cljs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 66074c9c1..68cddcc17 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12336,6 +12336,21 @@ reduces them without incurring seq initialization" (.fromArray Vector (.-arr args) (not (array? (.-arr args)))) (Vector. nil (into-array args) nil))) +(defn simple-vec + [coll] + (cond + (map-entry? coll) + [(key coll) (val coll)] + + (vector? coll) + (with-meta coll nil) + + (array? coll) + (.fromArray Vector coll) + + :else + (into [] coll))) + ; The keys field is an array of all keys of this map, in no particular ; order. Any string, keyword, or symbol key is used as a property name ; to store the value in strobj. If a key is assoc'ed when that same From 2d34791bf1c110ca4dc48443dd782ef0b57460b3 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 08:08:00 -0400 Subject: [PATCH 023/107] implement the transient protocols as identity and the standard ops. impossible to respect the O(1) copy contract, but too much of cljs.core relies on the protocol, we have to pretend we support it --- src/main/cljs/cljs/core.cljs | 62 ++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 68cddcc17..02aad72b7 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12323,6 +12323,16 @@ reduces them without incurring seq initialization" (-invoke [coll k not-found] (-lookup coll k not-found)) + IEditableCollection + (-as-transient [coll] + coll) + + ITransientCollection + (-conj! [coll val] + (-conj coll val)) + (-persistent! [coll] + coll) + IPrintWithWriter (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "[" " " "]" opts coll))) @@ -12473,9 +12483,23 @@ reduces them without incurring seq initialization" (-invoke [coll k not-found] (-lookup coll k not-found)) - ;IEditableCollection - ;(-as-transient [coll] - ; (transient (into (simple-hash-map) coll))) + IEditableCollection + (-as-transient [coll] + coll) + + ITransientCollection + (-conj! [coll val] + (-conj coll val)) + (-persistent! [coll] + coll) + + ITransientAssociative + (-assoc! [coll key val] + (-assoc coll key val)) + + ITransientMap + (-dissoc! [coll key] + (-dissoc coll key)) IPrintWithWriter (-pr-writer [coll writer opts] @@ -12590,6 +12614,24 @@ reduces them without incurring seq initialization" (-invoke [coll k not-found] (-lookup coll k not-found)) + IEditableCollection + (-as-transient [coll] + coll) + + ITransientCollection + (-conj! [coll val] + (-conj coll val)) + (-persistent! [coll] + coll) + + ITransientAssociative + (-assoc! [coll key val] + (-assoc coll key val)) + + ITransientMap + (-dissoc! [coll key] + (-dissoc coll key)) + IPrintWithWriter (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) @@ -12655,6 +12697,20 @@ reduces them without incurring seq initialization" (-disjoin [coll v] (Set. meta (dissoc hash-map v) nil)) + IEditableCollection + (-as-transient [coll] + coll) + + ITransientCollection + (-conj! [coll val] + (-conj coll val)) + (-persistent! [coll] + coll) + + ITransientSet + (-disjoin! [coll key] + (-disjoin coll key)) + IFn (-invoke [coll k] (-lookup coll k)) From f67fb7bc2c3d9eb59e941289cd446fcf93c91627 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 11:28:54 -0400 Subject: [PATCH 024/107] sketch for vector and vec replace compiler passes --- src/main/cljs/cljs/analyzer/passes/lite.cljc | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/cljs/cljs/analyzer/passes/lite.cljc diff --git a/src/main/cljs/cljs/analyzer/passes/lite.cljc b/src/main/cljs/cljs/analyzer/passes/lite.cljc new file mode 100644 index 000000000..2abf83271 --- /dev/null +++ b/src/main/cljs/cljs/analyzer/passes/lite.cljc @@ -0,0 +1,28 @@ +;; Copyright (c) Rich Hickey. All rights reserved. +;; The use and distribution terms for this software are covered by the +;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +;; which can be found in the file epl-v10.html at the root of this distribution. +;; By using this software in any fashion, you are agreeing to be bound by +;; the terms of this license. +;; You must not remove this notice, or any other, from this software. + +(ns cljs.analyzer.passes.lite) + +(defn var? [ast] + (= :var (:op ast))) + +(def replace + '{cljs.core/vector cljs.core/simple-vector + cljs.core/vec cljs.core/simple-vec}) + +(defn update-var [{:keys [name] :as ast}] + (update-in ast :name (get replace name))) + +(defn replace-var? [ast] + (and (var? ast) + (contains? replace (:name ast)))) + +(defn use-lite-types + [env ast _] + (cond-> ast + (replace-var? ast) update-var)) \ No newline at end of file From d9eb63ea077e4e8e386b789bce002d54d54f17f3 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 14:24:23 -0400 Subject: [PATCH 025/107] move lite-mode? predicate into the analyzer --- src/main/clojure/cljs/analyzer.cljc | 3 +++ src/main/clojure/cljs/compiler.cljc | 7 ++----- src/main/clojure/cljs/core.cljc | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/clojure/cljs/analyzer.cljc b/src/main/clojure/cljs/analyzer.cljc index 709531e59..6e23cb9db 100644 --- a/src/main/clojure/cljs/analyzer.cljc +++ b/src/main/clojure/cljs/analyzer.cljc @@ -492,6 +492,9 @@ (def ^:dynamic *cljs-warning-handlers* [default-warning-handler]) +(defn lite-mode? [] + (get-in @env/*compiler* [:options :lite-mode])) + #?(:clj (defmacro with-warning-handlers [handlers & body] `(binding [*cljs-warning-handlers* ~handlers] diff --git a/src/main/clojure/cljs/compiler.cljc b/src/main/clojure/cljs/compiler.cljc index dcbf11e9e..65f9be5ed 100644 --- a/src/main/clojure/cljs/compiler.cljc +++ b/src/main/clojure/cljs/compiler.cljc @@ -522,9 +522,6 @@ (and (every? #(= (:op %) :const) keys) (= (count (into #{} keys)) (count keys))))) -(defn lite-mode? [] - (get-in @env/*compiler* [:options :lite-mode])) - (defn obj-map-key [x] (if (keyword? x) (str \" "\\uFDD0" \' @@ -570,7 +567,7 @@ (defmethod emit* :map [{:keys [env form keys vals]}] (emit-wrap env - (if (lite-mode?) + (if (ana/lite-mode?) (let [form-keys (clojure.core/keys form)] (if (every? #(or (string? %) (keyword? %)) form-keys) (emit-obj-map (map obj-map-key form-keys) vals comma-sep distinct-keys?) @@ -599,7 +596,7 @@ (defmethod emit* :vector [{:keys [items env]}] (emit-wrap env - (if (lite-mode?) + (if (ana/lite-mode?) (emit-lite-vector items comma-sep) (emit-vector items comma-sep)))) diff --git a/src/main/clojure/cljs/core.cljc b/src/main/clojure/cljs/core.cljc index eccb58533..70ef0d267 100644 --- a/src/main/clojure/cljs/core.cljc +++ b/src/main/clojure/cljs/core.cljc @@ -1511,7 +1511,7 @@ ;; Elide all toString methods in :lite-mode (remove (core/fn [[f]] - (core/and (comp/lite-mode?) (core/= 'toString f)))) + (core/and (ana/lite-mode?) (core/= 'toString f)))) (map (core/fn [[f & meths :as form]] (core/let [[f meths] (if (vector? (first meths)) From 23492aeddb6b024968c752648e0fdb686bfe0a72 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 14:49:41 -0400 Subject: [PATCH 026/107] fix pass, add lite-mode tests --- src/main/cljs/cljs/analyzer/passes/lite.cljc | 9 +++++---- src/main/clojure/cljs/analyzer.cljc | 8 ++++---- src/test/clojure/cljs/analyzer_pass_tests.clj | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/main/cljs/cljs/analyzer/passes/lite.cljc b/src/main/cljs/cljs/analyzer/passes/lite.cljc index 2abf83271..8f8f77b00 100644 --- a/src/main/cljs/cljs/analyzer/passes/lite.cljc +++ b/src/main/cljs/cljs/analyzer/passes/lite.cljc @@ -6,21 +6,22 @@ ;; the terms of this license. ;; You must not remove this notice, or any other, from this software. -(ns cljs.analyzer.passes.lite) +(ns cljs.analyzer.passes.lite + (:refer-clojure :exclude [var?])) (defn var? [ast] (= :var (:op ast))) -(def replace +(def ctor->simple-ctor '{cljs.core/vector cljs.core/simple-vector cljs.core/vec cljs.core/simple-vec}) (defn update-var [{:keys [name] :as ast}] - (update-in ast :name (get replace name))) + (update ast :name ctor->simple-ctor)) (defn replace-var? [ast] (and (var? ast) - (contains? replace (:name ast)))) + (contains? ctor->simple-ctor (:name ast)))) (defn use-lite-types [env ast _] diff --git a/src/main/clojure/cljs/analyzer.cljc b/src/main/clojure/cljs/analyzer.cljc index 6e23cb9db..aaf7085b2 100644 --- a/src/main/clojure/cljs/analyzer.cljc +++ b/src/main/clojure/cljs/analyzer.cljc @@ -16,6 +16,7 @@ #?(:clj (:require [cljs.analyzer.impl :as impl] [cljs.analyzer.impl.namespaces :as nses] [cljs.analyzer.passes.and-or :as and-or] + [cljs.analyzer.passes.lite :as lite] [cljs.env :as env :refer [ensure]] [cljs.externs :as externs] [cljs.js-deps :as deps] @@ -30,6 +31,7 @@ :cljs (:require [cljs.analyzer.impl :as impl] [cljs.analyzer.impl.namespaces :as nses] [cljs.analyzer.passes.and-or :as and-or] + [cljs.analyzer.passes.lite :as lite] [cljs.env :as env] [cljs.reader :as edn] [cljs.tagged-literals :as tags] @@ -4455,10 +4457,8 @@ :cljs [infer-type and-or/optimize check-invoke-arg-types])) (defn analyze* [env form name opts] - (let [passes *passes* - passes (if (nil? passes) - default-passes - passes) + (let [passes (cond-> (or *passes* default-passes) + (lite-mode?) (conj lite/use-lite-types)) form (if (instance? LazySeq form) (if (seq form) form ()) form) diff --git a/src/test/clojure/cljs/analyzer_pass_tests.clj b/src/test/clojure/cljs/analyzer_pass_tests.clj index c87ec7bce..d0d4ba06c 100644 --- a/src/test/clojure/cljs/analyzer_pass_tests.clj +++ b/src/test/clojure/cljs/analyzer_pass_tests.clj @@ -178,8 +178,25 @@ (map (fn [x] x) s))))]))))] (is (empty? (re-seq #"or_" code)))))) +(deftest test-lite-mode-pass + (let [aenv (assoc (ana/empty-env) :context :expr) + env (env/default-compiler-env {:lite-mode true})] + (is (= 'cljs.core/simple-vec + (-> (env/with-compiler-env env + (comp/with-core-cljs {} + (fn [] + (analyze aenv 'cljs.core/vec)))) + :name))) + (is (= 'cljs.core/simple-vector + (-> (env/with-compiler-env env + (comp/with-core-cljs {} + (fn [] + (analyze aenv 'cljs.core/vector)))) + :name))))) + (comment (test/run-tests) (require '[clojure.pprint :refer [pprint]]) + ) From 94c1886ba074b6ad99d3f6b664b4366449a9a82f Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 15:24:45 -0400 Subject: [PATCH 027/107] for fn invokes to be replace we also need to update :info --- src/main/cljs/cljs/analyzer/passes/lite.cljc | 5 ++++- src/test/clojure/cljs/analyzer_pass_tests.clj | 22 ++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/main/cljs/cljs/analyzer/passes/lite.cljc b/src/main/cljs/cljs/analyzer/passes/lite.cljc index 8f8f77b00..08a7e03de 100644 --- a/src/main/cljs/cljs/analyzer/passes/lite.cljc +++ b/src/main/cljs/cljs/analyzer/passes/lite.cljc @@ -17,7 +17,10 @@ cljs.core/vec cljs.core/simple-vec}) (defn update-var [{:keys [name] :as ast}] - (update ast :name ctor->simple-ctor)) + (let [replacement (get ctor->simple-ctor name)] + (-> ast + (assoc :name replacement) + (assoc-in [:info :name] replacement)))) (defn replace-var? [ast] (and (var? ast) diff --git a/src/test/clojure/cljs/analyzer_pass_tests.clj b/src/test/clojure/cljs/analyzer_pass_tests.clj index d0d4ba06c..1a451d491 100644 --- a/src/test/clojure/cljs/analyzer_pass_tests.clj +++ b/src/test/clojure/cljs/analyzer_pass_tests.clj @@ -181,18 +181,20 @@ (deftest test-lite-mode-pass (let [aenv (assoc (ana/empty-env) :context :expr) env (env/default-compiler-env {:lite-mode true})] - (is (= 'cljs.core/simple-vec - (-> (env/with-compiler-env env - (comp/with-core-cljs {} - (fn [] - (analyze aenv 'cljs.core/vec)))) - :name))) - (is (= 'cljs.core/simple-vector - (-> (env/with-compiler-env env + (let [ast (env/with-compiler-env env (comp/with-core-cljs {} (fn [] - (analyze aenv 'cljs.core/vector)))) - :name))))) + (analyze aenv 'cljs.core/vec))))] + (is (= 'cljs.core/simple-vec + (-> ast :name) + (-> ast :info :name)))) + (let [ast (env/with-compiler-env env + (comp/with-core-cljs {} + (fn [] + (analyze aenv 'cljs.core/vector))))] + (is (= 'cljs.core/simple-vector + (-> ast :name) + (-> ast :info :name)))))) (comment (test/run-tests) From c31e77c30182fdb3ebb8db56935ae1249b257f3d Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 20:24:45 -0400 Subject: [PATCH 028/107] `vector` is an inlining macro, so can't handle it only as a pass - need to add a case to macro expansion --- src/main/clojure/cljs/analyzer.cljc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/clojure/cljs/analyzer.cljc b/src/main/clojure/cljs/analyzer.cljc index aaf7085b2..87733cf05 100644 --- a/src/main/clojure/cljs/analyzer.cljc +++ b/src/main/clojure/cljs/analyzer.cljc @@ -4077,8 +4077,10 @@ (if (and (some? nsym) (symbol? nsym)) (.findInternedVar ^clojure.lang.Namespace #?(:clj (find-ns nsym) :cljs (find-macros-ns nsym)) sym) - (.findInternedVar ^clojure.lang.Namespace - #?(:clj (find-ns 'cljs.core) :cljs (find-macros-ns impl/CLJS_CORE_MACROS_SYM)) sym))))))) + ;; can't be done as compiler pass because macros get to run first + (when-not (and (lite-mode?) (= 'vector sym)) + (.findInternedVar ^clojure.lang.Namespace + #?(:clj (find-ns 'cljs.core) :cljs (find-macros-ns impl/CLJS_CORE_MACROS_SYM)) sym)))))))) (defn get-expander "Given a sym, a symbol identifying a macro, and env, an analysis environment From 4f4842a61aa711f52cee3d4d9415090c28b32a69 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 20:35:25 -0400 Subject: [PATCH 029/107] handle sets --- src/main/cljs/cljs/core.cljs | 12 ++++++++++++ src/main/clojure/cljs/compiler.cljc | 9 ++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 02aad72b7..46329b8ff 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12721,3 +12721,15 @@ reduces them without incurring seq initialization" (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "#{" " " "}" opts coll))) (set! (. Set -EMPTY) (Set. nil (. HashMap -EMPTY) empty-unordered-hash)) + +(defn simple-set + [coll] + (if (set? coll) + (with-meta coll nil) + (let [in (seq coll)] + (if (nil? in) + #{} + (loop [in in out (. Set -EMPTY)] + (if-not (nil? in) + (recur (next in) (conj out (first in))) + out)))))) diff --git a/src/main/clojure/cljs/compiler.cljc b/src/main/clojure/cljs/compiler.cljc index 65f9be5ed..ce90f1f34 100644 --- a/src/main/clojure/cljs/compiler.cljc +++ b/src/main/clojure/cljs/compiler.cljc @@ -616,10 +616,17 @@ :else (emits "cljs.core.PersistentHashSet.createAsIfByAssoc([" (comma-sep items) "])"))) +(defn emit-lite-set [items comma-sep distinct-constants?] + (if (empty? items) + (emits "cljs.core.Set.EMPTY") + (emits "cljs.core.simple_set([" (comma-sep items) "])"))) + (defmethod emit* :set [{:keys [items env]}] (emit-wrap env - (emit-set items comma-sep distinct-constants?))) + (if (ana/lite-mode?) + (emit-lite-set items comma-sep distinct-constants?) + (emit-set items comma-sep distinct-constants?)))) (defn emit-js-object [items emit-js-object-val] (emits "({") From 5873009542956caa8cdc1cf2618f97892a3799b6 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 22:41:26 -0400 Subject: [PATCH 030/107] avoid lazyseq stuff in HashMap impl --- src/main/cljs/cljs/core.cljs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 46329b8ff..2cf7a10fd 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12552,9 +12552,20 @@ reduces them without incurring seq initialization" ISeqable (-seq [coll] (when (pos? count) - (let [hashes (.sort (js-keys hashobj))] - (mapcat #(map (fn [[k v]] (MapEntry. k v nil)) (partition 2 (unchecked-get hashobj %))) - hashes)))) + (let [hashes (.sort (js-keys hashobj)) + cnt (alength hashes) + arr (array)] + (loop [i 0] + (if (< i cnt) + (let [bckt (unchecked-get hashobj (aget hashes i)) + len (alength bkt)] + (loop [j 0] + (when (< j len) + (do + (.push arr (MapEntry. (aget bkt j) (aget bkt (inc j)) nil)) + (recur (+ j 2))))) + (recur (inc i))) + (prim-seq arr)))))) ICounted (-count [coll] count) From 9a2c2e86df593a3329f7e90c896b29fdb9d3acc1 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 23:07:54 -0400 Subject: [PATCH 031/107] typos --- src/main/cljs/cljs/core.cljs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 2cf7a10fd..60937b3d8 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12414,7 +12414,7 @@ reduces them without incurring seq initialization" (when (pos? (alength keys)) (prim-seq (.map (.sort keys obj-map-compare-keys) - #(unchecked-get strobj %)) 0))) + #(MapEntry. % (unchecked-get strobj %)))))) ICounted (-count [coll] (alength keys)) @@ -12558,11 +12558,11 @@ reduces them without incurring seq initialization" (loop [i 0] (if (< i cnt) (let [bckt (unchecked-get hashobj (aget hashes i)) - len (alength bkt)] + len (alength bckt)] (loop [j 0] (when (< j len) (do - (.push arr (MapEntry. (aget bkt j) (aget bkt (inc j)) nil)) + (.push arr (MapEntry. (aget bckt j) (aget bckt (inc j)) nil)) (recur (+ j 2))))) (recur (inc i))) (prim-seq arr)))))) From c81817a31f839e476eee40ab9d3ee512c52e03ff Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 23:17:19 -0400 Subject: [PATCH 032/107] avoid full blown map entry --- src/main/cljs/cljs/core.cljs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 60937b3d8..01110b0f3 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10383,7 +10383,7 @@ reduces them without incurring seq initialization" (implements? IMeta obj) (not (nil? (meta obj))))) -(defn- pr-map-entry [k v] +(defn- simple-map-entry [k v] (reify IMapEntry (-key [_] k) @@ -10429,7 +10429,7 @@ reduces them without incurring seq initialization" (.map (js-keys obj) (fn [k] - (pr-map-entry + (simple-map-entry (cond-> k (some? (.match k #"^[A-Za-z_\*\+\?!\-'][\w\*\+\?!\-']*$")) keyword) (unchecked-get obj k)))) pr-writer writer opts)) @@ -10610,10 +10610,10 @@ reduces them without incurring seq initialization" (when (or (keyword? k) (symbol? k)) (if ns (when (= ns (namespace k)) - (.push lm (pr-map-entry (strip-ns k) v)) + (.push lm (simple-map-entry (strip-ns k) v)) (recur ns entries)) (when-let [new-ns (namespace k)] - (.push lm (pr-map-entry (strip-ns k) v)) + (.push lm (simple-map-entry (strip-ns k) v)) (recur new-ns entries)))) #js [ns lm]))))) @@ -12414,7 +12414,7 @@ reduces them without incurring seq initialization" (when (pos? (alength keys)) (prim-seq (.map (.sort keys obj-map-compare-keys) - #(MapEntry. % (unchecked-get strobj %)))))) + #(simple-map-entry % (unchecked-get strobj %)))))) ICounted (-count [coll] (alength keys)) @@ -12562,7 +12562,7 @@ reduces them without incurring seq initialization" (loop [j 0] (when (< j len) (do - (.push arr (MapEntry. (aget bckt j) (aget bckt (inc j)) nil)) + (.push arr (simple-map-entry (aget bckt j) (aget bckt (inc j)) nil)) (recur (+ j 2))))) (recur (inc i))) (prim-seq arr)))))) From 6ce216c258bd5f0280e58dc9316c3cd17e430dd0 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 31 Jul 2025 23:33:34 -0400 Subject: [PATCH 033/107] - more std-lib avoidance, micro sizing opts - fix str keys --- src/main/cljs/cljs/core.cljs | 22 +++++++++++----------- src/main/clojure/cljs/compiler.cljc | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 01110b0f3..9318067d0 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12401,7 +12401,7 @@ reduces them without incurring seq initialization" (reduce -conj coll entry))) IEmptyableCollection - (-empty [coll] (with-meta (. ObjMap -EMPTY) meta)) + (-empty [coll] (-with-meta (. ObjMap -EMPTY) meta)) IEquiv (-equiv [coll other] (equiv-map coll other)) @@ -12433,14 +12433,14 @@ reduces them without incurring seq initialization" (if-not (nil? (scan-array 1 k keys)) (let [new-strobj (obj-clone strobj keys)] (gobject/set new-strobj k v) - (ObjMap. meta keys new-strobj nil)) ; overwrite - (let [new-strobj (obj-clone strobj keys) ; append - new-keys (aclone keys)] + (ObjMap. meta keys new-strobj nil)) ; overwrite + (let [new-strobj (obj-clone strobj keys) ; append + new-keys (aclone keys)] (gobject/set new-strobj k v) (.push new-keys k) (ObjMap. meta new-keys new-strobj nil))) ; non-string key. game over. - (with-meta (into (simple-hash-map k v) (seq coll)) meta))) + (-with-meta (apply simple-hash-map k v (-seq coll)) meta))) (-contains-key? [coll k] (if (and (string? k) (not (nil? (scan-array 1 k keys)))) @@ -12662,7 +12662,7 @@ reduces them without incurring seq initialization" [& keyvals] (loop [in (seq keyvals), out (. HashMap -EMPTY)] (if in - (recur (nnext in) (assoc out (first in) (second in))) + (recur (nnext in) (-assoc out (first in) (second in))) out))) (deftype Set [meta hash-map ^:mutable __hash] @@ -12683,7 +12683,7 @@ reduces them without incurring seq initialization" (-equiv [coll other] (and (set? other) - (= (count coll) (count other)) + (= (-count coll) (count other)) (every? #(contains? coll %) other))) @@ -12694,7 +12694,7 @@ reduces them without incurring seq initialization" (-seq [coll] (keys hash-map)) ICounted - (-count [coll] (count (seq coll))) + (-count [coll] (-count (-seq coll))) ILookup (-lookup [coll v] @@ -12706,7 +12706,7 @@ reduces them without incurring seq initialization" ISet (-disjoin [coll v] - (Set. meta (dissoc hash-map v) nil)) + (Set. meta (-dissoc hash-map v) nil)) IEditableCollection (-as-transient [coll] @@ -12736,11 +12736,11 @@ reduces them without incurring seq initialization" (defn simple-set [coll] (if (set? coll) - (with-meta coll nil) + (-with-meta coll nil) (let [in (seq coll)] (if (nil? in) #{} (loop [in in out (. Set -EMPTY)] (if-not (nil? in) - (recur (next in) (conj out (first in))) + (recur (next in) (-conj out (first in))) out)))))) diff --git a/src/main/clojure/cljs/compiler.cljc b/src/main/clojure/cljs/compiler.cljc index ce90f1f34..faba462b5 100644 --- a/src/main/clojure/cljs/compiler.cljc +++ b/src/main/clojure/cljs/compiler.cljc @@ -529,7 +529,7 @@ (str (namespace x) "/") "") (name x) \") - x)) + (str \" x \"))) (defn emit-obj-map [str-keys vals comma-sep distinct-keys?] (if (zero? (count str-keys)) From a2373cb009305293a9b81451c6d0b5d500de5765 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 1 Aug 2025 00:12:07 -0400 Subject: [PATCH 034/107] - use kv-reduce to save some more space --- src/main/cljs/cljs/core.cljs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 9318067d0..9945154d7 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12440,7 +12440,12 @@ reduces them without incurring seq initialization" (.push new-keys k) (ObjMap. meta new-keys new-strobj nil))) ; non-string key. game over. - (-with-meta (apply simple-hash-map k v (-seq coll)) meta))) + (-with-meta + (-kv-reduce coll + (fn [ret k v] + (-assoc ret k v)) + (. HashMap -EMPTY) ) + meta))) (-contains-key? [coll k] (if (and (string? k) (not (nil? (scan-array 1 k keys)))) From 1967067540c6b7c60a1b04f8b3753d7ca8290f8d Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 1 Aug 2025 00:13:01 -0400 Subject: [PATCH 035/107] - formatting --- src/main/cljs/cljs/core.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 9945154d7..e9734a585 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12433,8 +12433,8 @@ reduces them without incurring seq initialization" (if-not (nil? (scan-array 1 k keys)) (let [new-strobj (obj-clone strobj keys)] (gobject/set new-strobj k v) - (ObjMap. meta keys new-strobj nil)) ; overwrite - (let [new-strobj (obj-clone strobj keys) ; append + (ObjMap. meta keys new-strobj nil)) ;overwrite + (let [new-strobj (obj-clone strobj keys) ; append new-keys (aclone keys)] (gobject/set new-strobj k v) (.push new-keys k) From 67ee02bcdbc0f092e8724736067cedbd71a03568 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Sat, 2 Aug 2025 22:21:41 -0400 Subject: [PATCH 036/107] - before core fns knew about the ObjMap key rep - now it needs to be an internal detail - testing stuff wip --- resources/lite_test.edn | 10 +++ src/main/cljs/cljs/core.cljs | 87 ++++++++++--------- src/test/cljs/cljs/lite_collections_test.cljs | 11 +++ src/test/cljs/lite_test_runner.cljs | 21 +++++ 4 files changed, 90 insertions(+), 39 deletions(-) create mode 100644 resources/lite_test.edn create mode 100644 src/test/cljs/cljs/lite_collections_test.cljs create mode 100644 src/test/cljs/lite_test_runner.cljs diff --git a/resources/lite_test.edn b/resources/lite_test.edn new file mode 100644 index 000000000..5b4520dde --- /dev/null +++ b/resources/lite_test.edn @@ -0,0 +1,10 @@ +{:optimizations :advanced + :main lite-test-runner + :output-to "builds/out-lite/lite-test.js" + :output-dir "builds/out-lite" + :output-wrapper true + :verbose true + :compiler-stats true + :parallel-build true + :closure-warnings {:non-standard-jsdoc :off :global-this :off} + :language-out :es5} diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index e9734a585..316a5c8e1 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12371,9 +12371,9 @@ reduces them without incurring seq initialization" (let [a (hash a) b (hash b)] (cond - (< a b) -1 - (> a b) 1 - :else 0))) + (< a b) -1 + (> a b) 1 + :else 0))) (defn- obj-clone [obj ks] (let [new-obj (js-obj) @@ -12387,6 +12387,10 @@ reduces them without incurring seq initialization" (declare simple-hash-map) +(defn- keyword->obj-map-key + [k] + (str "\uFDD0" "'" (. k -fqn))) + (deftype ObjMap [meta keys strobj ^:mutable __hash] IWithMeta (-with-meta [coll meta] (ObjMap. meta keys strobj __hash)) @@ -12422,41 +12426,45 @@ reduces them without incurring seq initialization" ILookup (-lookup [coll k] (-lookup coll k nil)) (-lookup [coll k not-found] - (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) - (unchecked-get strobj k) - not-found)) + (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] + (if (and (string? k) + (not (nil? (scan-array 1 k keys)))) + (unchecked-get strobj k) + not-found))) IAssociative (-assoc [coll k v] - (if (string? k) - (if-not (nil? (scan-array 1 k keys)) - (let [new-strobj (obj-clone strobj keys)] - (gobject/set new-strobj k v) - (ObjMap. meta keys new-strobj nil)) ;overwrite - (let [new-strobj (obj-clone strobj keys) ; append - new-keys (aclone keys)] - (gobject/set new-strobj k v) - (.push new-keys k) - (ObjMap. meta new-keys new-strobj nil))) - ; non-string key. game over. - (-with-meta - (-kv-reduce coll - (fn [ret k v] - (-assoc ret k v)) - (. HashMap -EMPTY) ) - meta))) + (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] + (if (string? k) + (if-not (nil? (scan-array 1 k keys)) + (let [new-strobj (obj-clone strobj keys)] + (gobject/set new-strobj k v) + (ObjMap. meta keys new-strobj nil)) ;overwrite + (let [new-strobj (obj-clone strobj keys) ; append + new-keys (aclone keys)] + (gobject/set new-strobj k v) + (.push new-keys k) + (ObjMap. meta new-keys new-strobj nil))) + ; non-string key. game over. + (-with-meta + (-kv-reduce coll + (fn [ret k v] + (-assoc ret k v)) + (. HashMap -EMPTY)) + meta)))) (-contains-key? [coll k] - (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) - true - false)) + (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] + (if (and (string? k) + (not (nil? (scan-array 1 k keys)))) + true + false))) IFind (-find [coll k] - (when (and (string? k) - (not (nil? (scan-array 1 k keys)))) - (MapEntry. k (unchecked-get strobj k) nil))) + (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] + (when (and (string? k) + (not (nil? (scan-array 1 k keys)))) + (MapEntry. k (unchecked-get strobj k) nil)))) IKVReduce (-kv-reduce [coll f init] @@ -12473,14 +12481,15 @@ reduces them without incurring seq initialization" IMap (-dissoc [coll k] - (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) - (let [new-keys (aclone keys) - new-strobj (obj-clone strobj keys)] - (.splice new-keys (scan-array 1 k new-keys) 1) - (js-delete new-strobj k) - (ObjMap. meta new-keys new-strobj nil)) - coll)) ; key not found, return coll unchanged + (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] + (if (and (string? k) + (not (nil? (scan-array 1 k keys)))) + (let [new-keys (aclone keys) + new-strobj (obj-clone strobj keys)] + (.splice new-keys (scan-array 1 k new-keys) 1) + (js-delete new-strobj k) + (ObjMap. meta new-keys new-strobj nil)) + coll))) ; key not found, return coll unchanged IFn (-invoke [coll k] diff --git a/src/test/cljs/cljs/lite_collections_test.cljs b/src/test/cljs/cljs/lite_collections_test.cljs new file mode 100644 index 000000000..9545f7f07 --- /dev/null +++ b/src/test/cljs/cljs/lite_collections_test.cljs @@ -0,0 +1,11 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +; which can be found in the file epl-v10.html at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + +(ns cljs.lite-collections-test + (:require [cljs.test :refer-macros [deftest testing is are run-tests]] + [clojure.test.check.clojure-test :refer-macros [defspec]])) \ No newline at end of file diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs new file mode 100644 index 000000000..4869410ef --- /dev/null +++ b/src/test/cljs/lite_test_runner.cljs @@ -0,0 +1,21 @@ +;; Copyright (c) Rich Hickey. All rights reserved. +;; The use and distribution terms for this software are covered by the +;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +;; which can be found in the file epl-v10.html at the root of this distribution. +;; By using this software in any fashion, you are agreeing to be bound by +;; the terms of this license. +;; You must not remove this notice, or any other, from this software. + +(ns lite-test-runner + (:require [cljs.lite-collections-test])) + +(set! *print-newline* false) + +;; When testing Windows we default to Node.js +(if (exists? js/print) + (set-print-fn! js/print) + (enable-console-print!)) + +(run-tests + 'cljs.collections-test + ) From 28f513352603720a068e22e9955eabd7caf1960c Mon Sep 17 00:00:00 2001 From: David Nolen Date: Sun, 3 Aug 2025 07:04:29 -0400 Subject: [PATCH 037/107] - lite testing wip --- deps.edn | 2 ++ resources/lite_test.edn | 21 +++++++++++-------- src/test/cljs/cljs/lite_collections_test.cljs | 10 +++++++-- src/test/cljs/lite_test_runner.cljs | 5 +++-- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/deps.edn b/deps.edn index 012e22069..e3a236c2a 100644 --- a/deps.edn +++ b/deps.edn @@ -19,6 +19,8 @@ "-e" "(cljs.test-runner/-main)"]} :runtime.test.build {:extra-paths ["src/test/cljs"] :main-opts ["-m" "cljs.main" "-co" "resources/test.edn" "-c"]} + :lite.test.build {:extra-paths ["src/test/cljs"] + :main-opts ["-m" "cljs.main" "-co" "resources/lite_test.edn" "-c"]} :selfhost.test.build {:extra-paths ["src/test/self"] :main-opts ["-m" "cljs.main" "-co" "resources/self_host_test.edn" "-c"]} :selfparity.test.build {:extra-paths ["src/test/self"] diff --git a/resources/lite_test.edn b/resources/lite_test.edn index 5b4520dde..11b3d3f9f 100644 --- a/resources/lite_test.edn +++ b/resources/lite_test.edn @@ -1,10 +1,13 @@ -{:optimizations :advanced - :main lite-test-runner - :output-to "builds/out-lite/lite-test.js" - :output-dir "builds/out-lite" - :output-wrapper true - :verbose true - :compiler-stats true - :parallel-build true +{:optimizations :advanced + :main lite-test-runner + :lite-mode true + :output-to "builds/out-lite/lite-test.js" + :output-dir "builds/out-lite" + :output-wrapper true + :verbose true + :compiler-stats true + :parallel-build true :closure-warnings {:non-standard-jsdoc :off :global-this :off} - :language-out :es5} + :language-out :es5 + :pseudo-names true + :pretty-print true} diff --git a/src/test/cljs/cljs/lite_collections_test.cljs b/src/test/cljs/cljs/lite_collections_test.cljs index 9545f7f07..474099617 100644 --- a/src/test/cljs/cljs/lite_collections_test.cljs +++ b/src/test/cljs/cljs/lite_collections_test.cljs @@ -7,5 +7,11 @@ ; You must not remove this notice, or any other, from this software. (ns cljs.lite-collections-test - (:require [cljs.test :refer-macros [deftest testing is are run-tests]] - [clojure.test.check.clojure-test :refer-macros [defspec]])) \ No newline at end of file + (:require [cljs.test :refer-macros [deftest testing is are run-tests]])) + +;; NOTE: ** this name space must be tested with :lite-mode true ** + +(deftest test-obj-map + (let [a (. ObjMap -EMPTY) + b {}] + (is (identical? a b)))) \ No newline at end of file diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 4869410ef..baa7b0435 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -7,7 +7,8 @@ ;; You must not remove this notice, or any other, from this software. (ns lite-test-runner - (:require [cljs.lite-collections-test])) + (:require [cljs.test :refer-macros [run-tests]] + [cljs.lite-collections-test])) (set! *print-newline* false) @@ -17,5 +18,5 @@ (enable-console-print!)) (run-tests - 'cljs.collections-test + 'cljs.lite-collections-test ) From c447abb904df64742f6690baf84b44fd73c9db15 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Sun, 3 Aug 2025 07:05:02 -0400 Subject: [PATCH 038/107] - cannot pass arrays to ci-reduce, use array-reduce --- src/main/cljs/cljs/core.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 316a5c8e1..817fb0914 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12313,9 +12313,9 @@ reduces them without incurring seq initialization" IReduce (-reduce [v f] - (ci-reduce array f)) + (array-reduce array f)) (-reduce [v f start] - (ci-reduce array f start)) + (array-reduce array f start)) IFn (-invoke [coll k] From 8246266503a04552b5d6a12f7347036af8b99253 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Sun, 3 Aug 2025 07:16:01 -0400 Subject: [PATCH 039/107] - fix simple-map-entryff call --- src/main/cljs/cljs/core.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 817fb0914..8ee9dfef5 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12576,7 +12576,7 @@ reduces them without incurring seq initialization" (loop [j 0] (when (< j len) (do - (.push arr (simple-map-entry (aget bckt j) (aget bckt (inc j)) nil)) + (.push arr (simple-map-entry (aget bckt j) (aget bckt (inc j)))) (recur (+ j 2))))) (recur (inc i))) (prim-seq arr)))))) From 73c5b89f1c7a05de6a12332c6ceee5838c985922 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Sun, 3 Aug 2025 07:30:11 -0400 Subject: [PATCH 040/107] - missing declare --- src/main/cljs/cljs/core.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 8ee9dfef5..8fbc47423 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12385,7 +12385,7 @@ reduces them without incurring seq initialization" (recur (inc i))))) new-obj)) -(declare simple-hash-map) +(declare simple-hash-map HashMap) (defn- keyword->obj-map-key [k] From 393a5941d0df2b6aa5422d8a0c827af3f83a2983 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Sun, 3 Aug 2025 07:55:55 -0400 Subject: [PATCH 041/107] - simple-map-entry needs to satisfy IVector and IIndexed --- src/main/cljs/cljs/core.cljs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 8fbc47423..e40cf12ab 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10385,11 +10385,22 @@ reduces them without incurring seq initialization" (defn- simple-map-entry [k v] (reify + IVector + (-assoc-n [_ n x] + (case n + 0 (simple-map-entry x v) + 1 (simple-map-entry k x) + (throw (js/Error. "Index out of bounds")))) IMapEntry (-key [_] k) (-val [_] v) ISeqable - (-seq [_] (IndexedSeq. #js [k v] 0 nil)))) + (-seq [_] (IndexedSeq. #js [k v] 0 nil)) + IIndexed + (-nth [_ i] + (case i, 0 k, 1 v, (throw (js/Error. "Index out of bounds")))) + (-nth [_ i not-found] + (case i, 0 k, 1 v, not-found)))) (defn- pr-writer-impl [obj writer opts] From 8eae3806ed70e5bf0cad84f46b4afdffe034b009 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Sun, 3 Aug 2025 20:31:30 -0400 Subject: [PATCH 042/107] - remove doseq from printing - don't leak internal key rep from ObjMap --- src/main/cljs/cljs/core.cljs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index e40cf12ab..1373516ba 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10347,8 +10347,10 @@ reduces them without incurring seq initialization" (-write writer end))))) (defn write-all [writer & ss] - (doseq [s ss] - (-write writer s))) + (loop [ss (seq ss)] + (when-not (nil? ss) + (-write writer (first ss)) + (recur (next ss))))) (defn string-print [x] (when (nil? *print-fn*) @@ -10509,9 +10511,11 @@ reduces them without incurring seq initialization" (defn pr-seq-writer [objs writer opts] (pr-writer (first objs) writer opts) - (doseq [obj (next objs)] - (-write writer " ") - (pr-writer obj writer opts))) + (loop [objs (next objs)] + (when-not (nil? objs) + (-write writer " ") + (pr-writer (first objs) writer opts) + (recur (next objs))))) (defn- pr-sb-with-opts [objs opts] (let [sb (StringBuffer.) @@ -12402,6 +12406,12 @@ reduces them without incurring seq initialization" [k] (str "\uFDD0" "'" (. k -fqn))) +(defn- obj-map-key->keyword + [k] + (if (.startsWith k "\uFDD0") + (keyword (.substring k 2 (. k -length))) + k)) + (deftype ObjMap [meta keys strobj ^:mutable __hash] IWithMeta (-with-meta [coll meta] (ObjMap. meta keys strobj __hash)) @@ -12429,7 +12439,7 @@ reduces them without incurring seq initialization" (when (pos? (alength keys)) (prim-seq (.map (.sort keys obj-map-compare-keys) - #(simple-map-entry % (unchecked-get strobj %)))))) + #(simple-map-entry (obj-map-key->keyword %) (unchecked-get strobj %)))))) ICounted (-count [coll] (alength keys)) @@ -12484,7 +12494,7 @@ reduces them without incurring seq initialization" init init] (if (seq keys) (let [k (first keys) - init (f init k (unchecked-get strobj k))] + init (f init (obj-map-key->keyword k) (unchecked-get strobj k))] (if (reduced? init) @init (recur (rest keys) init))) @@ -12494,7 +12504,7 @@ reduces them without incurring seq initialization" (-dissoc [coll k] (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) + (not (nil? (scan-array 1 k keys)))) (let [new-keys (aclone keys) new-strobj (obj-clone strobj keys)] (.splice new-keys (scan-array 1 k new-keys) 1) From 5611cd503723b0a8e6f7b42e89eb854cb98afda5 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Sun, 3 Aug 2025 21:09:00 -0400 Subject: [PATCH 043/107] - obj-map is definitely incomplete, but fix the obvious problem now --- src/main/cljs/cljs/core.cljs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 1373516ba..063bb4b25 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12552,9 +12552,10 @@ reduces them without incurring seq initialization" obj (js-obj)] (loop [kvs (seq keyvals)] (if kvs - (do (.push ks (first kvs)) - (gobject/set obj (first kvs) (second kvs)) - (recur (nnext kvs))) + (let [k (-> kvs first keyword->obj-map-key)] + (.push ks k) + (gobject/set obj k (second kvs)) + (recur (nnext kvs))) (.fromObject ObjMap ks obj))))) ; The keys field is an array of all keys of this map, in no particular From e4bc146ca3e70bc4f9cbf06e56076f5a93554a59 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Mon, 4 Aug 2025 08:30:14 -0400 Subject: [PATCH 044/107] - simple-map-entry IEquiv --- src/main/cljs/cljs/core.cljs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 063bb4b25..f2fd26dbf 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10387,6 +10387,8 @@ reduces them without incurring seq initialization" (defn- simple-map-entry [k v] (reify + IEquiv + (-equiv [coll other] (equiv-sequential coll other)) IVector (-assoc-n [_ n x] (case n From dadba060eee2bd3752d69debb04ecdcd84598b37 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Mon, 4 Aug 2025 08:30:53 -0400 Subject: [PATCH 045/107] - test-obj-map in collections test - cleanup ns form --- src/test/cljs/cljs/collections_test.cljs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index 44d5e3f46..6027a3acf 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -9,12 +9,9 @@ (ns cljs.collections-test (:refer-clojure :exclude [iter]) (:require [cljs.test :refer-macros [deftest testing is are run-tests]] - [clojure.test.check :as tc] [clojure.test.check.clojure-test :refer-macros [defspec]] [clojure.test.check.generators :as gen] - [clojure.test.check.properties :as prop :include-macros true] - [clojure.string :as s] - [clojure.set :as set])) + [clojure.test.check.properties :as prop :include-macros true])) (deftest test-map-operations (testing "Test basic map collection operations" @@ -1157,6 +1154,22 @@ (let [things (zipmap (range 15000) (repeat 0))] (is (zero? (count (filter #(-> % key string?) things)))))) +(deftest test-obj-map + (let [a (obj-map)] + (is (empty? a)) + (is (zero? (count a)))) + (let [b (obj-map :a 1)] + (is (not (empty? b))) + (is (== 1 (count b)))) + (let [c (obj-map :a 1 :b 2 :c 3)] + (is (== 3 (count c))) + (is (= 1 (get c :a))) + (is (= 1 (:a c))) + (is (every? keyword? (keys c))) + (is (= (set [:a :b :c]) (set (keys c))))) + (is (= (obj-map :a 1 :b 2 :c 3) + (obj-map :a 1 :b 2 :c 3)))) + (comment (run-tests) From 2b4a93739023d9989596924f0c0664a90288f289 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Mon, 4 Aug 2025 23:17:13 -0400 Subject: [PATCH 046/107] - fix up HashMap issues --- src/main/cljs/cljs/core.cljs | 47 +++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index f2fd26dbf..d31f5ec9f 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -6560,15 +6560,6 @@ reduces them without incurring seq initialization" (= (get y (first xkv) never-equiv) (second xkv))) x)))))) - -(defn- scan-array [incr k array] - (let [len (alength array)] - (loop [i 0] - (when (< i len) - (if (identical? k (aget array i)) - i - (recur (+ i incr))))))) - ;; Record Iterator (deftype RecordIter [^:mutable i record base-count fields ext-map-iter] Object @@ -12414,6 +12405,14 @@ reduces them without incurring seq initialization" (keyword (.substring k 2 (. k -length))) k)) +(defn- scan-array [incr k array] + (let [len (alength array)] + (loop [i 0] + (when (< i len) + (if (identical? k (aget array i)) + i + (recur (+ i incr))))))) + (deftype ObjMap [meta keys strobj ^:mutable __hash] IWithMeta (-with-meta [coll meta] (ObjMap. meta keys strobj __hash)) @@ -12560,6 +12559,14 @@ reduces them without incurring seq initialization" (recur (nnext kvs))) (.fromObject ObjMap ks obj))))) +(defn- scan-array-equiv [incr k array] + (let [len (alength array)] + (loop [i 0] + (when (< i len) + (if (= k (aget array i)) + i + (recur (+ i incr))))))) + ; The keys field is an array of all keys of this map, in no particular ; order. Each key is hashed and the result used as a property name of ; hashobj. Each values in hashobj is actually a bucket in order to handle hash @@ -12611,25 +12618,27 @@ reduces them without incurring seq initialization" ILookup (-lookup [coll k] (-lookup coll k nil)) (-lookup [coll k not-found] - (let [bucket (aget hashobj (hash k)) - i (when bucket (scan-array 2 k bucket))] - (if i + (let [bucket (unchecked-get hashobj (hash k)) + i (when bucket (scan-array-equiv 2 k bucket))] + (if (some? i) (aget bucket (inc i)) not-found))) IAssociative (-assoc [coll k v] (let [h (hash k) - bucket (aget hashobj h)] + bucket (unchecked-get hashobj h)] (if bucket (let [new-bucket (aclone bucket) new-hashobj (gobject/clone hashobj)] (aset new-hashobj h new-bucket) - (if-let [i (scan-array 2 k new-bucket)] - (do ; found key, replace + (if-let [i (scan-array-equiv 2 k new-bucket)] + (do + ; found key, replace (aset new-bucket (inc i) v) (HashMap. meta count new-hashobj nil)) - (do ; did not find key, append + (do + ; did not find key, append (.push new-bucket k v) (HashMap. meta (inc count) new-hashobj nil)))) (let [new-hashobj (gobject/clone hashobj)] ; did not find bucket @@ -12637,8 +12646,8 @@ reduces them without incurring seq initialization" (HashMap. meta (inc count) new-hashobj nil))))) (-contains-key? [coll k] (let [bucket (unchecked-get hashobj (hash k)) - i (when bucket (scan-array 2 k bucket))] - (if i + i (when bucket (scan-array-equiv 2 k bucket))] + (if (some? i) true false))) @@ -12646,7 +12655,7 @@ reduces them without incurring seq initialization" (-dissoc [coll k] (let [h (hash k) bucket (unchecked-get hashobj h) - i (when bucket (scan-array 2 k bucket))] + i (when bucket (scan-array-equiv 2 k bucket))] (if (not i) coll ; key not found, return coll unchanged (let [new-hashobj (gobject/clone hashobj)] From a656ecabb3f8d6317dc473d229cc73c388d6ee10 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Mon, 4 Aug 2025 23:17:56 -0400 Subject: [PATCH 047/107] - test ObjMap & HashMap --- src/test/cljs/cljs/collections_test.cljs | 55 +++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index 6027a3acf..0645622e7 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -1168,10 +1168,63 @@ (is (every? keyword? (keys c))) (is (= (set [:a :b :c]) (set (keys c))))) (is (= (obj-map :a 1 :b 2 :c 3) - (obj-map :a 1 :b 2 :c 3)))) + (obj-map :a 1 :b 2 :c 3))) + (is (= (obj-map :a 1 :b 2) + (into (obj-map) [[:a 1] [:b 2]]))) + (is (= (merge-with + + (obj-map :a 1 :b 2) + (obj-map :a 1 :b 2)) + (into (obj-map) [[:a 2] [:b 4]]))) + (is (= (transient (obj-map :a 1 :b 2)) + (obj-map :a 1 :b 2)))) + +(deftest test-hash-map + (let [a (simple-hash-map)] + (is (empty? a)) + (is (zero? (count a)))) + (let [b (simple-hash-map :a 1)] + (is (not (empty? b))) + (is (== 1 (count b)))) + (let [c (simple-hash-map :a 1 :b 2 :c 3)] + (is (== 3 (count c))) + (is (= 1 (get c :a))) + (is (= 1 (:a c))) + (is (every? keyword? (keys c))) + (is (= (set [:a :b :c]) (set (keys c))))) + (is (= (simple-hash-map :a 1 :b 2 :c 3) + (simple-hash-map :a 1 :b 2 :c 3))) + (is (= (simple-hash-map :a 1 :b 2) + (into (simple-hash-map) [[:a 1] [:b 2]]))) + (is (= (merge-with + + (simple-hash-map :a 1 :b 2) + (simple-hash-map :a 1 :b 2)) + (into (simple-hash-map) [[:a 2] [:b 4]]))) + (is (= (transient (simple-hash-map :a 1 :b 2)) + (simple-hash-map :a 1 :b 2)))) (comment (run-tests) + (defn simple-group-by + [f coll] + (persistent! + (reduce + (fn [ret x] + (let [k (f x)] + (assoc! ret k (conj (get ret k (. Vector -EMPTY)) x)))) + (transient (. ObjMap -EMPTY)) coll))) + + (simple-group-by + :ns + '[{:ns foo :name woz} + {:ns bar :name goz} + {:ns bar :name baz} + {:ns foo :name naz}]) + + (get (simple-hash-map :a 1 :b 2 :c 3) :a) + + (#'scan-array-equiv 2 :a + (unchecked-get (. (simple-hash-map :a 1 :b 2 :c 3) -hashobj) (hash :a))) + ) From 4de7a718bf3fe77ce37959e94ecb8dfbcca28a54 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 07:59:11 -0400 Subject: [PATCH 048/107] - fix simple hash-map --- src/main/cljs/cljs/core.cljs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index d31f5ec9f..4dace1f59 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12472,7 +12472,7 @@ reduces them without incurring seq initialization" (-kv-reduce coll (fn [ret k v] (-assoc ret k v)) - (. HashMap -EMPTY)) + (simple-hash-map k v)) meta)))) (-contains-key? [coll k] (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] @@ -12628,11 +12628,12 @@ reduces them without incurring seq initialization" (-assoc [coll k v] (let [h (hash k) bucket (unchecked-get hashobj h)] - (if bucket + (if (some? bucket) (let [new-bucket (aclone bucket) - new-hashobj (gobject/clone hashobj)] + new-hashobj (gobject/clone hashobj) + i (scan-array-equiv 2 k new-bucket)] (aset new-hashobj h new-bucket) - (if-let [i (scan-array-equiv 2 k new-bucket)] + (if (some? i) (do ; found key, replace (aset new-bucket (inc i) v) @@ -12641,7 +12642,8 @@ reduces them without incurring seq initialization" ; did not find key, append (.push new-bucket k v) (HashMap. meta (inc count) new-hashobj nil)))) - (let [new-hashobj (gobject/clone hashobj)] ; did not find bucket + (let [new-hashobj (gobject/clone hashobj)] + ; did not find bucket (unchecked-set new-hashobj h (array k v)) (HashMap. meta (inc count) new-hashobj nil))))) (-contains-key? [coll k] @@ -12656,15 +12658,16 @@ reduces them without incurring seq initialization" (let [h (hash k) bucket (unchecked-get hashobj h) i (when bucket (scan-array-equiv 2 k bucket))] - (if (not i) - coll ; key not found, return coll unchanged + (if (some? i) (let [new-hashobj (gobject/clone hashobj)] (if (> 3 (alength bucket)) (js-delete new-hashobj h) (let [new-bucket (aclone bucket)] (.splice new-bucket i 2) (unchecked-set new-hashobj h new-bucket))) - (HashMap. meta (dec count) new-hashobj nil))))) + (HashMap. meta (dec count) new-hashobj nil)) + ; key not found, return coll unchanged + coll))) IFn (-invoke [coll k] From 3ceb397c750915fb48f01fff9d41d85ecdd0665e Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 08:00:01 -0400 Subject: [PATCH 049/107] - add toString methods --- src/main/cljs/cljs/core.cljs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 4dace1f59..52499bcd0 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12249,6 +12249,10 @@ reduces them without incurring seq initialization" ;;; Vector (deftype Vector [meta array ^:mutable __hash] + Object + (toString [coll] + (pr-str* coll)) + IWithMeta (-with-meta [coll meta] (Vector. meta array __hash)) @@ -12414,6 +12418,10 @@ reduces them without incurring seq initialization" (recur (+ i incr))))))) (deftype ObjMap [meta keys strobj ^:mutable __hash] + Object + (toString [coll] + (pr-str* coll)) + IWithMeta (-with-meta [coll meta] (ObjMap. meta keys strobj __hash)) @@ -12573,6 +12581,10 @@ reduces them without incurring seq initialization" ; collisions. A bucket is an array of alternating keys (not their hashes) and ; vals. (deftype HashMap [meta count hashobj ^:mutable __hash] + Object + (toString [coll] + (pr-str* coll)) + IWithMeta (-with-meta [coll meta] (HashMap. meta count hashobj __hash)) @@ -12716,6 +12728,10 @@ reduces them without incurring seq initialization" out))) (deftype Set [meta hash-map ^:mutable __hash] + Object + (toString [coll] + (pr-str* coll)) + IWithMeta (-with-meta [coll meta] (Set. meta hash-map __hash)) From bc0ebad57f52214bd641f2e15d025d484f5ddf54 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 08:00:45 -0400 Subject: [PATCH 050/107] - cleanup collections test --- src/test/cljs/cljs/collections_test.cljs | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index 0645622e7..be8c240ee 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -1200,31 +1200,10 @@ (simple-hash-map :a 1 :b 2)) (into (simple-hash-map) [[:a 2] [:b 4]]))) (is (= (transient (simple-hash-map :a 1 :b 2)) - (simple-hash-map :a 1 :b 2)))) + (simple-hash-map :a 1 :b 2)))) (comment (run-tests) - (defn simple-group-by - [f coll] - (persistent! - (reduce - (fn [ret x] - (let [k (f x)] - (assoc! ret k (conj (get ret k (. Vector -EMPTY)) x)))) - (transient (. ObjMap -EMPTY)) coll))) - - (simple-group-by - :ns - '[{:ns foo :name woz} - {:ns bar :name goz} - {:ns bar :name baz} - {:ns foo :name naz}]) - - (get (simple-hash-map :a 1 :b 2 :c 3) :a) - - (#'scan-array-equiv 2 :a - (unchecked-get (. (simple-hash-map :a 1 :b 2 :c 3) -hashobj) (hash :a))) - ) From fea514f6d44be85e6f15f8f342b27d9e5697c021 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 08:01:18 -0400 Subject: [PATCH 051/107] - add lite collections assertions, cleanup --- src/test/cljs/cljs/lite_collections_test.cljs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/cljs/cljs/lite_collections_test.cljs b/src/test/cljs/cljs/lite_collections_test.cljs index 474099617..976a44c74 100644 --- a/src/test/cljs/cljs/lite_collections_test.cljs +++ b/src/test/cljs/cljs/lite_collections_test.cljs @@ -7,11 +7,13 @@ ; You must not remove this notice, or any other, from this software. (ns cljs.lite-collections-test - (:require [cljs.test :refer-macros [deftest testing is are run-tests]])) + (:require [cljs.test :refer [deftest testing is]])) -;; NOTE: ** this name space must be tested with :lite-mode true ** +;; NOTE: ** this namespace must be tested with :lite-mode true ** (deftest test-obj-map (let [a (. ObjMap -EMPTY) b {}] - (is (identical? a b)))) \ No newline at end of file + (is (identical? a b))) + (let [a {:foo 1}] + (is (== 1 (:foo a))))) \ No newline at end of file From 5e99038d9ce9e5d0a02fbebde89435508cb97d97 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 08:03:49 -0400 Subject: [PATCH 052/107] - add lite test action --- .github/workflows/test.yaml | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e98aa8818..4420e9d0b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -59,6 +59,63 @@ jobs: /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc builds/out-adv/core-advanced-test.js | tee test-out.txt grep -qxF '0 failures, 0 errors.' test-out.txt + # Lite Tests + lite-test: + name: Lite Tests + runs-on: macos-14 + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - uses: DeLaGuardo/setup-clojure@3.1 + with: + tools-deps: '1.10.1.763' + + - name: Cache maven + uses: actions/cache@v4 + env: + cache-name: cache-maven + with: + path: ~/.m2 + key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/deps.edn') }} + restore-keys: | + ${{ runner.os }}-${{ env.cache-name }}- + + - name: Cache gitlibs + uses: actions/cache@v4 + env: + cache-name: cache-gitlibs + with: + path: ~/.gitlibs + key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/deps.edn') }} + restore-keys: | + ${{ runner.os }}-${{ env.cache-name }}- + + # - name: Cache JSC + # uses: actions/cache@v4 + # env: + # cache-name: cache-jsc + # with: + # path: WebKit + # key: ${{ runner.os }}-jsc + # restore-keys: | + # ${{ runner.os }}-jsc + + - name: Build tests + run: clojure -M:lite.test.build + + # - name: Install JSC + # run: ./ci/install_jsc.sh + + - name: Run tests + run: | + /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc builds/out-lite/lite-test.js | tee test-out.txt + grep -qxF '0 failures, 0 errors.' test-out.txt + # Runtime Tests runtime-windows-test: name: Runtime Windows Tests From 665619090fa97a968733fbfa0b0feee1484b3537 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 08:35:48 -0400 Subject: [PATCH 053/107] - :elide-to-string compiler flag --- src/main/clojure/cljs/analyzer.cljc | 3 +++ src/main/clojure/cljs/closure.clj | 3 ++- src/main/clojure/cljs/core.cljc | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/clojure/cljs/analyzer.cljc b/src/main/clojure/cljs/analyzer.cljc index 87733cf05..ceebbe973 100644 --- a/src/main/clojure/cljs/analyzer.cljc +++ b/src/main/clojure/cljs/analyzer.cljc @@ -497,6 +497,9 @@ (defn lite-mode? [] (get-in @env/*compiler* [:options :lite-mode])) +(defn elide-to-string? [] + (get-in @env/*compiler* [:options :elide-to-string])) + #?(:clj (defmacro with-warning-handlers [handlers & body] `(binding [*cljs-warning-handlers* ~handlers] diff --git a/src/main/clojure/cljs/closure.clj b/src/main/clojure/cljs/closure.clj index 5dc7db1a3..550fd68d5 100644 --- a/src/main/clojure/cljs/closure.clj +++ b/src/main/clojure/cljs/closure.clj @@ -211,7 +211,8 @@ :watch :watch-error-fn :watch-fn :install-deps :process-shim :rename-prefix :rename-prefix-namespace :closure-variable-map-in :closure-property-map-in :closure-variable-map-out :closure-property-map-out :stable-names :ignore-js-module-exts :opts-cache :aot-cache :elide-strict :fingerprint :spec-skip-macros - :nodejs-rt :target-fn :deps-cmd :bundle-cmd :global-goog-object&array :node-modules-dirs :lite-mode}) + :nodejs-rt :target-fn :deps-cmd :bundle-cmd :global-goog-object&array :node-modules-dirs :lite-mode + :elide-to-string}) (def string->charset {"iso-8859-1" StandardCharsets/ISO_8859_1 diff --git a/src/main/clojure/cljs/core.cljc b/src/main/clojure/cljs/core.cljc index 70ef0d267..b326a3fa6 100644 --- a/src/main/clojure/cljs/core.cljc +++ b/src/main/clojure/cljs/core.cljc @@ -1511,7 +1511,7 @@ ;; Elide all toString methods in :lite-mode (remove (core/fn [[f]] - (core/and (ana/lite-mode?) (core/= 'toString f)))) + (core/and (ana/elide-to-string?) (core/= 'toString f)))) (map (core/fn [[f & meths :as form]] (core/let [[f meths] (if (vector? (first meths)) From 515edb49a01e869e91d8a37e295f3cfd1c9331f8 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 22:02:55 -0400 Subject: [PATCH 054/107] - (.-length array) -> (alength array) - add missing -contains-key? method to Vector --- src/main/cljs/cljs/core.cljs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 52499bcd0..36c611b19 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12261,11 +12261,11 @@ reduces them without incurring seq initialization" IStack (-peek [coll] - (let [count (.-length array)] + (let [count (alength array)] (when (> count 0) (aget array (dec count))))) (-pop [coll] - (if (> (.-length array) 0) + (if (> (alength array) 0) (let [new-array (aclone array)] (. new-array (pop)) (Vector. meta new-array nil)) @@ -12289,24 +12289,24 @@ reduces them without incurring seq initialization" ISeqable (-seq [coll] - (when (> (.-length array) 0) + (when (> (alength array) 0) (let [vector-seq (fn vector-seq [i] (lazy-seq - (when (< i (.-length array)) + (when (< i (alength array)) (cons (aget array i) (vector-seq (inc i))))))] (vector-seq 0)))) ICounted - (-count [coll] (.-length array)) + (-count [coll] (alength array)) IIndexed (-nth [coll n] - (if (and (<= 0 n) (< n (.-length array))) + (if (and (<= 0 n) (< n (alength array))) (aget array n) - #_(throw (js/Error. (str "No item " n " in vector of length " (.-length array)))))) + #_(throw (js/Error. (str "No item " n " in vector of length " (alength array)))))) (-nth [coll n not-found] - (if (and (<= 0 n) (< n (.-length array))) + (if (and (<= 0 n) (< n (alength array))) (aget array n) not-found)) @@ -12319,6 +12319,11 @@ reduces them without incurring seq initialization" (let [new-array (aclone array)] (aset new-array k v) (Vector. meta new-array nil))) + (-contains-key? [coll k] + (if (integer? k) + (and (<= 0 k) (< k (alength array))) + false)) + IVector (-assoc-n [coll n val] (-assoc coll n val)) From 652cda9f91f9ddc91b4405eb16eabea0161829e9 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 22:13:34 -0400 Subject: [PATCH 055/107] - simple-vector needs to clone the underlying array --- src/main/cljs/cljs/core.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 36c611b19..255c2c9a2 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12360,7 +12360,7 @@ reduces them without incurring seq initialization" (defn simple-vector [& args] (if (and (instance? IndexedSeq args) (zero? (.-i args))) - (.fromArray Vector (.-arr args) (not (array? (.-arr args)))) + (.fromArray Vector (aclone (.-arr args))) (Vector. nil (into-array args) nil))) (defn simple-vec From a9a1d0cd095e239c76a24dfc20e332d4898cd649 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 22:24:06 -0400 Subject: [PATCH 056/107] - fix Vector -lookup --- src/main/cljs/cljs/core.cljs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 255c2c9a2..a295e87c7 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12311,8 +12311,13 @@ reduces them without incurring seq initialization" not-found)) ILookup - (-lookup [coll k] (-nth coll k nil)) - (-lookup [coll k not-found] (-nth coll k not-found)) + (-lookup [coll k] + (when (number? k) + (-nth coll k nil))) + (-lookup [coll k not-found] + (if (number? k) + (-nth coll k not-found) + not-found)) IAssociative (-assoc [coll k v] From 428618b3444b1581bde74d6831b9853a679eeb96 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 5 Aug 2025 22:37:33 -0400 Subject: [PATCH 057/107] - fix Vector -assoc, check key type --- src/main/cljs/cljs/core.cljs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index a295e87c7..3d5eeccd3 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12321,9 +12321,11 @@ reduces them without incurring seq initialization" IAssociative (-assoc [coll k v] - (let [new-array (aclone array)] - (aset new-array k v) - (Vector. meta new-array nil))) + (if (number? k) + (let [new-array (aclone array)] + (aset new-array k v) + (Vector. meta new-array nil)) + (throw (js/Error. "Vector's key for assoc must be a number.")))) (-contains-key? [coll k] (if (integer? k) (and (<= 0 k) (< k (alength array))) From bf2c2fefce56528663606bd536c270ca5461032e Mon Sep 17 00:00:00 2001 From: David Nolen Date: Wed, 6 Aug 2025 06:42:35 -0400 Subject: [PATCH 058/107] - add simple set test --- src/test/cljs/cljs/collections_test.cljs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index be8c240ee..7561c55e6 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -1178,7 +1178,7 @@ (is (= (transient (obj-map :a 1 :b 2)) (obj-map :a 1 :b 2)))) -(deftest test-hash-map +(deftest test-simple-hash-map (let [a (simple-hash-map)] (is (empty? a)) (is (zero? (count a)))) @@ -1202,6 +1202,12 @@ (is (= (transient (simple-hash-map :a 1 :b 2)) (simple-hash-map :a 1 :b 2)))) +(deftest test-simple-set + (is (= #{1 2 3} #{1 2 3})) + (is (= 3 (count #{1 2 3}))) + (let [x #{1 2 3}] + (is (every? #(contains? x %) [1 2 3])))) + (comment (run-tests) From 20a32cbde31ece933795920c40ff96fa7efda988 Mon Sep 17 00:00:00 2001 From: David Nolen Date: Mon, 11 Aug 2025 21:23:18 -0400 Subject: [PATCH 059/107] - fix -count on sets --- src/main/cljs/cljs/core.cljs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 3d5eeccd3..484ff593a 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12769,10 +12769,16 @@ reduces them without incurring seq initialization" (-hash [coll] (caching-hash coll hash-unordered-coll __hash)) ISeqable - (-seq [coll] (keys hash-map)) + (-seq [coll] + (let [xs (-seq hash-map)] + (when (some? xs) + (prim-seq (.map (.-arr xs) (fn [kv] (-key kv))))))) ICounted - (-count [coll] (-count (-seq coll))) + (-count [coll] + (let [xs (-seq coll)] + (when (some? xs) + (-count xs)))) ILookup (-lookup [coll v] From 265474b70b4b440895f38b96f4232d1fa3e28d1a Mon Sep 17 00:00:00 2001 From: David Nolen Date: Mon, 11 Aug 2025 21:49:10 -0400 Subject: [PATCH 060/107] - -iterator impl for lite maps --- src/main/cljs/cljs/core.cljs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 484ff593a..25aaec8b4 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12557,6 +12557,13 @@ reduces them without incurring seq initialization" (-dissoc! [coll key] (-dissoc coll key)) + IIterable + (-iterator [coll] + (let [xs (-seq coll)] + (if (some? xs) + (-iterator xs) + (nil-iter)))) + IPrintWithWriter (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) @@ -12717,6 +12724,13 @@ reduces them without incurring seq initialization" (-dissoc! [coll key] (-dissoc coll key)) + IIterable + (-iterator [coll] + (let [xs (-seq coll)] + (if (some? xs) + (-iterator xs) + (nil-iter)))) + IPrintWithWriter (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) From be48b1879f5f5f27bf3b88f81f922c2cf33f846c Mon Sep 17 00:00:00 2001 From: David Nolen Date: Mon, 11 Aug 2025 22:34:38 -0400 Subject: [PATCH 061/107] - add simple-map-entry tests --- src/test/cljs/cljs/collections_test.cljs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index 7561c55e6..680fe24f6 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -1208,6 +1208,12 @@ (let [x #{1 2 3}] (is (every? #(contains? x %) [1 2 3])))) +(deftest test-simple-map-entry + (is (= (simple-map-entry :foo 1) + (MapEntry. :foo 1 nil))) + (is (= (hash (simple-map-entry :foo 1)) + (hash (MapEntry. :foo 1 nil))))) + (comment (run-tests) From 4f042fb3c57a69eab59e531ed1bbe65dddebb41e Mon Sep 17 00:00:00 2001 From: David Nolen Date: Mon, 11 Aug 2025 22:42:58 -0400 Subject: [PATCH 062/107] - another assertion --- src/test/cljs/cljs/collections_test.cljs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index 680fe24f6..b5c5248e0 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -1206,7 +1206,9 @@ (is (= #{1 2 3} #{1 2 3})) (is (= 3 (count #{1 2 3}))) (let [x #{1 2 3}] - (is (every? #(contains? x %) [1 2 3])))) + (is (every? #(contains? x %) [1 2 3]))) + (is (= (simple-set [[3 4] [1 2] [5 6]]) + (into #{} [[3 4] [1 2] [5 6]])))) (deftest test-simple-map-entry (is (= (simple-map-entry :foo 1) From 4879df11fa959f41f8e6141bf894912537bfd96b Mon Sep 17 00:00:00 2001 From: David Nolen Date: Mon, 11 Aug 2025 22:59:04 -0400 Subject: [PATCH 063/107] - try hashing a vector, not hashing properly in CI is very weird --- src/main/cljs/cljs/core.cljs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 25aaec8b4..4b36ca9c6 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10378,6 +10378,10 @@ reduces them without incurring seq initialization" (defn- simple-map-entry [k v] (reify + ICounted + (-count [coll] 2) + IHash + (-hash [coll] (hash-ordered-coll [k v])) IEquiv (-equiv [coll other] (equiv-sequential coll other)) IVector From 650fe98b7efd97ab73c890b71ab1a87ab4e5dfdd Mon Sep 17 00:00:00 2001 From: David Nolen Date: Tue, 12 Aug 2025 06:46:19 -0400 Subject: [PATCH 064/107] - Vector, throw if out of bounds --- src/main/cljs/cljs/core.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 4b36ca9c6..4ca9e2b3c 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12308,7 +12308,7 @@ reduces them without incurring seq initialization" (-nth [coll n] (if (and (<= 0 n) (< n (alength array))) (aget array n) - #_(throw (js/Error. (str "No item " n " in vector of length " (alength array)))))) + (throw (js/Error. (str "No item " n " in vector of length " (alength array)))))) (-nth [coll n not-found] (if (and (<= 0 n) (< n (alength array))) (aget array n) @@ -12317,7 +12317,7 @@ reduces them without incurring seq initialization" ILookup (-lookup [coll k] (when (number? k) - (-nth coll k nil))) + (-nth coll k))) (-lookup [coll k not-found] (if (number? k) (-nth coll k not-found) From 813e65a181d7f56a244c8a09eae623f660d895fe Mon Sep 17 00:00:00 2001 From: David Nolen Date: Wed, 27 Aug 2025 11:58:40 -0400 Subject: [PATCH 065/107] simple vector missing IKVReduce & IComparable impls --- src/main/cljs/cljs/core.cljs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 4ca9e2b3c..c3f1999f7 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12345,6 +12345,23 @@ reduces them without incurring seq initialization" (-reduce [v f start] (array-reduce array f start)) + IKVReduce + (-kv-reduce [v f init] + (let [len (alength array)] + (loop [i 0 init init] + (if (< i len) + (let [init (f init i (aget array i))] + (if (reduced? init) + @init + (recur (inc i) init))) + init)))) + + IComparable + (-compare [x y] + (if (vector? y) + (compare-indexed x y) + (throw (js/Error. "Cannot compare with Vector")))) + IFn (-invoke [coll k] (-lookup coll k)) From db9b5a41e71c54300238ed13812cbea8d78004ba Mon Sep 17 00:00:00 2001 From: David Nolen Date: Sat, 30 Aug 2025 17:04:50 -0400 Subject: [PATCH 066/107] fix simple vector hash --- src/main/cljs/cljs/core.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index c3f1999f7..a1247c051 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12289,7 +12289,7 @@ reduces them without incurring seq initialization" (-equiv [coll other] (equiv-sequential coll other)) IHash - (-hash [coll] (hash-coll coll)) + (-hash [coll] (hash-ordered-coll coll)) ISeqable (-seq [coll] From ba118da6a903caf5626285d47db052fca612bb8b Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 6 Sep 2025 18:21:38 -0400 Subject: [PATCH 067/107] one more failing cljs.core-test around map entries - sanity check eq / hash between simple-map-entry and MapEntry - go ahead and update cljs/lite-test-runner to run cljs.core-test --- src/test/cljs/cljs/lite_collections_test.cljs | 15 ++++++++++++++- src/test/cljs/lite_test_runner.cljs | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/test/cljs/cljs/lite_collections_test.cljs b/src/test/cljs/cljs/lite_collections_test.cljs index 976a44c74..c6ab0e34b 100644 --- a/src/test/cljs/cljs/lite_collections_test.cljs +++ b/src/test/cljs/cljs/lite_collections_test.cljs @@ -16,4 +16,17 @@ b {}] (is (identical? a b))) (let [a {:foo 1}] - (is (== 1 (:foo a))))) \ No newline at end of file + (is (== 1 (:foo a))))) + +(deftest test-simple-map-entry-eq-hash + (is (= (simple-map-entry 1 2) + (MapEntry. 1 2 nil))) + (is (== (hash (simple-map-entry 1 2)) + (hash (MapEntry. 1 2 nil))))) + +(comment + + (require '[cljs.lite-collections-test] :reload) + (cljs.test/run-tests) + +) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index baa7b0435..a7de39e7e 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -8,6 +8,7 @@ (ns lite-test-runner (:require [cljs.test :refer-macros [run-tests]] + [cljs.core-test] [cljs.lite-collections-test])) (set! *print-newline* false) @@ -19,4 +20,5 @@ (run-tests 'cljs.lite-collections-test + 'cljs.core-test ) From 838046a72517381d00001e0d39df98f51ad68076 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 6 Sep 2025 18:29:20 -0400 Subject: [PATCH 068/107] - add working test - add failing case in the comments --- src/test/cljs/cljs/lite_collections_test.cljs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/cljs/cljs/lite_collections_test.cljs b/src/test/cljs/cljs/lite_collections_test.cljs index c6ab0e34b..4e26edcf9 100644 --- a/src/test/cljs/cljs/lite_collections_test.cljs +++ b/src/test/cljs/cljs/lite_collections_test.cljs @@ -24,9 +24,17 @@ (is (== (hash (simple-map-entry 1 2)) (hash (MapEntry. 1 2 nil))))) +(deftest test-simple-set-with-set + (is (= (simple-set []) (set []))) + (is (= (set []) (simple-set [])))) + (comment (require '[cljs.lite-collections-test] :reload) (cljs.test/run-tests) + ;; failing + (= (simple-set [(simple-map-entry 1 2)]) + (set [(MapEntry. 1 2 nil)])) + ) From 82d2bac7386c1ddf6c7839fca2a60f9ed401a07b Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 6 Sep 2025 19:09:18 -0400 Subject: [PATCH 069/107] simple-map-entry missing ISequential marker protocol - add test assertions for the cases considered along the way to the problem - cljs.core-test now passing under :lite-mode true --- src/main/cljs/cljs/core.cljs | 1 + src/test/cljs/cljs/lite_collections_test.cljs | 25 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index a1247c051..c1d19f12c 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10382,6 +10382,7 @@ reduces them without incurring seq initialization" (-count [coll] 2) IHash (-hash [coll] (hash-ordered-coll [k v])) + ISequential IEquiv (-equiv [coll other] (equiv-sequential coll other)) IVector diff --git a/src/test/cljs/cljs/lite_collections_test.cljs b/src/test/cljs/cljs/lite_collections_test.cljs index 4e26edcf9..aee495f46 100644 --- a/src/test/cljs/cljs/lite_collections_test.cljs +++ b/src/test/cljs/cljs/lite_collections_test.cljs @@ -19,22 +19,29 @@ (is (== 1 (:foo a))))) (deftest test-simple-map-entry-eq-hash + (is (= (simple-map-entry 1 2) (simple-map-entry 1 2))) (is (= (simple-map-entry 1 2) - (MapEntry. 1 2 nil))) + (MapEntry. 1 2 nil))) (is (== (hash (simple-map-entry 1 2)) (hash (MapEntry. 1 2 nil))))) (deftest test-simple-set-with-set (is (= (simple-set []) (set []))) - (is (= (set []) (simple-set [])))) + (is (= (set []) (simple-set []))) + (is (= (simple-set [(simple-map-entry 1 2)]) + (set [(MapEntry. 1 2 nil)])))) -(comment +(deftest test-hash-map-simple-map-entry + (let [m (assoc (. HashMap -EMPTY) (simple-map-entry 1 2) true)] + (is (contains? m (simple-map-entry 1 2))))) + +(deftest test-simple-set-simple-map-entry + (let [a (simple-set [(simple-map-entry 1 2)])] + (is (contains? a (simple-map-entry 1 2))))) - (require '[cljs.lite-collections-test] :reload) - (cljs.test/run-tests) +(comment - ;; failing - (= (simple-set [(simple-map-entry 1 2)]) - (set [(MapEntry. 1 2 nil)])) + (require '[cljs.lite-collections-test]) + (cljs.test/run-tests) -) + ) From c865113f679d775f20d4262c4c321159acc67b9c Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 11 Sep 2025 20:50:36 -0400 Subject: [PATCH 070/107] add ICloneable to light types, more tests --- src/main/cljs/cljs/core.cljs | 12 +++++++++ src/test/cljs/lite_test_runner.cljs | 39 ++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index c1d19f12c..c2f9b9d2a 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12261,6 +12261,9 @@ reduces them without incurring seq initialization" IWithMeta (-with-meta [coll meta] (Vector. meta array __hash)) + ICloneable + (-clone [coll] (Vector. meta array __hash)) + IMeta (-meta [coll] meta) @@ -12462,6 +12465,9 @@ reduces them without incurring seq initialization" IMeta (-meta [coll] meta) + ICloneable + (-clone [coll] (ObjMap. meta keys strobj __hash)) + ICollection (-conj [coll entry] (if (vector? entry) @@ -12632,6 +12638,9 @@ reduces them without incurring seq initialization" IMeta (-meta [coll] meta) + ICloneable + (-clone [coll] (HashMap. meta count hashobj __hash)) + ICollection (-conj [coll entry] (if (vector? entry) @@ -12786,6 +12795,9 @@ reduces them without incurring seq initialization" IMeta (-meta [coll] meta) + ICloneable + (-clone [coll] (Set. meta hash-map __hash)) + ICollection (-conj [coll o] (Set. meta (assoc hash-map o nil) nil)) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index a7de39e7e..45e0734b4 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -8,6 +8,25 @@ (ns lite-test-runner (:require [cljs.test :refer-macros [run-tests]] + [cljs.apply-test] + [cljs.primitives-test] + [cljs.destructuring-test] + [cljs.new-new-test] + [cljs.seqs-test] + [cljs.hashing-test] + [cljs.interop-test] + [cljs.iterator-test] + [cljs.binding-test] + [cljs.ns-test] + [clojure.set-test] + [clojure.string-test] + [clojure.data-test] + [clojure.datafy-test] + [clojure.edn-test] + [clojure.walk-test] + [clojure.math-test] + [cljs.macro-test] + [cljs.letfn-test] [cljs.core-test] [cljs.lite-collections-test])) @@ -19,6 +38,24 @@ (enable-console-print!)) (run-tests - 'cljs.lite-collections-test + 'cljs.apply-test + 'cljs.primitives-test + 'cljs.destructuring-test + 'cljs.new-new-test + #_'cljs.seqs-test ;; rseq Vector + #_'cljs.hashing-test + #_'cljs.interop-test ;; ES6 stuff + #_'cljs.iterator-test + 'cljs.binding-test + 'cljs.ns-test + 'clojure.set-test + 'clojure.string-test + #_'clojure.data-test ;; 1 failure #object[Error Error: No item 1 in vector of length 1] + 'clojure.datafy-test + 'clojure.edn-test + 'clojure.walk-test + 'clojure.math-test + 'cljs.macro-test 'cljs.core-test + 'cljs.lite-collections-test ) From eb226c55bd6e3541d25a7da6fa73bb66484f0031 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 11 Sep 2025 20:57:39 -0400 Subject: [PATCH 071/107] more passing (and failing tests) --- src/test/cljs/lite_test_runner.cljs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 45e0734b4..5eca88681 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -27,6 +27,19 @@ [clojure.math-test] [cljs.macro-test] [cljs.letfn-test] + [foo.ns-shadow-test] + [cljs.top-level] + [cljs.reducers-test] + [cljs.keyword-test] + [cljs.import-test] + [cljs.ns-test.foo] + [cljs.syntax-quote-test] + [cljs.pprint] + [cljs.pprint-test] + [cljs.spec-test] + [cljs.specials-test] + [cljs.spec.test-test] + [cljs.clojure-alias-test] [cljs.core-test] [cljs.lite-collections-test])) @@ -56,6 +69,20 @@ 'clojure.walk-test 'clojure.math-test 'cljs.macro-test + 'cljs.letfn-test + 'foo.ns-shadow-test + 'cljs.top-level + #_'cljs.reducers-test ;; missing IReduce, IKVReduce + 'cljs.keyword-test + 'cljs.import-test + 'cljs.ns-test.foo + 'cljs.syntax-quote-test + 'cljs.pprint + 'cljs.pprint-test + #_'cljs.spec-test ;; this one is strange + 'cljs.specials-test + 'cljs.spec.test-test + 'cljs.clojure-alias-test 'cljs.core-test 'cljs.lite-collections-test ) From d5cca13f7c0c7f402b7a749575a7cce126478a47 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 11 Sep 2025 21:29:59 -0400 Subject: [PATCH 072/107] IAssociative for simple-map-entry, more tests --- src/main/cljs/cljs/core.cljs | 5 +++++ src/test/cljs/lite_test_runner.cljs | 30 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index c2f9b9d2a..7dbfdf027 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10391,6 +10391,11 @@ reduces them without incurring seq initialization" 0 (simple-map-entry x v) 1 (simple-map-entry k x) (throw (js/Error. "Index out of bounds")))) + IAssociative + (-assoc [node k v] + (-assoc-n node k v)) + (-contains-key? [node k] + (or (== k 0) (== k 1))) IMapEntry (-key [_] k) (-val [_] v) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 5eca88681..1d1e7f6dc 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -12,6 +12,7 @@ [cljs.primitives-test] [cljs.destructuring-test] [cljs.new-new-test] + [cljs.printing-test] [cljs.seqs-test] [cljs.hashing-test] [cljs.interop-test] @@ -40,6 +41,20 @@ [cljs.specials-test] [cljs.spec.test-test] [cljs.clojure-alias-test] + ;; [cljs.metadata-test] + ;; [cljs.npm-deps-test] + [cljs.other-functions-test] + [cljs.predicates-test] + ;; [cljs.tagged-literals-test] + [cljs.test-test] + [static.core-test] + [cljs.recur-test] + [cljs.array-access-test] + [cljs.inference-test] + ;; [cljs.walk-test] + [cljs.repl-test] + ;; [cljs.extend-to-native-test] + [cljs.var-test] [cljs.core-test] [cljs.lite-collections-test])) @@ -54,6 +69,7 @@ 'cljs.apply-test 'cljs.primitives-test 'cljs.destructuring-test + 'cljs.printing-test 'cljs.new-new-test #_'cljs.seqs-test ;; rseq Vector #_'cljs.hashing-test @@ -83,6 +99,20 @@ 'cljs.specials-test 'cljs.spec.test-test 'cljs.clojure-alias-test + #_'cljs.metadata-test ;; another RSeq one + #_'cljs.npm-deps-test + 'cljs.other-functions-test + 'cljs.predicates-test + #_'cljs.tagged-literals-test ;; duplicate keys in ObjMap/HashMap + 'cljs.test-test + 'static.core-test + 'cljs.recur-test + 'cljs.array-access-test + 'cljs.inference-test + #_'cljs.walk-test ;; not sure here + 'cljs.repl-test + #_'cljs.extend-to-native-test ;; this one breaks a bunchof things + 'cljs.var-test 'cljs.core-test 'cljs.lite-collections-test ) From f6f9a60afdcdde93c5e4427579a08db91f56e46c Mon Sep 17 00:00:00 2001 From: davidnolen Date: Thu, 11 Sep 2025 21:52:41 -0400 Subject: [PATCH 073/107] bring over the other tests, even if commented, reader test, parse test --- src/test/cljs/lite_test_runner.cljs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 1d1e7f6dc..be5ebf012 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -14,10 +14,15 @@ [cljs.new-new-test] [cljs.printing-test] [cljs.seqs-test] + ;; [cljs.collections-test] [cljs.hashing-test] + [cljs.core-test] + ;; [cljs.chunked-seq] ;; doesn't exist in :lite-mode [cljs.interop-test] [cljs.iterator-test] + [cljs.reader-test] [cljs.binding-test] + [cljs.parse-test] [cljs.ns-test] [clojure.set-test] [clojure.string-test] @@ -41,6 +46,8 @@ [cljs.specials-test] [cljs.spec.test-test] [cljs.clojure-alias-test] + ;; [cljs.hash-map-test] + ;; [cljs.map-entry-test] ;; [cljs.metadata-test] ;; [cljs.npm-deps-test] [cljs.other-functions-test] @@ -55,7 +62,6 @@ [cljs.repl-test] ;; [cljs.extend-to-native-test] [cljs.var-test] - [cljs.core-test] [cljs.lite-collections-test])) (set! *print-newline* false) @@ -75,7 +81,9 @@ #_'cljs.hashing-test #_'cljs.interop-test ;; ES6 stuff #_'cljs.iterator-test + 'cljs.reader-test 'cljs.binding-test + 'cljs.parse-test 'cljs.ns-test 'clojure.set-test 'clojure.string-test From 7593b1143cd6d3b4806732793398c25f1ed721db Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 12 Sep 2025 09:09:02 -0400 Subject: [PATCH 074/107] Fix cljs.seq-test for :lite-mode - simple-map-entry: add ICollection impl - RSeq: can use `-count` in lastIndexOf - Vector: Object.indexOf and Object.lastIndexOf inlined, a very small size hit, better for perf - Vector: implement RSeq - Set (Lite): need to return 0 from -count - cljs.seqs-test: elide chunked-seq assertions from lite-mode tests - cljs.lite-test-runner: run cljs.seqs-test --- src/main/cljs/cljs/core.cljs | 47 ++++++++++++++++++++++++++--- src/test/cljs/cljs/seqs_test.cljs | 29 +++++++++--------- src/test/cljs/lite_test_runner.cljs | 2 +- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 7dbfdf027..1466cefa3 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -1768,7 +1768,7 @@ reduces them without incurring seq initialization" (indexOf [coll x start] (-indexOf coll x start)) (lastIndexOf [coll x] - (-lastIndexOf coll x (count coll))) + (-lastIndexOf coll x (-count coll))) (lastIndexOf [coll x start] (-lastIndexOf coll x start)) @@ -10396,6 +10396,9 @@ reduces them without incurring seq initialization" (-assoc-n node k v)) (-contains-key? [node k] (or (== k 0) (== k 1))) + ICollection + (-conj [coll x] + (Vector. nil #js [k v x] nil)) IMapEntry (-key [_] k) (-val [_] v) @@ -12262,6 +12265,36 @@ reduces them without incurring seq initialization" Object (toString [coll] (pr-str* coll)) + (equiv [coll other] + (-equiv coll other)) + (indexOf [coll x start] + (let [start (if (nil? start) 0 start) + len (-count coll)] + (if (>= start len) + -1 + (loop [idx (cond + (pos? start) start + (neg? start) (max 0 (+ start len)) + :else start)] + (if (< idx len) + (if (= (-nth coll idx) x) + idx + (recur (inc idx))) + -1))))) + (lastIndexOf [coll x start] + (let [start (if (nil? start) (alength array) start) + len (-count coll)] + (if (zero? len) + -1 + (loop [idx (cond + (pos? start) (min (dec len) start) + (neg? start) (+ len start) + :else start)] + (if (>= idx 0) + (if (= (-nth coll idx) x) + idx + (recur (dec idx))) + -1))))) IWithMeta (-with-meta [coll meta] (Vector. meta array __hash)) @@ -12344,10 +12377,15 @@ reduces them without incurring seq initialization" (and (<= 0 k) (< k (alength array))) false)) - IVector (-assoc-n [coll n val] (-assoc coll n val)) + IReversible + (-rseq [coll] + (let [cnt (alength array)] + (when (pos? cnt) + (RSeq. coll (dec cnt) nil)))) + IReduce (-reduce [v f] (array-reduce array f)) @@ -12830,8 +12868,9 @@ reduces them without incurring seq initialization" ICounted (-count [coll] (let [xs (-seq coll)] - (when (some? xs) - (-count xs)))) + (if (some? xs) + (-count xs) + 0))) ILookup (-lookup [coll v] diff --git a/src/test/cljs/cljs/seqs_test.cljs b/src/test/cljs/cljs/seqs_test.cljs index 9e43a7340..c48d1a12f 100644 --- a/src/test/cljs/cljs/seqs_test.cljs +++ b/src/test/cljs/cljs/seqs_test.cljs @@ -203,20 +203,21 @@ (is (= (.lastIndexOf (sequence (map inc) '(0 1 0 3 4)) 1) 2)))) (deftest test-chunked - (let [r (range 64) - v (into [] r)] - (testing "Testing Chunked Seqs" - (is (= (hash (seq v)) (hash (seq v)))) - (is (= 6 (reduce + (array-chunk (array 1 2 3))))) - (is (instance? ChunkedSeq (seq v))) - (is (= r (seq v))) - (is (= (map inc r) (map inc v))) - (is (= (filter even? r) (filter even? v))) - (is (= (filter odd? r) (filter odd? v))) - (is (= (concat r r r) (concat v v v))) - (is (satisfies? IReduce (seq v))) - (is (== 2010 (reduce + (nnext (nnext (seq v)))))) - (is (== 2020 (reduce + 10 (nnext (nnext (seq v))))))))) + (when-not LITE_MODE + (let [r (range 64) + v (into [] r)] + (testing "Testing Chunked Seqs" + (is (= (hash (seq v)) (hash (seq v)))) + (is (= 6 (reduce + (array-chunk (array 1 2 3))))) + (is (instance? ChunkedSeq (seq v))) + (is (= r (seq v))) + (is (= (map inc r) (map inc v))) + (is (= (filter even? r) (filter even? v))) + (is (= (filter odd? r) (filter odd? v))) + (is (= (concat r r r) (concat v v v))) + (is (satisfies? IReduce (seq v))) + (is (== 2010 (reduce + (nnext (nnext (seq v)))))) + (is (== 2020 (reduce + 10 (nnext (nnext (seq v)))))))))||||) (deftest test-778 (testing "Testing CLJS-778, -rest, -next RSeq" diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index be5ebf012..ad4bee462 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -77,7 +77,7 @@ 'cljs.destructuring-test 'cljs.printing-test 'cljs.new-new-test - #_'cljs.seqs-test ;; rseq Vector + 'cljs.seqs-test ;; rseq Vector #_'cljs.hashing-test #_'cljs.interop-test ;; ES6 stuff #_'cljs.iterator-test From db2d6237420f5923a7d744c369c9451fd61491bb Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 12 Sep 2025 19:21:51 -0400 Subject: [PATCH 075/107] remove RSeq comment --- src/test/cljs/lite_test_runner.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index ad4bee462..7cd6eb378 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -77,7 +77,7 @@ 'cljs.destructuring-test 'cljs.printing-test 'cljs.new-new-test - 'cljs.seqs-test ;; rseq Vector + 'cljs.seqs-test #_'cljs.hashing-test #_'cljs.interop-test ;; ES6 stuff #_'cljs.iterator-test From 591b5a87b0d1932a2b2f99ea56eeea3a02f3b20e Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 12 Sep 2025 20:21:08 -0400 Subject: [PATCH 076/107] missing declare Vector --- src/main/cljs/cljs/core.cljs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 1466cefa3..f2399dc77 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10376,6 +10376,8 @@ reduces them without incurring seq initialization" (implements? IMeta obj) (not (nil? (meta obj))))) +(declare Vector) + (defn- simple-map-entry [k v] (reify ICounted From 5845b89004d4ea7ea6b63fc7075af1e22dd7af03 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 12 Sep 2025 20:55:03 -0400 Subject: [PATCH 077/107] don't cross wires, only use Vector in simple-map-entry when LITE_MODE=true --- src/main/cljs/cljs/core.cljs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index f2399dc77..91b0b2abe 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10400,7 +10400,9 @@ reduces them without incurring seq initialization" (or (== k 0) (== k 1))) ICollection (-conj [coll x] - (Vector. nil #js [k v x] nil)) + (if ^boolean LITE_MODE + (Vector. nil #js [k v x] nil) + [k v x])) IMapEntry (-key [_] k) (-val [_] v) From 37255cd12cf9c2f0ee051c42dc1d467b9e56b4aa Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 12 Sep 2025 21:18:14 -0400 Subject: [PATCH 078/107] remove typos --- src/test/cljs/cljs/seqs_test.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/cljs/cljs/seqs_test.cljs b/src/test/cljs/cljs/seqs_test.cljs index c48d1a12f..babfae99d 100644 --- a/src/test/cljs/cljs/seqs_test.cljs +++ b/src/test/cljs/cljs/seqs_test.cljs @@ -217,7 +217,7 @@ (is (= (concat r r r) (concat v v v))) (is (satisfies? IReduce (seq v))) (is (== 2010 (reduce + (nnext (nnext (seq v)))))) - (is (== 2020 (reduce + 10 (nnext (nnext (seq v)))))))))||||) + (is (== 2020 (reduce + 10 (nnext (nnext (seq v)))))))))) (deftest test-778 (testing "Testing CLJS-778, -rest, -next RSeq" From b549ba5cc14c9e33457ba09977abc44cf5b8d7b8 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 13 Sep 2025 10:37:32 -0400 Subject: [PATCH 079/107] es6 interop tests passing - implement es6 collection compatibility - include cljs.intero-test in lite-test-runner --- src/main/cljs/cljs/core.cljs | 93 ++++++++++++++++++++++------ src/test/cljs/cljs/interop_test.cljs | 13 ++-- src/test/cljs/lite_test_runner.cljs | 2 +- 3 files changed, 84 insertions(+), 24 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 91b0b2abe..ea0691be3 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12432,6 +12432,8 @@ reduces them without incurring seq initialization" IPrintWithWriter (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "[" " " "]" opts coll))) +(es6-iterable PersistentVector) + (set! (. Vector -EMPTY) (Vector. nil (array) nil)) (set! (. Vector -fromArray) (fn [xs] (Vector. nil xs nil))) @@ -12501,19 +12503,38 @@ reduces them without incurring seq initialization" i (recur (+ i incr))))))) -(deftype ObjMap [meta keys strobj ^:mutable __hash] +(deftype ObjMap [meta strkeys strobj ^:mutable __hash] Object (toString [coll] (pr-str* coll)) + (keys [coll] + (es6-iterator + (prim-seq + (.map (.sort strkeys obj-map-compare-keys) + obj-map-key->keyword)))) + (entries [coll] + (es6-entries-iterator (-seq coll))) + (values [coll] + (es6-iterator + (prim-seq + (.map (.sort strkeys obj-map-compare-keys) + #(unchecked-get strobj %))))) + (has [coll k] + (contains? coll k)) + (get [coll k not-found] + (-lookup coll k not-found)) + (forEach [coll f] + (.forEach (.sort strkeys obj-map-compare-keys) + #(f (unchecked-get strobj %) (obj-map-key->keyword %)))) IWithMeta - (-with-meta [coll meta] (ObjMap. meta keys strobj __hash)) + (-with-meta [coll meta] (ObjMap. meta strkeys strobj __hash)) IMeta (-meta [coll] meta) ICloneable - (-clone [coll] (ObjMap. meta keys strobj __hash)) + (-clone [coll] (ObjMap. meta strkeys strobj __hash)) ICollection (-conj [coll entry] @@ -12532,20 +12553,20 @@ reduces them without incurring seq initialization" ISeqable (-seq [coll] - (when (pos? (alength keys)) + (when (pos? (alength strkeys)) (prim-seq - (.map (.sort keys obj-map-compare-keys) + (.map (.sort strkeys obj-map-compare-keys) #(simple-map-entry (obj-map-key->keyword %) (unchecked-get strobj %)))))) ICounted - (-count [coll] (alength keys)) + (-count [coll] (alength strkeys)) ILookup (-lookup [coll k] (-lookup coll k nil)) (-lookup [coll k not-found] (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) + (not (nil? (scan-array 1 k strkeys)))) (unchecked-get strobj k) not-found))) @@ -12553,12 +12574,12 @@ reduces them without incurring seq initialization" (-assoc [coll k v] (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] (if (string? k) - (if-not (nil? (scan-array 1 k keys)) - (let [new-strobj (obj-clone strobj keys)] + (if-not (nil? (scan-array 1 k strkeys)) + (let [new-strobj (obj-clone strobj strkeys)] (gobject/set new-strobj k v) - (ObjMap. meta keys new-strobj nil)) ;overwrite - (let [new-strobj (obj-clone strobj keys) ; append - new-keys (aclone keys)] + (ObjMap. meta strkeys new-strobj nil)) ;overwrite + (let [new-strobj (obj-clone strobj strkeys) ; append + new-keys (aclone strkeys)] (gobject/set new-strobj k v) (.push new-keys k) (ObjMap. meta new-keys new-strobj nil))) @@ -12572,7 +12593,7 @@ reduces them without incurring seq initialization" (-contains-key? [coll k] (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) + (not (nil? (scan-array 1 k strkeys)))) true false))) @@ -12580,13 +12601,13 @@ reduces them without incurring seq initialization" (-find [coll k] (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] (when (and (string? k) - (not (nil? (scan-array 1 k keys)))) + (not (nil? (scan-array 1 k strkeys)))) (MapEntry. k (unchecked-get strobj k) nil)))) IKVReduce (-kv-reduce [coll f init] - (let [len (alength keys)] - (loop [keys (.sort keys obj-map-compare-keys) + (let [len (alength strkeys)] + (loop [keys (.sort strkeys obj-map-compare-keys) init init] (if (seq keys) (let [k (first keys) @@ -12600,9 +12621,9 @@ reduces them without incurring seq initialization" (-dissoc [coll k] (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] (if (and (string? k) - (not (nil? (scan-array 1 k keys)))) - (let [new-keys (aclone keys) - new-strobj (obj-clone strobj keys)] + (not (nil? (scan-array 1 k strkeys)))) + (let [new-keys (aclone strkeys) + new-strobj (obj-clone strobj strkeys)] (.splice new-keys (scan-array 1 k new-keys) 1) (js-delete new-strobj k) (ObjMap. meta new-keys new-strobj nil)) @@ -12643,6 +12664,8 @@ reduces them without incurring seq initialization" (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) +(es6-iterable ObjMap) + (set! (. ObjMap -EMPTY) (ObjMap. nil (array) (js-obj) empty-ordered-hash)) (set! (. ObjMap -fromObject) (fn [ks obj] (ObjMap. nil ks obj nil))) @@ -12678,6 +12701,21 @@ reduces them without incurring seq initialization" Object (toString [coll] (pr-str* coll)) + (keys [coll] + (es6-iterator (map #(-key %) (-seq coll)))) + (entries [coll] + (es6-entries-iterator (-seq coll))) + (values [coll] + (es6-iterator (map #(-val %) (-key coll)))) + (has [coll k] + (contains? coll k)) + (get [coll k not-found] + (-lookup coll k not-found)) + (forEach [coll f] + (let [xs (-seq coll)] + (when-not (nil? xs) + (.forEach (.-arr xs) + #(f (-val %) (-key %)))))) IWithMeta (-with-meta [coll meta] (HashMap. meta count hashobj __hash)) @@ -12813,6 +12851,8 @@ reduces them without incurring seq initialization" (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) +(es6-iterable HashMap) + (set! (. HashMap -EMPTY) (HashMap. nil 0 (js-obj) empty-unordered-hash)) (set! (. HashMap -fromArrays) (fn [ks vs] @@ -12835,6 +12875,19 @@ reduces them without incurring seq initialization" Object (toString [coll] (pr-str* coll)) + (keys [coll] + (es6-iterator (-seq coll))) + (entries [coll] + (es6-set-entries-iterator (-seq coll))) + (values [coll] + (es6-iterator (-seq coll))) + (has [coll k] + (contains? coll k)) + (forEach [coll f] + (let [xs (-seq hash-map)] + (when (some? xs) + (.forEach (.-arr xs) + #(f (-val %) (-key %)))))) IWithMeta (-with-meta [coll meta] (Set. meta hash-map __hash)) @@ -12911,6 +12964,8 @@ reduces them without incurring seq initialization" IPrintWithWriter (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "#{" " " "}" opts coll))) +(es6-iterable Set) + (set! (. Set -EMPTY) (Set. nil (. HashMap -EMPTY) empty-unordered-hash)) (defn simple-set diff --git a/src/test/cljs/cljs/interop_test.cljs b/src/test/cljs/cljs/interop_test.cljs index ee158ec18..f736ea15c 100644 --- a/src/test/cljs/cljs/interop_test.cljs +++ b/src/test/cljs/cljs/interop_test.cljs @@ -14,12 +14,17 @@ (testing "Object equiv method" (is (.equiv :foo :foo)) (is (.equiv 'foo 'foo)) - (is (.equiv {:foo 1 :bar 2} {:foo 1 :bar 2})) + ;; .equiv is not a standard thing, primarily for interop + ;; in transit-js, probably not a concern for lite-mode users + (when-not LITE_MODE + (is (.equiv {:foo 1 :bar 2} {:foo 1 :bar 2}))) (is (.equiv [1 2 3] [1 2 3])) (is (.equiv '(1 2 3) '(1 2 3))) (is (.equiv (map inc [1 2 3]) (map inc [1 2 3]))) - (is (.equiv #{:cat :dog :bird} #{:cat :dog :bird})) - )) + ;; .equiv is not a standard thing, primarily for interop + ;; in transit-js, probably not a concern for lite-mode users + (when-not LITE_MODE + (is (.equiv #{:cat :dog :bird} #{:cat :dog :bird}))))) (deftest test-es6-interfaces (testing "ES6 collection interfaces" @@ -67,4 +72,4 @@ (is (#{:cat :bird :dog} (.-value (.next iter)))) (is (#{:cat :bird :dog} (.-value (.next iter)))) (is (.-done (.next iter))))) - )) \ No newline at end of file + )) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 7cd6eb378..ef94ff100 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -79,7 +79,7 @@ 'cljs.new-new-test 'cljs.seqs-test #_'cljs.hashing-test - #_'cljs.interop-test ;; ES6 stuff + 'cljs.interop-test ;; ES6 stuff #_'cljs.iterator-test 'cljs.reader-test 'cljs.binding-test From c103b37e9059190fc3dadeba0daac6cb509ce8e4 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 13 Sep 2025 13:35:34 -0400 Subject: [PATCH 080/107] fix cljs.reducers-test - add ObjMapIterator - implement ObjMap IIterable - implement HashMap -kv-reduce - run cljs.reducers-test --- src/main/cljs/cljs/core.cljs | 39 +++++++++++++++++++++++++++++ src/test/cljs/lite_test_runner.cljs | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index ea0691be3..1d207486e 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12503,6 +12503,15 @@ reduces them without incurring seq initialization" i (recur (+ i incr))))))) +(deftype ObjMapIterator [strkeys strobj ^:mutable i] + Object + (hasNext [_] + (< i (alength strkeys))) + (next [_] + (let [k (aget strkeys i)] + (set! i (inc i)) + (simple-map-entry (obj-map-key->keyword k) (unchecked-get strobj k))))) + (deftype ObjMap [meta strkeys strobj ^:mutable __hash] Object (toString [coll] @@ -12617,6 +12626,16 @@ reduces them without incurring seq initialization" (recur (rest keys) init))) init)))) + IIterable + (-iterator [coll] + (ObjMapIterator. strkeys strobj 0)) + + IReduce + (-reduce [coll f] + (iter-reduce coll f)) + (-reduce [coll f start] + (iter-reduce coll f start)) + IMap (-dissoc [coll k] (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] @@ -12847,6 +12866,26 @@ reduces them without incurring seq initialization" (-iterator xs) (nil-iter)))) + IKVReduce + (-kv-reduce [coll f init] + (let [hashes (.sort (js-keys hashobj)) + ilen (alength hashes)] + (loop [i 0 init init] + (if (< i ilen) + (let [bckt (unchecked-get hashobj (aget hashes i)) + jlen (alength bckt) + init (loop [j 0 init init] + (if (< j jlen) + (let [init (f init (aget bckt j) (aget bckt (inc j)))] + (if (reduced? init) + init + (recur (+ j 2) init))) + init))] + (if (reduced? init) + @init + (recur (inc i) init))) + init)))) + IPrintWithWriter (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index ef94ff100..a10808a15 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -96,7 +96,7 @@ 'cljs.letfn-test 'foo.ns-shadow-test 'cljs.top-level - #_'cljs.reducers-test ;; missing IReduce, IKVReduce + 'cljs.reducers-test ;; missing IReduce, IKVReduce 'cljs.keyword-test 'cljs.import-test 'cljs.ns-test.foo From a529a38bbe2389439e432c28062f65448d3db6ac Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 13 Sep 2025 14:07:09 -0400 Subject: [PATCH 081/107] remove duped IIterable for ObjMap --- src/main/cljs/cljs/core.cljs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 1d207486e..49cbbef57 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12672,13 +12672,6 @@ reduces them without incurring seq initialization" (-dissoc! [coll key] (-dissoc coll key)) - IIterable - (-iterator [coll] - (let [xs (-seq coll)] - (if (some? xs) - (-iterator xs) - (nil-iter)))) - IPrintWithWriter (-pr-writer [coll writer opts] (print-map coll pr-writer writer opts))) From 474bfecae59daa791e30dce8021786e8f2fc5152 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 13 Sep 2025 14:25:08 -0400 Subject: [PATCH 082/107] fix ObjMap/EMPTY hash --- src/main/cljs/cljs/core.cljs | 2 +- src/test/cljs/lite_test_runner.cljs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 49cbbef57..d2ccd6305 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12678,7 +12678,7 @@ reduces them without incurring seq initialization" (es6-iterable ObjMap) -(set! (. ObjMap -EMPTY) (ObjMap. nil (array) (js-obj) empty-ordered-hash)) +(set! (. ObjMap -EMPTY) (ObjMap. nil (array) (js-obj) empty-unordered-hash)) (set! (. ObjMap -fromObject) (fn [ks obj] (ObjMap. nil ks obj nil))) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index a10808a15..75ec10dcb 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -78,7 +78,7 @@ 'cljs.printing-test 'cljs.new-new-test 'cljs.seqs-test - #_'cljs.hashing-test + 'cljs.hashing-test 'cljs.interop-test ;; ES6 stuff #_'cljs.iterator-test 'cljs.reader-test From 681a50773fa59730d9b5bb18854bfffee8358db3 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 13 Sep 2025 14:50:11 -0400 Subject: [PATCH 083/107] less opaque reporting from walk test, rename test --- src/test/cljs/cljs/walk_test.cljs | 45 ++++++++++++++++--------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/test/cljs/cljs/walk_test.cljs b/src/test/cljs/cljs/walk_test.cljs index 9f28ebf08..fb3476f53 100644 --- a/src/test/cljs/cljs/walk_test.cljs +++ b/src/test/cljs/cljs/walk_test.cljs @@ -51,28 +51,29 @@ (defmethod get-comparator PersistentTreeSet [o] (get-comparator (.-tree-map o))) -(deftest walk - "Checks that walk returns the correct result and type of collection" - (let [colls ['(1 2 3) - [1 2 3] - #{1 2 3} - (sorted-set-by > 1 2 3) - {:a 1, :b 2, :c 3} - (sorted-map-by > 1 10, 2 20, 3 30) - (->Foo 1 2 3) - (map->Foo {:a 1 :b 2 :c 3 :extra 4})]] - (doseq [c colls] - (let [walked (w/walk identity identity c)] - (is (= c walked)) - ;;(is (= (type c) (type walked))) - (if (map? c) - (is (= (w/walk #(update-in % [1] inc) #(reduce + (vals %)) c) - (reduce + (map (comp inc val) c)))) - (is (= (w/walk inc #(reduce + %) c) - (reduce + (map inc c))))) - (when (or (instance? PersistentTreeMap c) - (instance? PersistentTreeSet c)) - (is (= (get-comparator c) (get-comparator walked)))))))) +(deftest test-walk + (testing "Test that walk returns the correct result\n" + (let [colls ['(1 2 3) + [1 2 3] + #{1 2 3} + (sorted-set-by > 1 2 3) + {:a 1, :b 2, :c 3} + (sorted-map-by > 1 10, 2 20, 3 30) + (->Foo 1 2 3) + (map->Foo {:a 1 :b 2 :c 3 :extra 4})]] + (doseq [c colls] + (testing (str "Walking ... " c) + (let [walked (w/walk identity identity c)] + (is (= c walked)) + ;;(is (= (type c) (type walked))) + (if (map? c) + (is (= (w/walk #(update-in % [1] inc) #(reduce + (vals %)) c) + (reduce + (map (comp inc val) c)))) + (is (= (w/walk inc #(reduce + %) c) + (reduce + (map inc c))))) + (when (or (instance? PersistentTreeMap c) + (instance? PersistentTreeSet c)) + (is (= (get-comparator c) (get-comparator walked)))))))))) (deftest walk-mapentry "Checks that walk preserves the MapEntry type. See CLJS-2909." From 1452729f667883a88579b2601a7087fa3ce360f8 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 13 Sep 2025 16:01:04 -0400 Subject: [PATCH 084/107] missing collection protocol method for simple-map-entry - add ILookup - add IFind - add lite-collection-test for these cases - NOTE: it wasn't clear until we we got to testing that we would need all this stuff. Perhaps we just want to use MapEntry, this does create a dependence on Vector, but I think simple-map-entry was created to avoid the connection to PV before I had done all work to emit the simple vector type under :lite-mode --- src/main/cljs/cljs/core.cljs | 11 ++++++++++- src/test/cljs/cljs/lite_collections_test.cljs | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index d2ccd6305..d5288f10c 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10412,7 +10412,16 @@ reduces them without incurring seq initialization" (-nth [_ i] (case i, 0 k, 1 v, (throw (js/Error. "Index out of bounds")))) (-nth [_ i not-found] - (case i, 0 k, 1 v, not-found)))) + (case i, 0 k, 1 v, not-found)) + ILookup + (-lookup [coll k] (-nth coll k nil)) + (-lookup [coll k not-found] (-nth coll k not-found)) + IFind + (-find [node x] + (case x + 0 (simple-map-entry 0 k) + 1 (simple-map-entry 1 v) + nil)))) (defn- pr-writer-impl [obj writer opts] diff --git a/src/test/cljs/cljs/lite_collections_test.cljs b/src/test/cljs/cljs/lite_collections_test.cljs index aee495f46..183f0460f 100644 --- a/src/test/cljs/cljs/lite_collections_test.cljs +++ b/src/test/cljs/cljs/lite_collections_test.cljs @@ -39,9 +39,19 @@ (let [a (simple-set [(simple-map-entry 1 2)])] (is (contains? a (simple-map-entry 1 2))))) +(deftest test-simple-map-entry-lookups + (let [me (simple-map-entry :foo "bar")] + (is (= :foo (get me 0))) + (is (= "bar" (get me 1))) + (is (= [0 :foo] + (vec (find (simple-map-entry :foo "bar") 0)))) + (is (= [:foo "b"] + (vec (update (simple-map-entry :foo "bar") 1 first)) + (vec (update-in (simple-map-entry :foo "bar") [1] first)))))) + (comment - (require '[cljs.lite-collections-test]) + (require '[cljs.lite-collections-test] :reload) (cljs.test/run-tests) ) From d97804e225e7e9d081b6aecdcf121ff8c929043b Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 13 Sep 2025 16:04:57 -0400 Subject: [PATCH 085/107] test cljs.walk-test now that simple-map-entry is fixed --- src/test/cljs/lite_test_runner.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 75ec10dcb..683ff10cc 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -58,7 +58,7 @@ [cljs.recur-test] [cljs.array-access-test] [cljs.inference-test] - ;; [cljs.walk-test] + [cljs.walk-test] [cljs.repl-test] ;; [cljs.extend-to-native-test] [cljs.var-test] @@ -117,7 +117,7 @@ 'cljs.recur-test 'cljs.array-access-test 'cljs.inference-test - #_'cljs.walk-test ;; not sure here + 'cljs.walk-test ;; not sure here 'cljs.repl-test #_'cljs.extend-to-native-test ;; this one breaks a bunchof things 'cljs.var-test From 48d63400e96d306214bcaad9b2516d239812e53c Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sat, 13 Sep 2025 16:21:31 -0400 Subject: [PATCH 086/107] remove stray comment about cljs.walk-test --- src/test/cljs/lite_test_runner.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 683ff10cc..f6dd43c6d 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -117,7 +117,7 @@ 'cljs.recur-test 'cljs.array-access-test 'cljs.inference-test - 'cljs.walk-test ;; not sure here + 'cljs.walk-test 'cljs.repl-test #_'cljs.extend-to-native-test ;; this one breaks a bunchof things 'cljs.var-test From 429d7ca3ed81a187372c9f9701647ccf709fd816 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 21 Sep 2025 13:25:41 -0400 Subject: [PATCH 087/107] Vector ILookup and IFn issues - -lookup needs to use nil so it doesn't throw - -invoke should not take extra parameter, just copy PersistentVector implementation - clojure.data-test passing now --- src/main/cljs/cljs/core.cljs | 8 ++++---- src/test/cljs/lite_test_runner.cljs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index d5288f10c..5c775b714 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12372,7 +12372,7 @@ reduces them without incurring seq initialization" ILookup (-lookup [coll k] (when (number? k) - (-nth coll k))) + (-nth coll k nil))) (-lookup [coll k not-found] (if (number? k) (-nth coll k not-found) @@ -12424,9 +12424,9 @@ reduces them without incurring seq initialization" IFn (-invoke [coll k] - (-lookup coll k)) - (-invoke [coll k not-found] - (-lookup coll k not-found)) + (if (number? k) + (-nth coll k) + (throw (js/Error. "Key must be integer")))) IEditableCollection (-as-transient [coll] diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index f6dd43c6d..acf6de00f 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -87,7 +87,7 @@ 'cljs.ns-test 'clojure.set-test 'clojure.string-test - #_'clojure.data-test ;; 1 failure #object[Error Error: No item 1 in vector of length 1] + 'clojure.data-test 'clojure.datafy-test 'clojure.edn-test 'clojure.walk-test From 5ad974d45e1e82ce260accf4b6f040ebbfb0a260 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 21 Sep 2025 20:45:21 -0400 Subject: [PATCH 088/107] Vector IIterable impl --- src/main/cljs/cljs/core.cljs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 5c775b714..871afa62b 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12274,6 +12274,15 @@ reduces them without incurring seq initialization" ;;; Vector +(deftype VectorIterator [arr ^:mutable i] + Object + (hasNext [_] + (< i (alength arr))) + (next [_] + (let [x (aget arr i)] + (set! i (inc i)) + x))) + (deftype Vector [meta array ^:mutable __hash] Object (toString [coll] @@ -12438,6 +12447,10 @@ reduces them without incurring seq initialization" (-persistent! [coll] coll) + IIterable + (-iterator [coll] + (VectorIterator. array 0)) + IPrintWithWriter (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "[" " " "]" opts coll))) From 75c82ed6951108ba0410b0cdc0d057e36302b001 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 21 Sep 2025 21:27:33 -0400 Subject: [PATCH 089/107] Set IIterable impl, cljs.iterator-test now passing --- src/main/cljs/cljs/core.cljs | 7 +++++++ src/test/cljs/lite_test_runner.cljs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 871afa62b..364acbf3e 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -13015,6 +13015,13 @@ reduces them without incurring seq initialization" (-invoke [coll k not-found] (-lookup coll k not-found)) + IIterable + (-iterator [coll] + (let [xs (-seq coll)] + (if (some? xs) + (-iterator xs) + (nil-iter)))) + IPrintWithWriter (-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "#{" " " "}" opts coll))) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index acf6de00f..75628960e 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -80,7 +80,7 @@ 'cljs.seqs-test 'cljs.hashing-test 'cljs.interop-test ;; ES6 stuff - #_'cljs.iterator-test + 'cljs.iterator-test 'cljs.reader-test 'cljs.binding-test 'cljs.parse-test From 366110da50b8a86cf95dbd74fe73d1d41f369db9 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 21 Sep 2025 22:03:38 -0400 Subject: [PATCH 090/107] generate more detailed error in the metadata tests --- src/test/cljs/cljs/metadata_test.cljc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test/cljs/cljs/metadata_test.cljc b/src/test/cljs/cljs/metadata_test.cljc index b22c79612..8f5e99411 100644 --- a/src/test/cljs/cljs/metadata_test.cljc +++ b/src/test/cljs/cljs/metadata_test.cljc @@ -109,11 +109,15 @@ (seq-interface-tests (seq [])) (seq-interface-tests (rseq []))) (testing "Medium" - (seq-interface-tests (seq [0 1 2 3])) - (seq-interface-tests (rseq [0 1 2 3]))) + (testing "seq" + (seq-interface-tests (seq [0 1 2 3]))) + (testing "rseq" + (seq-interface-tests (rseq [0 1 2 3])))) (testing "Large" - (seq-interface-tests (seq (vec (range 100)))) - (seq-interface-tests (rseq (vec (range 100)))))) + (testing "seq" + (seq-interface-tests (seq (vec (range 100))))) + (testing "rseq" + (seq-interface-tests (rseq (vec (range 100))))))) (testing "PersistentHashSet" (testing "Empty" From 9434c0afebf1ddd5bf812ba507a3db5f3f145217 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 21 Sep 2025 22:16:23 -0400 Subject: [PATCH 091/107] make lite_test.edn easier to compare with test.edn, npm-deps-tests passing --- resources/lite_test.edn | 19 +++++++++++++++++-- src/test/cljs/lite_test_runner.cljs | 4 ++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/resources/lite_test.edn b/resources/lite_test.edn index 11b3d3f9f..44508575d 100644 --- a/resources/lite_test.edn +++ b/resources/lite_test.edn @@ -1,13 +1,28 @@ {:optimizations :advanced :main lite-test-runner - :lite-mode true :output-to "builds/out-lite/lite-test.js" :output-dir "builds/out-lite" :output-wrapper true :verbose true :compiler-stats true :parallel-build true + :npm-deps {:lodash "4.17.4"} :closure-warnings {:non-standard-jsdoc :off :global-this :off} + :install-deps true :language-out :es5 + :foreign-libs + [{:file "src/test/cljs/calculator_global.js" + :provides ["calculator"] + :global-exports {calculator Calculator}} + {:file "src/test/cljs/es6_dep.js" + :module-type :es6 + :provides ["es6_calc"]} + {:file "src/test/cljs/calculator.js" + :module-type :commonjs + :provides ["calculator"]} + {:file "src/test/cljs/es6_default_hello.js" + :provides ["es6_default_hello"] + :module-type :es6}] :pseudo-names true - :pretty-print true} + :pretty-print true + :lite-mode true} diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 75628960e..e955ca428 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -49,7 +49,7 @@ ;; [cljs.hash-map-test] ;; [cljs.map-entry-test] ;; [cljs.metadata-test] - ;; [cljs.npm-deps-test] + [cljs.npm-deps-test] [cljs.other-functions-test] [cljs.predicates-test] ;; [cljs.tagged-literals-test] @@ -108,7 +108,7 @@ 'cljs.spec.test-test 'cljs.clojure-alias-test #_'cljs.metadata-test ;; another RSeq one - #_'cljs.npm-deps-test + 'cljs.npm-deps-test 'cljs.other-functions-test 'cljs.predicates-test #_'cljs.tagged-literals-test ;; duplicate keys in ObjMap/HashMap From 9549fff7edf1697d871908d8c3dc779eb3a48633 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Mon, 22 Sep 2025 20:39:31 -0400 Subject: [PATCH 092/107] remove stale comment --- src/test/cljs/lite_test_runner.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index e955ca428..2d0241ed5 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -96,7 +96,7 @@ 'cljs.letfn-test 'foo.ns-shadow-test 'cljs.top-level - 'cljs.reducers-test ;; missing IReduce, IKVReduce + 'cljs.reducers-test 'cljs.keyword-test 'cljs.import-test 'cljs.ns-test.foo From 13d7f8c3bbb9007c6dd9fe5e56b95e606824ae34 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Mon, 22 Sep 2025 21:12:21 -0400 Subject: [PATCH 093/107] cljs.metadata-test passing - Vector uncovered a very old LazySeq bug where it returned meta after empty. Don't change for now, different path for `:lite-mode` - Use (.-EMPTY PersistentVector) instead [] for PersistentQueue --- src/main/cljs/cljs/core.cljs | 10 ++++++++-- src/test/cljs/cljs/seqs_test.cljs | 6 +++++- src/test/cljs/lite_test_runner.cljs | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 364acbf3e..590cff3e5 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -3614,7 +3614,13 @@ reduces them without incurring seq initialization" (-conj [coll o] (cons o coll)) IEmptyableCollection - (-empty [coll] (-with-meta (.-EMPTY List) meta)) + (-empty [coll] + ;; MAYBE FIXME: :lite-mode testing uncovered a very old bug, empty on seq + ;; should discared the metadata, we change the behavior in LITE_MODE for now + ;; to avoid a breaking change + (if-not ^boolean LITE_MODE + (-with-meta (.-EMPTY List) meta) + (.-EMPTY List))) ISequential IEquiv @@ -6528,7 +6534,7 @@ reduces them without incurring seq initialization" ICounted (-count [coll] count)) -(set! (.-EMPTY PersistentQueue) (PersistentQueue. nil 0 nil [] empty-ordered-hash)) +(set! (.-EMPTY PersistentQueue) (PersistentQueue. nil 0 nil (.-EMPTY PersistentVector) empty-ordered-hash)) (es6-iterable PersistentQueue) diff --git a/src/test/cljs/cljs/seqs_test.cljs b/src/test/cljs/cljs/seqs_test.cljs index babfae99d..00d648fa1 100644 --- a/src/test/cljs/cljs/seqs_test.cljs +++ b/src/test/cljs/cljs/seqs_test.cljs @@ -40,7 +40,11 @@ (testing "lazy seq" (is (seq? e-lazy-seq)) (is (empty? e-lazy-seq)) - (is (= {:b :c} (meta e-lazy-seq))))) + ;; MAYBE FIXME: this is a bad test, discovered from :lite-mode work + (if-not ^boolean LITE_MODE + (is (= {:b :c} (meta e-lazy-seq))) + ;; LITE_MODE has the correct behavior + (is (nil? (meta e-lazy-seq)))))) (let [e-list (empty '^{:b :c} (1 2 3))] (testing "list" (is (seq? e-list)) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 2d0241ed5..090d08ed2 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -48,7 +48,7 @@ [cljs.clojure-alias-test] ;; [cljs.hash-map-test] ;; [cljs.map-entry-test] - ;; [cljs.metadata-test] + [cljs.metadata-test] [cljs.npm-deps-test] [cljs.other-functions-test] [cljs.predicates-test] @@ -107,7 +107,7 @@ 'cljs.specials-test 'cljs.spec.test-test 'cljs.clojure-alias-test - #_'cljs.metadata-test ;; another RSeq one + 'cljs.metadata-test 'cljs.npm-deps-test 'cljs.other-functions-test 'cljs.predicates-test From bf26779b54cd4f5c236fdf3c049299320f09748f Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 26 Sep 2025 22:00:54 -0400 Subject: [PATCH 094/107] cljs.tagged-literals-test passing --- src/test/cljs/lite_test_runner.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 090d08ed2..ee1966bda 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -52,7 +52,7 @@ [cljs.npm-deps-test] [cljs.other-functions-test] [cljs.predicates-test] - ;; [cljs.tagged-literals-test] + [cljs.tagged-literals-test] [cljs.test-test] [static.core-test] [cljs.recur-test] @@ -111,7 +111,7 @@ 'cljs.npm-deps-test 'cljs.other-functions-test 'cljs.predicates-test - #_'cljs.tagged-literals-test ;; duplicate keys in ObjMap/HashMap + 'cljs.tagged-literals-test 'cljs.test-test 'static.core-test 'cljs.recur-test From 130670966b6e9e9a4a541b70b553aeb7196567f7 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 26 Sep 2025 22:09:02 -0400 Subject: [PATCH 095/107] cljs.extend-to-native-test passing --- src/test/cljs/lite_test_runner.cljs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index ee1966bda..9c483f791 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -60,9 +60,9 @@ [cljs.inference-test] [cljs.walk-test] [cljs.repl-test] - ;; [cljs.extend-to-native-test] - [cljs.var-test] - [cljs.lite-collections-test])) + [cljs.lite-collections-test] + [cljs.extend-to-native-test] + [cljs.var-test])) (set! *print-newline* false) @@ -79,6 +79,7 @@ 'cljs.new-new-test 'cljs.seqs-test 'cljs.hashing-test + 'cljs.core-test 'cljs.interop-test ;; ES6 stuff 'cljs.iterator-test 'cljs.reader-test @@ -119,8 +120,7 @@ 'cljs.inference-test 'cljs.walk-test 'cljs.repl-test - #_'cljs.extend-to-native-test ;; this one breaks a bunchof things - 'cljs.var-test - 'cljs.core-test 'cljs.lite-collections-test + 'cljs.extend-to-native-test ;; this one breaks a bunchof things + 'cljs.var-test ) From 75afb2feaba2e3de6d76b1b3ad8ec296e861bf99 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 28 Sep 2025 21:51:07 -0400 Subject: [PATCH 096/107] IFn impl for simple-map-entry --- src/main/cljs/cljs/core.cljs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 590cff3e5..2139fcfe2 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10427,7 +10427,12 @@ reduces them without incurring seq initialization" (case x 0 (simple-map-entry 0 k) 1 (simple-map-entry 1 v) - nil)))) + nil)) + IFn + (-invoke [coll k] + (-nth coll k)) + (-invoke [coll k not-found] + (-nth coll k not-found)))) (defn- pr-writer-impl [obj writer opts] From fcfe7f9dab84e3d1bef8a8fef10b8aeb0cc4fec6 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 28 Sep 2025 22:13:30 -0400 Subject: [PATCH 097/107] cljs.spec-test passing - missing Set specize* impl - run cljs.spec-test - remove stale comment about cljs.extend-to-native-test --- src/main/cljs/cljs/spec/alpha.cljs | 4 ++++ src/test/cljs/lite_test_runner.cljs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/spec/alpha.cljs b/src/main/cljs/cljs/spec/alpha.cljs index c88079f5f..b348d9928 100644 --- a/src/main/cljs/cljs/spec/alpha.cljs +++ b/src/main/cljs/cljs/spec/alpha.cljs @@ -148,6 +148,10 @@ (specize* ([s] (spec-impl s s nil nil)) ([s form] (spec-impl form s nil nil))) + Set + (specize* ([s] (spec-impl s s nil nil)) + ([s form] (spec-impl form s nil nil))) + default (specize* ([o] diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 9c483f791..83541adac 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -104,7 +104,7 @@ 'cljs.syntax-quote-test 'cljs.pprint 'cljs.pprint-test - #_'cljs.spec-test ;; this one is strange + 'cljs.spec-test 'cljs.specials-test 'cljs.spec.test-test 'cljs.clojure-alias-test @@ -121,6 +121,6 @@ 'cljs.walk-test 'cljs.repl-test 'cljs.lite-collections-test - 'cljs.extend-to-native-test ;; this one breaks a bunchof things + 'cljs.extend-to-native-test 'cljs.var-test ) From e6a6073d53c73f6a91f119cc660104ff1f3977de Mon Sep 17 00:00:00 2001 From: davidnolen Date: Mon, 29 Sep 2025 20:31:28 -0400 Subject: [PATCH 098/107] Vector IDrop impl, elide another chunked-seq test in LITE_MODE --- src/main/cljs/cljs/core.cljs | 7 +++++++ src/test/cljs/cljs/collections_test.cljs | 6 ++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index 2139fcfe2..f069ca535 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12436,6 +12436,13 @@ reduces them without incurring seq initialization" (recur (inc i) init))) init)))) + IDrop + (-drop [v n] + (let [cnt (alength array)] + (if (< n cnt) + (prim-seq array n) + nil))) + IComparable (-compare [x y] (if (vector? y) diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index b5c5248e0..08dfe6840 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -193,8 +193,10 @@ (is (not (counted? (range)))) (is (counted? (range 0 10 1))) (is (not (counted? (range 0.1 10 1)))) - (is (chunked-seq? (range 0 10 1))) - (is (chunked-seq? (range 0.1 10 1))) + ;; no chunked seqs in :lite-mode + (when-not ^boolean LITE_MODE + (is (chunked-seq? (range 0 10 1))) + (is (chunked-seq? (range 0.1 10 1)))) (is (= (range 0.5 8 1.2) '(0.5 1.7 2.9 4.1 5.3 6.5 7.7))) (is (= (range 0.5 -4 -2) '(0.5 -1.5 -3.5))) (testing "IDrop" From e3cd744491b81ac8711d8de32eb4dbe009d98db4 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Mon, 29 Sep 2025 20:51:03 -0400 Subject: [PATCH 099/107] Vector, Set -with-meta should return coll if meta identical elide another impl specific LITE_MODE test add missing transiet impls to Vector --- src/main/cljs/cljs/core.cljs | 23 +++++++++++++++++++++-- src/test/cljs/cljs/collections_test.cljs | 5 +++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index f069ca535..fb0645f9c 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12330,7 +12330,10 @@ reduces them without incurring seq initialization" -1))))) IWithMeta - (-with-meta [coll meta] (Vector. meta array __hash)) + (-with-meta [coll new-meta] + (if (identical? new-meta meta) + coll + (Vector. new-meta array __hash))) ICloneable (-clone [coll] (Vector. meta array __hash)) @@ -12465,6 +12468,19 @@ reduces them without incurring seq initialization" (-persistent! [coll] coll) + ITransientAssociative + (-assoc! [tcoll key val] + (-assoc-n! tcoll key val)) + + ITransientVector + (-assoc-n! [tcoll key val] + (if (number? key) + (-assoc-n tcoll key val) + (throw (js/Error. "Vector's key for assoc! must be a number.")))) + + (-pop! [tcoll] + (-pop tcoll)) + IIterable (-iterator [coll] (VectorIterator. array 0)) @@ -12962,7 +12978,10 @@ reduces them without incurring seq initialization" #(f (-val %) (-key %)))))) IWithMeta - (-with-meta [coll meta] (Set. meta hash-map __hash)) + (-with-meta [coll new-meta] + (if (identical? new-meta meta) + coll + (Set. new-meta hash-map __hash))) IMeta (-meta [coll] meta) diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index 08dfe6840..7d7036bda 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -1019,8 +1019,9 @@ (deftest test-cljs-2128 (testing "Subvec iteration" - (testing "Subvec over PersistentVector uses RangedIterator" - (is (instance? RangedIterator (-iterator (subvec [0 1 2 3] 1 3))))) + (when-not ^boolean LITE_MODE + (testing "Subvec over PersistentVector uses RangedIterator" + (is (instance? RangedIterator (-iterator (subvec [0 1 2 3] 1 3)))))) (testing "Subvec over other vectors uses naive SeqIter" (is (instance? SeqIter (-iterator (subvec (->CustomVectorThing [0 1 2 3]) 1 3)))))) (testing "Subvec reduce" From fbd8bce47b513e4f58062420824df5b415f9e944 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Mon, 29 Sep 2025 20:59:36 -0400 Subject: [PATCH 100/107] 0.1 -> 0 etc. when calling -nth on vector --- src/main/cljs/cljs/core.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index fb0645f9c..fa92284df 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12385,11 +12385,11 @@ reduces them without incurring seq initialization" IIndexed (-nth [coll n] (if (and (<= 0 n) (< n (alength array))) - (aget array n) + (aget array (int n)) (throw (js/Error. (str "No item " n " in vector of length " (alength array)))))) (-nth [coll n not-found] (if (and (<= 0 n) (< n (alength array))) - (aget array n) + (aget array (int n)) not-found)) ILookup From f122ee6b5ef90869319ff3442fa4977c7f04fe20 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Mon, 29 Sep 2025 21:04:41 -0400 Subject: [PATCH 101/107] fix broken ObjMap -find --- src/main/cljs/cljs/core.cljs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index fa92284df..ef34ec974 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12664,10 +12664,10 @@ reduces them without incurring seq initialization" IFind (-find [coll k] - (let [k (if-not (keyword? k) k (keyword->obj-map-key k))] - (when (and (string? k) - (not (nil? (scan-array 1 k strkeys)))) - (MapEntry. k (unchecked-get strobj k) nil)))) + (let [k' (if-not (keyword? k) k (keyword->obj-map-key k))] + (when (and (string? k') + (not (nil? (scan-array 1 k' strkeys)))) + (MapEntry. k (unchecked-get strobj k') nil)))) IKVReduce (-kv-reduce [coll f init] From d1212bd095a4bc4bfa39517412e4f5876b914d14 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Mon, 29 Sep 2025 21:31:09 -0400 Subject: [PATCH 102/107] cljs.collection-test passing - Set needs to assoc value to underlying hashmap - Set needs to return the value in the underlying hashmap - skip a transient test we just don't support at the moment - run the collections test - :nodejs target for lite-test, easier to flip to :simple --- resources/lite_test.edn | 1 + src/main/cljs/cljs/core.cljs | 4 ++-- src/test/cljs/cljs/collections_test.cljs | 9 ++++++--- src/test/cljs/lite_test_runner.cljs | 3 ++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/resources/lite_test.edn b/resources/lite_test.edn index 44508575d..fef9afe67 100644 --- a/resources/lite_test.edn +++ b/resources/lite_test.edn @@ -9,6 +9,7 @@ :npm-deps {:lodash "4.17.4"} :closure-warnings {:non-standard-jsdoc :off :global-this :off} :install-deps true + :target :nodejs :language-out :es5 :foreign-libs [{:file "src/test/cljs/calculator_global.js" diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index ef34ec974..fa1317832 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -12991,7 +12991,7 @@ reduces them without incurring seq initialization" ICollection (-conj [coll o] - (Set. meta (assoc hash-map o nil) nil)) + (Set. meta (assoc hash-map o o) nil)) IEmptyableCollection (-empty [coll] (with-meta (. Set -EMPTY) meta)) @@ -13025,7 +13025,7 @@ reduces them without incurring seq initialization" (-lookup coll v nil)) (-lookup [coll v not-found] (if (-contains-key? hash-map v) - v + (-lookup hash-map v) not-found)) ISet diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index 7d7036bda..01701c51f 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -1127,9 +1127,12 @@ (next (chunk-cons (chunk b) nil)))))) (deftest test-cljs-3124 - (let [t (assoc! (transient []) 0 1)] - (persistent! t) - (is (= :fail (try (get t :a :not-found) (catch js/Error e :fail)))))) + ;; Doesn't work under :lite-mode because there are not + ;; separate transient types for now + (when-not ^boolean LITE_MODE + (let [t (assoc! (transient []) 0 1)] + (persistent! t) + (is (= :fail (try (get t :a :not-found) (catch js/Error e :fail))))))) (deftest test-cljs-3317 (testing "persistent vector invoke matches clojure" diff --git a/src/test/cljs/lite_test_runner.cljs b/src/test/cljs/lite_test_runner.cljs index 83541adac..95313b3f8 100644 --- a/src/test/cljs/lite_test_runner.cljs +++ b/src/test/cljs/lite_test_runner.cljs @@ -14,7 +14,7 @@ [cljs.new-new-test] [cljs.printing-test] [cljs.seqs-test] - ;; [cljs.collections-test] + [cljs.collections-test] [cljs.hashing-test] [cljs.core-test] ;; [cljs.chunked-seq] ;; doesn't exist in :lite-mode @@ -78,6 +78,7 @@ 'cljs.printing-test 'cljs.new-new-test 'cljs.seqs-test + 'cljs.collections-test 'cljs.hashing-test 'cljs.core-test 'cljs.interop-test ;; ES6 stuff From 7d8ee19570f53053a040fc7eb99d925809efeea5 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Mon, 29 Sep 2025 21:47:48 -0400 Subject: [PATCH 103/107] remove :nodejs target, add code size tests for lite mode --- resources/lite_test.edn | 1 - src/test/clojure/cljs/build_api_tests.clj | 32 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/resources/lite_test.edn b/resources/lite_test.edn index fef9afe67..44508575d 100644 --- a/resources/lite_test.edn +++ b/resources/lite_test.edn @@ -9,7 +9,6 @@ :npm-deps {:lodash "4.17.4"} :closure-warnings {:non-standard-jsdoc :off :global-this :off} :install-deps true - :target :nodejs :language-out :es5 :foreign-libs [{:file "src/test/cljs/calculator_global.js" diff --git a/src/test/clojure/cljs/build_api_tests.clj b/src/test/clojure/cljs/build_api_tests.clj index a1a2f3871..492e0de9f 100644 --- a/src/test/clojure/cljs/build_api_tests.clj +++ b/src/test/clojure/cljs/build_api_tests.clj @@ -759,6 +759,22 @@ (build/build (build/inputs (io/file inputs "trivial/core4.cljs")) opts cenv) (is (< (.length out-file) 32768)))) +(deftest lite-mode-vector-code-size-ratchet + (testing ":lite-mode + :elide-to-string, should cut output size for [] in 1/2" + (let [out (.getPath (io/file (test/tmp-dir) "trivial-output-vector-test-out")) + out-file (io/file out "main.js") + {:keys [inputs opts]} {:inputs (str (io/file "src" "test" "cljs_build")) + :opts {:main 'trivial.core4 + :output-dir out + :output-to (.getPath out-file) + :lite-mode true + :elide-to-string true + :optimizations :advanced}} + cenv (env/default-compiler-env)] + (test/delete-out-files out) + (build/build (build/inputs (io/file inputs "trivial/core4.cljs")) opts cenv) + (is (< (.length out-file) 16384))))) + (deftest trivial-output-size-map (let [out (.getPath (io/file (test/tmp-dir) "trivial-output-map-test-out")) out-file (io/file out "main.js") @@ -772,6 +788,22 @@ (build/build (build/inputs (io/file inputs "trivial/core5.cljs")) opts cenv) (is (< (.length out-file) 92160)))) +(deftest lite-mode-map-code-size-ratchet + (testing ":lite-mode + :elide-to-string, should cut output size for {} in 1/3" + (let [out (.getPath (io/file (test/tmp-dir) "trivial-output-map-test-out")) + out-file (io/file out "main.js") + {:keys [inputs opts]} {:inputs (str (io/file "src" "test" "cljs_build")) + :opts {:main 'trivial.core5 + :output-dir out + :output-to (.getPath out-file) + :lite-mode true + :elide-to-string true + :optimizations :advanced}} + cenv (env/default-compiler-env)] + (test/delete-out-files out) + (build/build (build/inputs (io/file inputs "trivial/core5.cljs")) opts cenv) + (is (< (.length out-file) 32768))))) + (deftest cljs-3255-nil-inputs-build (let [out (.getPath (io/file (test/tmp-dir) "3255-test-out")) out-file (io/file out "main.js") From f0e76c3249a26143128881b32b5348f370861325 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 3 Oct 2025 20:41:00 -0400 Subject: [PATCH 104/107] cleanup - remove simple-map-entry, more trouble than it's worth hassle, and does really save any spaced since need to implement everything to pass tests - add trivial.core6 size ratchet --- src/main/cljs/cljs/core.cljs | 65 +++---------------- src/test/cljs/cljs/collections_test.cljs | 6 -- src/test/cljs/cljs/lite_collections_test.cljs | 27 +------- src/test/cljs_build/trivial/core6.cljs | 3 + src/test/clojure/cljs/build_api_tests.clj | 16 +++++ 5 files changed, 28 insertions(+), 89 deletions(-) create mode 100644 src/test/cljs_build/trivial/core6.cljs diff --git a/src/main/cljs/cljs/core.cljs b/src/main/cljs/cljs/core.cljs index fa1317832..8eabe774b 100644 --- a/src/main/cljs/cljs/core.cljs +++ b/src/main/cljs/cljs/core.cljs @@ -10384,56 +10384,6 @@ reduces them without incurring seq initialization" (declare Vector) -(defn- simple-map-entry [k v] - (reify - ICounted - (-count [coll] 2) - IHash - (-hash [coll] (hash-ordered-coll [k v])) - ISequential - IEquiv - (-equiv [coll other] (equiv-sequential coll other)) - IVector - (-assoc-n [_ n x] - (case n - 0 (simple-map-entry x v) - 1 (simple-map-entry k x) - (throw (js/Error. "Index out of bounds")))) - IAssociative - (-assoc [node k v] - (-assoc-n node k v)) - (-contains-key? [node k] - (or (== k 0) (== k 1))) - ICollection - (-conj [coll x] - (if ^boolean LITE_MODE - (Vector. nil #js [k v x] nil) - [k v x])) - IMapEntry - (-key [_] k) - (-val [_] v) - ISeqable - (-seq [_] (IndexedSeq. #js [k v] 0 nil)) - IIndexed - (-nth [_ i] - (case i, 0 k, 1 v, (throw (js/Error. "Index out of bounds")))) - (-nth [_ i not-found] - (case i, 0 k, 1 v, not-found)) - ILookup - (-lookup [coll k] (-nth coll k nil)) - (-lookup [coll k not-found] (-nth coll k not-found)) - IFind - (-find [node x] - (case x - 0 (simple-map-entry 0 k) - 1 (simple-map-entry 1 v) - nil)) - IFn - (-invoke [coll k] - (-nth coll k)) - (-invoke [coll k not-found] - (-nth coll k not-found)))) - (defn- pr-writer-impl [obj writer opts] (cond @@ -10472,9 +10422,10 @@ reduces them without incurring seq initialization" (.map (js-keys obj) (fn [k] - (simple-map-entry + (MapEntry. (cond-> k (some? (.match k #"^[A-Za-z_\*\+\?!\-'][\w\*\+\?!\-']*$")) keyword) - (unchecked-get obj k)))) + (unchecked-get obj k) + nil))) pr-writer writer opts)) (array? obj) @@ -10655,10 +10606,10 @@ reduces them without incurring seq initialization" (when (or (keyword? k) (symbol? k)) (if ns (when (= ns (namespace k)) - (.push lm (simple-map-entry (strip-ns k) v)) + (.push lm (MapEntry. (strip-ns k) v nil)) (recur ns entries)) (when-let [new-ns (namespace k)] - (.push lm (simple-map-entry (strip-ns k) v)) + (.push lm (MapEntry. (strip-ns k) v nil)) (recur new-ns entries)))) #js [ns lm]))))) @@ -12566,7 +12517,7 @@ reduces them without incurring seq initialization" (next [_] (let [k (aget strkeys i)] (set! i (inc i)) - (simple-map-entry (obj-map-key->keyword k) (unchecked-get strobj k))))) + (MapEntry. (obj-map-key->keyword k) (unchecked-get strobj k) nil)))) (deftype ObjMap [meta strkeys strobj ^:mutable __hash] Object @@ -12621,7 +12572,7 @@ reduces them without incurring seq initialization" (when (pos? (alength strkeys)) (prim-seq (.map (.sort strkeys obj-map-compare-keys) - #(simple-map-entry (obj-map-key->keyword %) (unchecked-get strobj %)))))) + #(MapEntry. (obj-map-key->keyword %) (unchecked-get strobj %) nil))))) ICounted (-count [coll] (alength strkeys)) @@ -12822,7 +12773,7 @@ reduces them without incurring seq initialization" (loop [j 0] (when (< j len) (do - (.push arr (simple-map-entry (aget bckt j) (aget bckt (inc j)))) + (.push arr (MapEntry. (aget bckt j) (aget bckt (inc j)) nil)) (recur (+ j 2))))) (recur (inc i))) (prim-seq arr)))))) diff --git a/src/test/cljs/cljs/collections_test.cljs b/src/test/cljs/cljs/collections_test.cljs index 01701c51f..20aae48f0 100644 --- a/src/test/cljs/cljs/collections_test.cljs +++ b/src/test/cljs/cljs/collections_test.cljs @@ -1216,12 +1216,6 @@ (is (= (simple-set [[3 4] [1 2] [5 6]]) (into #{} [[3 4] [1 2] [5 6]])))) -(deftest test-simple-map-entry - (is (= (simple-map-entry :foo 1) - (MapEntry. :foo 1 nil))) - (is (= (hash (simple-map-entry :foo 1)) - (hash (MapEntry. :foo 1 nil))))) - (comment (run-tests) diff --git a/src/test/cljs/cljs/lite_collections_test.cljs b/src/test/cljs/cljs/lite_collections_test.cljs index 183f0460f..f481be9ff 100644 --- a/src/test/cljs/cljs/lite_collections_test.cljs +++ b/src/test/cljs/cljs/lite_collections_test.cljs @@ -18,37 +18,12 @@ (let [a {:foo 1}] (is (== 1 (:foo a))))) -(deftest test-simple-map-entry-eq-hash - (is (= (simple-map-entry 1 2) (simple-map-entry 1 2))) - (is (= (simple-map-entry 1 2) - (MapEntry. 1 2 nil))) - (is (== (hash (simple-map-entry 1 2)) - (hash (MapEntry. 1 2 nil))))) - (deftest test-simple-set-with-set (is (= (simple-set []) (set []))) (is (= (set []) (simple-set []))) - (is (= (simple-set [(simple-map-entry 1 2)]) + (is (= (simple-set [(MapEntry. 1 2 nil)]) (set [(MapEntry. 1 2 nil)])))) -(deftest test-hash-map-simple-map-entry - (let [m (assoc (. HashMap -EMPTY) (simple-map-entry 1 2) true)] - (is (contains? m (simple-map-entry 1 2))))) - -(deftest test-simple-set-simple-map-entry - (let [a (simple-set [(simple-map-entry 1 2)])] - (is (contains? a (simple-map-entry 1 2))))) - -(deftest test-simple-map-entry-lookups - (let [me (simple-map-entry :foo "bar")] - (is (= :foo (get me 0))) - (is (= "bar" (get me 1))) - (is (= [0 :foo] - (vec (find (simple-map-entry :foo "bar") 0)))) - (is (= [:foo "b"] - (vec (update (simple-map-entry :foo "bar") 1 first)) - (vec (update-in (simple-map-entry :foo "bar") [1] first)))))) - (comment (require '[cljs.lite-collections-test] :reload) diff --git a/src/test/cljs_build/trivial/core6.cljs b/src/test/cljs_build/trivial/core6.cljs new file mode 100644 index 000000000..244feba5b --- /dev/null +++ b/src/test/cljs_build/trivial/core6.cljs @@ -0,0 +1,3 @@ +(ns trivial.core6) + +(.log js/console (->> (map inc (range 10)) (filter even?) (partition 2) (drop 1) (mapcat identity) into-array)}) diff --git a/src/test/clojure/cljs/build_api_tests.clj b/src/test/clojure/cljs/build_api_tests.clj index 492e0de9f..5854f4c4e 100644 --- a/src/test/clojure/cljs/build_api_tests.clj +++ b/src/test/clojure/cljs/build_api_tests.clj @@ -804,6 +804,22 @@ (build/build (build/inputs (io/file inputs "trivial/core5.cljs")) opts cenv) (is (< (.length out-file) 32768))))) +(deftest lite-mode-api-code-size-ratchet + (testing ":lite-mode + :elide-to-string, typical cljs.core api usage < 32K" + (let [out (.getPath (io/file (test/tmp-dir) "trivial-output-map-test-out")) + out-file (io/file out "main.js") + {:keys [inputs opts]} {:inputs (str (io/file "src" "test" "cljs_build")) + :opts {:main 'trivial.core6 + :output-dir out + :output-to (.getPath out-file) + :lite-mode true + :elide-to-string true + :optimizations :advanced}} + cenv (env/default-compiler-env)] + (test/delete-out-files out) + (build/build (build/inputs (io/file inputs "trivial/core6.cljs")) opts cenv) + (is (< (.length out-file) 32768))))) + (deftest cljs-3255-nil-inputs-build (let [out (.getPath (io/file (test/tmp-dir) "3255-test-out")) out-file (io/file out "main.js") From 66276a42eebb2f05fffd508c0665a698550d46d0 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 3 Oct 2025 20:50:41 -0400 Subject: [PATCH 105/107] remove typo --- src/test/cljs_build/trivial/core6.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/cljs_build/trivial/core6.cljs b/src/test/cljs_build/trivial/core6.cljs index 244feba5b..3eed31bc6 100644 --- a/src/test/cljs_build/trivial/core6.cljs +++ b/src/test/cljs_build/trivial/core6.cljs @@ -1,3 +1,3 @@ (ns trivial.core6) -(.log js/console (->> (map inc (range 10)) (filter even?) (partition 2) (drop 1) (mapcat identity) into-array)}) +(.log js/console (->> (map inc (range 10)) (filter even?) (partition 2) (drop 1) (mapcat identity) into-array)) From cc88daa94d02cbfdfd7086a68e0756da22ec3a59 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 3 Oct 2025 21:12:37 -0400 Subject: [PATCH 106/107] note quite 32K --- src/test/clojure/cljs/build_api_tests.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/clojure/cljs/build_api_tests.clj b/src/test/clojure/cljs/build_api_tests.clj index 5854f4c4e..e6f0d33b1 100644 --- a/src/test/clojure/cljs/build_api_tests.clj +++ b/src/test/clojure/cljs/build_api_tests.clj @@ -805,7 +805,7 @@ (is (< (.length out-file) 32768))))) (deftest lite-mode-api-code-size-ratchet - (testing ":lite-mode + :elide-to-string, typical cljs.core api usage < 32K" + (testing ":lite-mode + :elide-to-string, typical cljs.core api usage ~32K" (let [out (.getPath (io/file (test/tmp-dir) "trivial-output-map-test-out")) out-file (io/file out "main.js") {:keys [inputs opts]} {:inputs (str (io/file "src" "test" "cljs_build")) @@ -818,7 +818,7 @@ cenv (env/default-compiler-env)] (test/delete-out-files out) (build/build (build/inputs (io/file inputs "trivial/core6.cljs")) opts cenv) - (is (< (.length out-file) 32768))))) + (is (< (.length out-file) 34000))))) (deftest cljs-3255-nil-inputs-build (let [out (.getPath (io/file (test/tmp-dir) "3255-test-out")) From 01c65d1dcb0505edc2a7cd28baac99c0f352424d Mon Sep 17 00:00:00 2001 From: davidnolen Date: Fri, 3 Oct 2025 21:53:08 -0400 Subject: [PATCH 107/107] fix trivial output size for vector not in :lite-mode/:elide-to-string --- src/test/clojure/cljs/build_api_tests.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/clojure/cljs/build_api_tests.clj b/src/test/clojure/cljs/build_api_tests.clj index e6f0d33b1..535f1c2c0 100644 --- a/src/test/clojure/cljs/build_api_tests.clj +++ b/src/test/clojure/cljs/build_api_tests.clj @@ -757,7 +757,7 @@ cenv (env/default-compiler-env)] (test/delete-out-files out) (build/build (build/inputs (io/file inputs "trivial/core4.cljs")) opts cenv) - (is (< (.length out-file) 32768)))) + (is (< (.length out-file) 92160)))) (deftest lite-mode-vector-code-size-ratchet (testing ":lite-mode + :elide-to-string, should cut output size for [] in 1/2"