From d270939333fb3431730d1cd6b0255e53a1aa474f Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 30 Nov 2025 10:46:53 -0500 Subject: [PATCH 1/3] cljs.proxy doesn't handle `for .. in` correctly - check for Symbol.iterator case in vec and map handler - need to bind iterator to target for it to work - fixes trivial vector case [1 2 3 4], but not nested case * will need to map over the results of the iterator * this true for the map case too where entries are 2-element arrays --- src/main/cljs/cljs/proxy.cljs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/main/cljs/cljs/proxy.cljs b/src/main/cljs/cljs/proxy.cljs index b0d40655f..5c6438617 100644 --- a/src/main/cljs/cljs/proxy.cljs +++ b/src/main/cljs/cljs/proxy.cljs @@ -1,5 +1,5 @@ (ns cljs.proxy - (:refer-global :only [Proxy isNaN]) + (:refer-global :only [isNaN Proxy Symbol]) (:require [cljs.proxy.impl :refer [SimpleCache]])) (defn- write-through [f] @@ -45,16 +45,26 @@ (js* "var __ctor") (let [cache-key-fn (write-through key-fn) vec-handler #js {:get (fn [^cljs.core/IIndexed target prop receiver] - (if (identical? prop "length") + (cond + (identical? "length" prop) (-count ^cljs.core/ICounted target) + + (identical? (. Symbol -iterator) prop) + (.bind (unchecked-get target prop) target) + + (string? prop) (let [n (js* "+~{}" prop)] (when (and (number? n) (not (isNaN n))) (js/__ctor (-nth target n nil)))))) :has (fn [^cljs.core/IAssociative target prop] - (if (identical? prop "length") - true + (cond + (identical? prop "length") true + + (identical? (. Symbol -iterator) prop) true + + (string? prop) (let [n (js* "+~{}" prop)] (and (number? n) (not (isNaN n)) @@ -70,10 +80,16 @@ :getOwnPropertyDescriptor (fn [target prop] desc)} map-handler #js {:get (fn [^cljs.core/ILookup target prop receiver] - (js/__ctor (-lookup target (cache-key-fn prop)))) + (cond + (identical? (. Symbol -iterator) prop) + (unchecked-get target prop) + + :else (js/__ctor (-lookup target (cache-key-fn prop))))) :has (fn [^cljs.core/IAssociative target prop] - (-contains-key? target (cache-key-fn prop))) + (cond + (identical? (. Symbol -iterator) prop) true + :else (-contains-key? target (cache-key-fn prop)))) :getPrototypeOf (fn [target] nil) @@ -150,5 +166,7 @@ (def proxied-deep (proxy [{:foo "Hello"}])) (-> proxied-deep (aget 0) (unchecked-get "foo")) + + (aget ((cljs.proxy/builder) [{}]) 0) ) From 7c4c3f320dfe3b23ed96e7ecc4fcfd84a0b377fe Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 30 Nov 2025 12:12:44 -0500 Subject: [PATCH 2/3] iterator bind case missing from map proxy --- src/main/cljs/cljs/proxy.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cljs/cljs/proxy.cljs b/src/main/cljs/cljs/proxy.cljs index 5c6438617..169433895 100644 --- a/src/main/cljs/cljs/proxy.cljs +++ b/src/main/cljs/cljs/proxy.cljs @@ -82,7 +82,7 @@ map-handler #js {:get (fn [^cljs.core/ILookup target prop receiver] (cond (identical? (. Symbol -iterator) prop) - (unchecked-get target prop) + (.bind (unchecked-get target prop) target) :else (js/__ctor (-lookup target (cache-key-fn prop))))) From 3789897d9bf74be4c3b4f5579aebf8f097fc4c28 Mon Sep 17 00:00:00 2001 From: davidnolen Date: Sun, 30 Nov 2025 14:28:05 -0500 Subject: [PATCH 3/3] - add cljs.proxu.impl/MapIterator - remove string cases - remove iterator cases from map-handler, no for..of for raw Objects --- src/main/cljs/cljs/proxy.cljs | 20 ++++++++------------ src/main/cljs/cljs/proxy/impl.cljs | 9 +++++++++ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/cljs/cljs/proxy.cljs b/src/main/cljs/cljs/proxy.cljs index 169433895..c3ef55414 100644 --- a/src/main/cljs/cljs/proxy.cljs +++ b/src/main/cljs/cljs/proxy.cljs @@ -1,6 +1,6 @@ (ns cljs.proxy (:refer-global :only [isNaN Proxy Symbol]) - (:require [cljs.proxy.impl :refer [SimpleCache]])) + (:require [cljs.proxy.impl :refer [SimpleCache MapIterator]])) (defn- write-through [f] (let [cache (SimpleCache. #js {} 0)] @@ -50,9 +50,11 @@ (-count ^cljs.core/ICounted target) (identical? (. Symbol -iterator) prop) - (.bind (unchecked-get target prop) target) + (fn [] + (MapIterator. + ((.bind (unchecked-get target prop) target)) js/__ctor)) - (string? prop) + :else (let [n (js* "+~{}" prop)] (when (and (number? n) (not (isNaN n))) @@ -64,7 +66,7 @@ (identical? (. Symbol -iterator) prop) true - (string? prop) + :else (let [n (js* "+~{}" prop)] (and (number? n) (not (isNaN n)) @@ -80,16 +82,10 @@ :getOwnPropertyDescriptor (fn [target prop] desc)} map-handler #js {:get (fn [^cljs.core/ILookup target prop receiver] - (cond - (identical? (. Symbol -iterator) prop) - (.bind (unchecked-get target prop) target) - - :else (js/__ctor (-lookup target (cache-key-fn prop))))) + (js/__ctor (-lookup target (cache-key-fn prop)))) :has (fn [^cljs.core/IAssociative target prop] - (cond - (identical? (. Symbol -iterator) prop) true - :else (-contains-key? target (cache-key-fn prop)))) + (-contains-key? target (cache-key-fn prop))) :getPrototypeOf (fn [target] nil) diff --git a/src/main/cljs/cljs/proxy/impl.cljs b/src/main/cljs/cljs/proxy/impl.cljs index 56c99430d..3914cc115 100644 --- a/src/main/cljs/cljs/proxy/impl.cljs +++ b/src/main/cljs/cljs/proxy/impl.cljs @@ -13,3 +13,12 @@ (clear [this] (set! obj #js {}) (set! cnt 0))) + +(deftype MapIterator [^:mutable iter f] + Object + (next [_] + (let [x (.next iter)] + (if-not ^boolean (. x -done) + #js {:value (f (. x -value)) + :done false} + x))))