Skip to content

Commit eef4041

Browse files
committed
first pass at cljs.proxy
1 parent 54d013d commit eef4041

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

src/main/cljs/cljs/proxy.cljs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
(ns cljs.proxy
2+
(:refer-global :only [Proxy isNaN]))
3+
4+
(deftype SimpleCache [^:mutable obj ^:mutable cnt]
5+
Object
6+
(set [this k v]
7+
(when (== cnt 1024)
8+
(.clear this))
9+
(unchecked-set obj k v)
10+
(set! cnt (inc cnt))
11+
v)
12+
(get [this k]
13+
(unchecked-get obj k))
14+
(clear [this]
15+
(set! obj #js {})
16+
(set! cnt 0)))
17+
18+
(defn write-through [f]
19+
(let [cache (SimpleCache. #js {} 0)]
20+
(fn [x]
21+
(let [v (.get cache x)]
22+
(if (some? v)
23+
v
24+
(.set cache x (f x)))))))
25+
26+
(def desc
27+
#js {:configurable true
28+
:enumerable true})
29+
30+
(defn builder
31+
([]
32+
(builder keyword))
33+
([key-fn]
34+
(js* "var __ctor")
35+
(let [cache-key-fn (write-through key-fn)
36+
vec-handler #js {:get (fn [^cljs.core/IIndexed target prop receiver]
37+
(if (identical? prop "length")
38+
(-count ^cljs.core/ICounted target)
39+
(let [n (js* "+~{}" prop)]
40+
(when (and (number? n)
41+
(not (isNaN n)))
42+
(js/__ctor (-nth target n nil))))))
43+
44+
:has (fn [^cljs.core/IAssociative target prop]
45+
(if (identical? prop "length")
46+
true
47+
(let [n (js* "+~{}" prop)]
48+
(and (number? n)
49+
(not (isNaN n))
50+
(<= 0 n)
51+
(< n (-count ^cljs.core/ICounted target))))))
52+
53+
:getPrototypeOf
54+
(fn [target] nil)
55+
56+
:ownKeys
57+
(fn [target] #js ["length"])
58+
59+
:getOwnPropertyDescriptor
60+
(fn [target prop] desc)}
61+
map-handler #js {:get (fn [^cljs.core/ILookup target prop receiver]
62+
(js/__ctor (-lookup target (cache-key-fn prop))))
63+
64+
:has (fn [^cljs.core/IAssociative target prop]
65+
(-contains-key? target (cache-key-fn prop)))
66+
67+
:getPrototypeOf
68+
(fn [target] nil)
69+
70+
:ownKeys
71+
(fn [target]
72+
(when (nil? (.-cljs$cachedOwnKeys target))
73+
(set! (. target -cljs$cachedOwnKeys)
74+
(into-array (map -name (keys target)))))
75+
(.-cljs$cachedOwnKeys target))
76+
77+
:getOwnPropertyDescriptor
78+
(fn [target prop] desc)}
79+
__ctor (fn [target]
80+
(cond
81+
(implements? IMap target) (Proxy. target map-handler)
82+
(implements? IVector target) (Proxy. target vec-handler)
83+
:else target))]
84+
__ctor)))
85+
86+
(comment
87+
88+
(def c (SimpleCache. #js {} 0))
89+
(.set c "foo" :foo)
90+
(.get c "foo")
91+
(.-cnt c)
92+
(.clear c)
93+
(.get c "foo")
94+
95+
(def kw (write-through keyword))
96+
(kw "foo")
97+
98+
(time
99+
(dotimes [i 1e6]
100+
(kw "foo")))
101+
102+
(time
103+
(dotimes [i 1e6]
104+
(keyword "foo")))
105+
106+
(def proxy (builder))
107+
108+
(def proxied-map (proxy {:foo 1 :bar 2}))
109+
110+
(require '[goog.object :as gobj])
111+
(gobj/get proxied-map "foo")
112+
(gobj/get proxied-map "bar")
113+
114+
(time
115+
(dotimes [i 1e7]
116+
(unchecked-get proxied-map "foo")))
117+
118+
(def proxied-vec (proxy [1 2 3 4]))
119+
(alength proxied-vec)
120+
(time
121+
(dotimes [i 1e6]
122+
(alength proxied-vec)))
123+
124+
(nth [1 2 3 4] 1)
125+
126+
(aget proxied-vec 1)
127+
128+
(time
129+
(dotimes [i 1e7]
130+
(aget proxied-vec 1)))
131+
132+
)

0 commit comments

Comments
 (0)