proxy-facades 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/.idea/.name +1 -0
  2. package/.idea/modules.xml +8 -0
  3. package/.idea/proxy-facades.iml +8 -0
  4. package/.idea/vcs.xml +6 -0
  5. package/DEVELOPMENT.md +15 -0
  6. package/LICENSE +21 -0
  7. package/RecordedReadOnProxiedObjectExt.d.ts +22 -0
  8. package/RecordedReadOnProxiedObjectExt.d.ts.map +1 -0
  9. package/RecordedReadOnProxiedObjectExt.js +41 -0
  10. package/RecordedReadOnProxiedObjectExt.js.map +1 -0
  11. package/RecordedReadOnProxiedObjectExt.ts +41 -0
  12. package/Util.d.ts +85 -0
  13. package/Util.d.ts.map +1 -0
  14. package/Util.js +239 -0
  15. package/Util.js.map +1 -0
  16. package/Util.ts +254 -0
  17. package/class-trackers/Array.d.ts +93 -0
  18. package/class-trackers/Array.d.ts.map +1 -0
  19. package/class-trackers/Array.js +193 -0
  20. package/class-trackers/Array.js.map +1 -0
  21. package/class-trackers/Array.ts +245 -0
  22. package/class-trackers/Iterator.d.ts +38 -0
  23. package/class-trackers/Iterator.d.ts.map +1 -0
  24. package/class-trackers/Iterator.js +69 -0
  25. package/class-trackers/Iterator.js.map +1 -0
  26. package/class-trackers/Iterator.ts +73 -0
  27. package/class-trackers/Map.d.ts +128 -0
  28. package/class-trackers/Map.d.ts.map +1 -0
  29. package/class-trackers/Map.js +310 -0
  30. package/class-trackers/Map.js.map +1 -0
  31. package/class-trackers/Map.ts +403 -0
  32. package/class-trackers/Set.d.ts +85 -0
  33. package/class-trackers/Set.d.ts.map +1 -0
  34. package/class-trackers/Set.js +197 -0
  35. package/class-trackers/Set.js.map +1 -0
  36. package/class-trackers/Set.ts +245 -0
  37. package/class-trackers/index.d.ts +7 -0
  38. package/class-trackers/index.d.ts.map +1 -0
  39. package/class-trackers/index.js +36 -0
  40. package/class-trackers/index.js.map +1 -0
  41. package/class-trackers/index.ts +38 -0
  42. package/class-trackers/readme.md +2 -0
  43. package/common.d.ts +235 -0
  44. package/common.d.ts.map +1 -0
  45. package/common.js +378 -0
  46. package/common.js.map +1 -0
  47. package/common.ts +501 -0
  48. package/dev_generateEsRuntimeBehaviourCheckerCode.d.ts +10 -0
  49. package/dev_generateEsRuntimeBehaviourCheckerCode.d.ts.map +1 -0
  50. package/dev_generateEsRuntimeBehaviourCheckerCode.js +76 -0
  51. package/dev_generateEsRuntimeBehaviourCheckerCode.js.map +1 -0
  52. package/dev_generateEsRuntimeBehaviourCheckerCode.ts +85 -0
  53. package/dist/mjs/RecordedReadOnProxiedObjectExt.d.ts +22 -0
  54. package/dist/mjs/RecordedReadOnProxiedObjectExt.d.ts.map +1 -0
  55. package/dist/mjs/RecordedReadOnProxiedObjectExt.js +37 -0
  56. package/dist/mjs/RecordedReadOnProxiedObjectExt.js.map +1 -0
  57. package/dist/mjs/Util.d.ts +85 -0
  58. package/dist/mjs/Util.d.ts.map +1 -0
  59. package/dist/mjs/Util.js +223 -0
  60. package/dist/mjs/Util.js.map +1 -0
  61. package/dist/mjs/class-trackers/Array.d.ts +93 -0
  62. package/dist/mjs/class-trackers/Array.d.ts.map +1 -0
  63. package/dist/mjs/class-trackers/Array.js +186 -0
  64. package/dist/mjs/class-trackers/Array.js.map +1 -0
  65. package/dist/mjs/class-trackers/Iterator.d.ts +38 -0
  66. package/dist/mjs/class-trackers/Iterator.d.ts.map +1 -0
  67. package/dist/mjs/class-trackers/Iterator.js +65 -0
  68. package/dist/mjs/class-trackers/Iterator.js.map +1 -0
  69. package/dist/mjs/class-trackers/Map.d.ts +128 -0
  70. package/dist/mjs/class-trackers/Map.d.ts.map +1 -0
  71. package/dist/mjs/class-trackers/Map.js +299 -0
  72. package/dist/mjs/class-trackers/Map.js.map +1 -0
  73. package/dist/mjs/class-trackers/Set.d.ts +85 -0
  74. package/dist/mjs/class-trackers/Set.d.ts.map +1 -0
  75. package/dist/mjs/class-trackers/Set.js +189 -0
  76. package/dist/mjs/class-trackers/Set.js.map +1 -0
  77. package/dist/mjs/class-trackers/index.d.ts +7 -0
  78. package/dist/mjs/class-trackers/index.d.ts.map +1 -0
  79. package/dist/mjs/class-trackers/index.js +32 -0
  80. package/dist/mjs/class-trackers/index.js.map +1 -0
  81. package/dist/mjs/common.d.ts +235 -0
  82. package/dist/mjs/common.d.ts.map +1 -0
  83. package/dist/mjs/common.js +361 -0
  84. package/dist/mjs/common.js.map +1 -0
  85. package/dist/mjs/dev_generateEsRuntimeBehaviourCheckerCode.d.ts +10 -0
  86. package/dist/mjs/dev_generateEsRuntimeBehaviourCheckerCode.d.ts.map +1 -0
  87. package/dist/mjs/dev_generateEsRuntimeBehaviourCheckerCode.js +76 -0
  88. package/dist/mjs/dev_generateEsRuntimeBehaviourCheckerCode.js.map +1 -0
  89. package/dist/mjs/index.d.ts +8 -0
  90. package/dist/mjs/index.d.ts.map +1 -0
  91. package/dist/mjs/index.js +8 -0
  92. package/dist/mjs/index.js.map +1 -0
  93. package/dist/mjs/objectChangeTracking.d.ts +43 -0
  94. package/dist/mjs/objectChangeTracking.d.ts.map +1 -0
  95. package/dist/mjs/objectChangeTracking.js +209 -0
  96. package/dist/mjs/objectChangeTracking.js.map +1 -0
  97. package/dist/mjs/origChangeTracking.d.ts +14 -0
  98. package/dist/mjs/origChangeTracking.d.ts.map +1 -0
  99. package/dist/mjs/origChangeTracking.js +58 -0
  100. package/dist/mjs/origChangeTracking.js.map +1 -0
  101. package/dist/mjs/proxyFacade.d.ts +45 -0
  102. package/dist/mjs/proxyFacade.d.ts.map +1 -0
  103. package/dist/mjs/proxyFacade.js +179 -0
  104. package/dist/mjs/proxyFacade.js.map +1 -0
  105. package/dist/mjs/watchedProxyFacade.d.ts +84 -0
  106. package/dist/mjs/watchedProxyFacade.d.ts.map +1 -0
  107. package/dist/mjs/watchedProxyFacade.js +300 -0
  108. package/dist/mjs/watchedProxyFacade.js.map +1 -0
  109. package/index.d.ts +8 -0
  110. package/index.d.ts.map +1 -0
  111. package/index.js +36 -0
  112. package/index.js.map +1 -0
  113. package/index.ts +7 -0
  114. package/index_esm.mjs +44 -0
  115. package/objectChangeTracking.d.ts +43 -0
  116. package/objectChangeTracking.d.ts.map +1 -0
  117. package/objectChangeTracking.js +214 -0
  118. package/objectChangeTracking.js.map +1 -0
  119. package/objectChangeTracking.ts +251 -0
  120. package/origChangeTracking.d.ts +14 -0
  121. package/origChangeTracking.d.ts.map +1 -0
  122. package/origChangeTracking.js +63 -0
  123. package/origChangeTracking.js.map +1 -0
  124. package/origChangeTracking.ts +72 -0
  125. package/package.json +52 -0
  126. package/proxyFacade.d.ts +45 -0
  127. package/proxyFacade.d.ts.map +1 -0
  128. package/proxyFacade.js +187 -0
  129. package/proxyFacade.js.map +1 -0
  130. package/proxyFacade.ts +222 -0
  131. package/readme.md +111 -0
  132. package/watchedProxyFacade.d.ts +84 -0
  133. package/watchedProxyFacade.d.ts.map +1 -0
  134. package/watchedProxyFacade.js +312 -0
  135. package/watchedProxyFacade.js.map +1 -0
  136. package/watchedProxyFacade.ts +369 -0
@@ -0,0 +1,403 @@
1
+ import {
2
+ ChangeListener, EventHook, ClassTrackingConfiguration,
3
+ DualUseTracker, dualUseTracker_callOrigMethodOnTarget,
4
+ ForWatchedProxyHandler, IWatchedProxyHandler_common, makeIteratorTranslateValue,
5
+ ObjKey,
6
+ RecordedRead,
7
+ RecordedReadOnProxiedObject,
8
+ runChangeOperation, UnspecificObjectChange
9
+ } from "../common";
10
+ import {getChangeHooksForObject, changeHooksForObject} from "../objectChangeTracking";
11
+ import {arraysAreShallowlyEqual, arraysWithEntriesAreShallowlyEqual, MapSet, newDefaultMap} from "../Util";
12
+ import {installChangeTracker} from "../origChangeTracking";
13
+ import {WatchedProxyHandler} from "../watchedProxyFacade";
14
+ import {RecordedReadOnProxiedObjectExt} from "../RecordedReadOnProxiedObjectExt";
15
+
16
+
17
+ /**
18
+ * Hooks for one map.
19
+ * Note for specificity: There will be only one of the **change** events fired. The Recorded...Read.onChange handler will add the listeners to all possible candidates. It's this way around.
20
+ * {@link ObjectChangeHooks} are also subscribed on Maps
21
+ */
22
+ class MapChangeHooks {
23
+ specificKeyAddedOrRemoved = newDefaultMap<unknown, EventHook>( () => new EventHook());
24
+ anyKeyAddedOrRemoved = new EventHook();
25
+
26
+ specificValueChanged = newDefaultMap<unknown, EventHook>( () => new EventHook());
27
+ anyValueChanged = new EventHook();
28
+ }
29
+
30
+ export const changeHooksForMap = new WeakMap<Map<unknown,unknown>, MapChangeHooks>();
31
+ export function getChangeHooksForMap(map: Map<unknown,unknown>) {
32
+ let result = changeHooksForMap.get(map);
33
+ if(result === undefined) {
34
+ changeHooksForMap.set(map, result = new MapChangeHooks());
35
+ }
36
+ return result;
37
+ }
38
+
39
+ /**
40
+ * Can be either used as a supervisor-class in a WatchedProxyHandler, or installed on the non-proxied object via Object.setPrototypeOf
41
+ * The "this" may be different in these cases.
42
+ */
43
+ export class MapChangeTracker<K,V> extends Map<K,V> implements DualUseTracker<Map<K,V>>{
44
+
45
+ get _watchedProxyHandler(): IWatchedProxyHandler_common | undefined {
46
+ return undefined;
47
+ }
48
+
49
+ protected _withUnspecificChange<R>(changeFn: () => R): R {
50
+ return runChangeOperation(this, new UnspecificObjectChange(this), [getChangeHooksForObject(this).unspecificChange], changeFn)
51
+ }
52
+
53
+ /**
54
+ * Will return the original object when this class is used as supervisor class in the WatchedProxyHandler
55
+ */
56
+ get _target(): Map<K, V> {
57
+ return this;
58
+ }
59
+
60
+ /**
61
+ * Pretend that this is a Map
62
+ */
63
+ get ["constructor"]() {
64
+ return Map;
65
+ }
66
+
67
+ set(key:K, value: V): this {
68
+ key = this._watchedProxyHandler?this._watchedProxyHandler.getFacade().getUnproxiedValue(key):key; // Translate to unproxied key
69
+ value = this._watchedProxyHandler?this._watchedProxyHandler.getFacade().getUnproxiedValue(value):value; // Translate to unproxied value
70
+
71
+ const isNewKey = !this._target.has(key);
72
+ const valueChanged = isNewKey || this._target.get(key) !== value;
73
+ if(!isNewKey && !valueChanged) {
74
+ return this;
75
+ }
76
+
77
+ const hooksForThisMap = getChangeHooksForMap(this);
78
+ const hooksToServe = [
79
+ ...(isNewKey?[hooksForThisMap.specificKeyAddedOrRemoved.get(key), hooksForThisMap.anyKeyAddedOrRemoved]:[]),
80
+ ...(valueChanged?[hooksForThisMap.specificValueChanged.get(key), hooksForThisMap.anyValueChanged]:[])
81
+ ];
82
+ runChangeOperation(this, new UnspecificObjectChange(this),hooksToServe,() => {
83
+ return dualUseTracker_callOrigMethodOnTarget(this, "set", [key, value])
84
+ });
85
+
86
+ return this;
87
+ }
88
+
89
+ delete(key: K): boolean {
90
+ key = this._watchedProxyHandler?this._watchedProxyHandler.getFacade().getUnproxiedValue(key):key; // Translate to unproxied key
91
+
92
+ if(!this._target.has(key)) { // no change?
93
+ return false;
94
+ }
95
+
96
+ const hooksForThisMap = getChangeHooksForMap(this);
97
+ const hooksToServe = [hooksForThisMap.specificKeyAddedOrRemoved.get(key),hooksForThisMap.anyKeyAddedOrRemoved,hooksForThisMap.specificValueChanged.get(key),hooksForThisMap.anyValueChanged];
98
+ return runChangeOperation(this, new UnspecificObjectChange(this),hooksToServe,() => {
99
+ return dualUseTracker_callOrigMethodOnTarget(this, "delete", [key]);
100
+ });
101
+ }
102
+
103
+ clear() {
104
+ const hooksToServe = [getChangeHooksForMap(this).anyKeyAddedOrRemoved, getChangeHooksForMap(this).anyValueChanged, getChangeHooksForObject(this).unspecificChange];
105
+ return runChangeOperation(this, new UnspecificObjectChange(this),hooksToServe,() => {
106
+ return dualUseTracker_callOrigMethodOnTarget(this, "clear", []);
107
+ });
108
+ }
109
+
110
+ }
111
+
112
+ export class RecordedMap_get extends RecordedReadOnProxiedObjectExt {
113
+ key!: unknown;
114
+
115
+ keyExists: boolean;
116
+ /**
117
+ * Result of the .get call
118
+ */
119
+ value: unknown;
120
+ obj!: Map<unknown, unknown>;
121
+
122
+
123
+ constructor(key: unknown, keyExists: boolean, value: unknown) {
124
+ super();
125
+ this.key = key;
126
+ this.keyExists = keyExists;
127
+ this.value = value;
128
+ }
129
+
130
+ get isChanged() {
131
+ return !(this.keyExists === this.obj.has(this.key) && this.value === this.obj.get(this.key));
132
+ }
133
+
134
+ getAffectingChangeHooks(target: this["obj"]) {
135
+ return [
136
+ getChangeHooksForMap(target).specificKeyAddedOrRemoved.get(this.key),
137
+ getChangeHooksForMap(target).specificValueChanged.get(this.key),
138
+ getChangeHooksForObject(target).unspecificChange
139
+ ]
140
+ }
141
+
142
+ equals(other: RecordedRead) {
143
+ if (!(other instanceof RecordedMap_get)) {
144
+ return false;
145
+ }
146
+
147
+ return this.proxyHandler === other.proxyHandler && this.obj === other.obj && this.key === other.key && this.keyExists == other.keyExists && this.value === other.value;
148
+ }
149
+ }
150
+
151
+ export class RecordedMap_has extends RecordedReadOnProxiedObjectExt {
152
+ key!: unknown;
153
+
154
+ /**
155
+ * Result of the .has call
156
+ */
157
+ keyExists: boolean;
158
+ obj!: Map<unknown, unknown>;
159
+
160
+
161
+ constructor(key: unknown, keyExists: boolean) {
162
+ super();
163
+ this.key = key;
164
+ this.keyExists = keyExists;
165
+ }
166
+
167
+ get isChanged() {
168
+ return this.keyExists !== this.obj.has(this.key);
169
+ }
170
+
171
+ getAffectingChangeHooks(target: this["obj"]) {
172
+ return [
173
+ getChangeHooksForMap(target).specificKeyAddedOrRemoved.get(this.key),
174
+ getChangeHooksForObject(target).unspecificChange,
175
+ ]
176
+ }
177
+
178
+ equals(other: RecordedRead) {
179
+ if (!(other instanceof RecordedMap_has)) {
180
+ return false;
181
+ }
182
+
183
+ return this.proxyHandler === other.proxyHandler && this.obj === other.obj && this.key === other.key && this.keyExists === other.keyExists;
184
+ }
185
+ }
186
+
187
+ export class RecordedMapKeysRead extends RecordedReadOnProxiedObjectExt {
188
+ keys: Array<unknown>;
189
+ obj!: Map<unknown, unknown>;
190
+
191
+
192
+ constructor(keys: Array<unknown>) {
193
+ super();
194
+ this.keys = keys;
195
+ }
196
+
197
+ getAffectingChangeHooks(target: this["obj"]) {
198
+ return [
199
+ getChangeHooksForMap(target).anyKeyAddedOrRemoved,
200
+ getChangeHooksForObject(target).unspecificChange
201
+ ]
202
+ }
203
+
204
+ equals(other: RecordedRead): boolean {
205
+ if (!(other instanceof RecordedMapKeysRead)) {
206
+ return false;
207
+ }
208
+
209
+ return this.proxyHandler === other.proxyHandler && this.obj === other.obj && arraysAreShallowlyEqual(this.keys, other.keys);
210
+ }
211
+
212
+ get isChanged(): boolean {
213
+ return !arraysAreShallowlyEqual(this.keys, [...(this.obj).keys()]);
214
+ }
215
+ }
216
+
217
+ export class RecordedMapValuesRead extends RecordedReadOnProxiedObjectExt {
218
+ values: Array<unknown>;
219
+
220
+ obj!:Map<unknown, unknown>;
221
+
222
+ constructor(values: Array<unknown>) {
223
+ super();
224
+ this.values = values;
225
+ }
226
+
227
+ getAffectingChangeHooks(target: this["obj"]) {
228
+ return [
229
+ getChangeHooksForMap(target).anyValueChanged,
230
+ getChangeHooksForObject(target).unspecificChange
231
+ ]
232
+ }
233
+
234
+ equals(other: RecordedRead): boolean {
235
+ if (!(other instanceof RecordedMapValuesRead)) {
236
+ return false;
237
+ }
238
+
239
+ return this.proxyHandler === other.proxyHandler && this.obj === other.obj && arraysAreShallowlyEqual(this.values, other.values);
240
+ }
241
+
242
+ get isChanged(): boolean {
243
+ return !arraysAreShallowlyEqual(this.values, [...(this.obj).values()]);
244
+ }
245
+ }
246
+
247
+ export class RecordedMapEntriesRead extends RecordedReadOnProxiedObjectExt {
248
+ values: Array<[unknown, unknown]>;
249
+
250
+ obj!: Map<unknown, unknown>;
251
+
252
+
253
+ constructor(values: Array<[unknown, unknown]>) {
254
+ super();
255
+ this.values = values;
256
+ }
257
+
258
+ getAffectingChangeHooks(target: this["obj"]) {
259
+ return [
260
+ getChangeHooksForMap(target).anyKeyAddedOrRemoved,
261
+ getChangeHooksForMap(target).anyValueChanged,
262
+ getChangeHooksForObject(target).unspecificChange
263
+ ]
264
+ }
265
+
266
+ equals(other: RecordedRead): boolean {
267
+ if (!(other instanceof RecordedMapEntriesRead)) {
268
+ return false;
269
+ }
270
+
271
+ return this.proxyHandler === other.proxyHandler && this.obj === other.obj && arraysWithEntriesAreShallowlyEqual(this.values, other.values);
272
+ }
273
+
274
+ get isChanged(): boolean {
275
+ return !arraysWithEntriesAreShallowlyEqual(this.values, [...(this.obj).entries()]);
276
+ }
277
+ }
278
+
279
+ export class MapReadTracker<K, V> extends Map<K, V> implements ForWatchedProxyHandler<Map<K, V>> {
280
+ get _watchedProxyHandler(): WatchedProxyHandler {
281
+ throw new Error("not calling from inside a WatchedProxyHandler"); // Will return the handler when called through the handler
282
+ }
283
+
284
+ get _target(): Map<K, V> {
285
+ throw new Error("not calling from inside a WatchedProxyHandler"); // Will return the value when called through the handler
286
+ }
287
+
288
+ protected _fireAfterEntriesRead() {
289
+ let recordedMapEntriesRead = new RecordedMapEntriesRead([...this._target.entries()]);
290
+ this._watchedProxyHandler?.fireAfterRead(recordedMapEntriesRead);
291
+ }
292
+
293
+ /**
294
+ * Pretend that this is a Map
295
+ */
296
+ get ["constructor"]() {
297
+ return Map;
298
+ }
299
+
300
+ get(key: K): V | undefined {
301
+ key = this._watchedProxyHandler.getFacade().getUnproxiedValue(key);
302
+ const keyExists = this._target.has(key);
303
+ const result = this._target.get(key);
304
+
305
+ const read = new RecordedMap_get(key, keyExists, result);
306
+ this._watchedProxyHandler?.fireAfterRead(read);
307
+
308
+ return this._watchedProxyHandler.getFacade().getProxyFor(result);
309
+ }
310
+
311
+ has(key: K): boolean {
312
+ key = this._watchedProxyHandler.getFacade().getUnproxiedValue(key);
313
+ const result = this._target.has(key);
314
+
315
+ const read = new RecordedMap_has(key, result);
316
+ this._watchedProxyHandler?.fireAfterRead(read);
317
+
318
+ return result;
319
+ }
320
+
321
+ values(): MapIterator<V> {
322
+ const result = this._target.values();
323
+
324
+ let recordedMapValuesRead = new RecordedMapValuesRead([...result]);
325
+ this._watchedProxyHandler?.fireAfterRead(recordedMapValuesRead);
326
+
327
+ return makeIteratorTranslateValue(result, (value) => this._watchedProxyHandler.getFacade().getProxyFor(value));
328
+ }
329
+
330
+ entries(): MapIterator<[K, V]> {
331
+ const result = this._target.entries();
332
+ this._fireAfterEntriesRead();
333
+
334
+ const facade = this._watchedProxyHandler.getFacade();
335
+ return makeIteratorTranslateValue<[K, V], MapIterator<[K, V]>/*strange that TS does not infer the types here*/>(result, ([key,value]) => [facade.getProxyFor(key), facade.getProxyFor(value)]);
336
+ }
337
+
338
+ keys(): MapIterator<K> {
339
+ const result = this._target.keys();
340
+
341
+ let recordedMapKeysRead = new RecordedMapKeysRead([...result]);
342
+ this._watchedProxyHandler?.fireAfterRead(recordedMapKeysRead);
343
+
344
+ return makeIteratorTranslateValue(result, (key) => this._watchedProxyHandler.getFacade().getProxyFor(key));
345
+ }
346
+
347
+ forEach(callbackfn: (value: V, key: K, map: Map<K, V>, ...restOfArgs: unknown[]) => void, ...restOfArgs: unknown[]) {
348
+ const getProxyFor: (<T>(val: T)=>T) = (value) => this._watchedProxyHandler.getFacade().getProxyFor(value);
349
+
350
+ /**
351
+ * Calls callbackFn but supplies it it's arguments *proxied*
352
+ */
353
+ function callCallbackFnWithProxies(this: Map<K, V>, value: V, key: K, map: Map<K, V>, ...restOfArgs: unknown[]): void{
354
+ callbackfn.apply(this, [getProxyFor(value), getProxyFor(key), getProxyFor(map), ...restOfArgs]);
355
+ }
356
+
357
+ const result = this._target.forEach(callCallbackFnWithProxies, ...restOfArgs);
358
+ this._fireAfterEntriesRead();
359
+ return result;
360
+ }
361
+
362
+ [Symbol.iterator](): MapIterator<[K, V]> {
363
+ const result = this._target[Symbol.iterator]();
364
+ this._fireAfterEntriesRead();
365
+
366
+ const facade = this._watchedProxyHandler.getFacade();
367
+ return makeIteratorTranslateValue<[K, V], MapIterator<[K, V]>/*strange that TS does not infer the types here*/>(result, ([key,value]) => [facade.getProxyFor(key), facade.getProxyFor(value)]);
368
+ }
369
+
370
+ get size(): number {
371
+ const result = this._target.size;
372
+
373
+ let recordedMapKeysRead = new RecordedMapKeysRead([...this._target.keys()]); // TODO: RecordedMapSizeRead
374
+ this._watchedProxyHandler?.fireAfterRead(recordedMapKeysRead);
375
+
376
+ return result;
377
+ }
378
+ }
379
+
380
+ export const config = new class extends ClassTrackingConfiguration {
381
+ clazz=Map;
382
+ readTracker= MapReadTracker;
383
+ changeTracker = MapChangeTracker
384
+
385
+ /**
386
+ * Built-in Methods, which are using fields / calling methods on the proxy transparently/loyally, so those methods don't call/use internal stuff directly.
387
+ * Tested with, see dev_generateEsRuntimeBehaviourCheckerCode.ts
388
+ * May include read-only / reader methods
389
+ */
390
+ knownHighLevelMethods = new Set<keyof Map<unknown,unknown>>([]) as Set<ObjKey>;
391
+
392
+ /**
393
+ * Non-high level
394
+ */
395
+ readOnlyMethods = new Set<keyof Map<unknown,unknown>>([]) as Set<ObjKey>;
396
+
397
+ /**
398
+ * Non-high level
399
+ */
400
+ readOnlyFields = new Set<keyof Map<unknown,unknown>>(["size"]) as Set<ObjKey>;
401
+
402
+ receiverMustBeNonProxied = true;
403
+ }
@@ -0,0 +1,85 @@
1
+ import { DualUseTracker, ForWatchedProxyHandler, IWatchedProxyHandler_common, ObjKey, RecordedRead, EventHook } from "../common";
2
+ import { WatchedProxyHandler } from "../watchedProxyFacade";
3
+ import { RecordedReadOnProxiedObjectExt } from "../RecordedReadOnProxiedObjectExt";
4
+ /**
5
+ * Listeners for one set.
6
+ * Note for specificity: There will be only one of the **change** events fired. The Recorded...Read.onChange handler will add the listeners to all possible candidates. It's this way around.
7
+ * {@link ObjectChangeHooks} are also subscribed on Sets
8
+ */
9
+ declare class SetChangeHooks {
10
+ afterSpecificValueChanged: import("../Util").DefaultMap<unknown, EventHook>;
11
+ afterAnyValueChanged: EventHook;
12
+ }
13
+ export declare const changeHooksForSet: WeakMap<Set<unknown>, SetChangeHooks>;
14
+ export declare function getChangeHooksForSet(set: Set<unknown>): SetChangeHooks;
15
+ /**
16
+ * Can be either used as a supervisor-class in a WatchedProxyHandler, or installed on the non-proxied object via Object.setPrototypeOf
17
+ * The "this" may be different in these cases.
18
+ */
19
+ export declare class SetChangeTracker<T> extends Set<T> implements DualUseTracker<Set<T>> {
20
+ get _watchedProxyHandler(): IWatchedProxyHandler_common | undefined;
21
+ protected _withUnspecificChange<R>(changeFn: () => R): R;
22
+ /**
23
+ * Will return the original object when this class is used as supervisor class in the WatchedProxyHandler
24
+ */
25
+ get _target(): Set<T>;
26
+ /**
27
+ * Pretend that this is a Set
28
+ */
29
+ get ["constructor"](): SetConstructor;
30
+ add(value: T): this;
31
+ delete(value: T): boolean;
32
+ clear(): void;
33
+ }
34
+ export declare class RecordedSet_has extends RecordedReadOnProxiedObjectExt {
35
+ value: unknown;
36
+ /**
37
+ * Result of the .has call
38
+ */
39
+ result: boolean;
40
+ obj: Set<unknown>;
41
+ constructor(value: unknown, result: boolean);
42
+ get isChanged(): boolean;
43
+ getAffectingChangeHooks(target: this["obj"]): EventHook[];
44
+ equals(other: RecordedRead): boolean;
45
+ }
46
+ export declare class RecordedSetValuesRead extends RecordedReadOnProxiedObjectExt {
47
+ values: Array<unknown>;
48
+ obj: Set<unknown>;
49
+ constructor(values: Array<unknown>);
50
+ getAffectingChangeHooks(target: this["obj"]): EventHook[];
51
+ equals(other: RecordedRead): boolean;
52
+ get isChanged(): boolean;
53
+ }
54
+ export declare class SetReadTracker<T> extends Set<T> implements ForWatchedProxyHandler<Set<T>> {
55
+ get _watchedProxyHandler(): WatchedProxyHandler;
56
+ get _target(): Set<T>;
57
+ protected _fireAfterValuesRead(): void;
58
+ /**
59
+ * Pretend that this is a Set
60
+ */
61
+ get ["constructor"](): SetConstructor;
62
+ has(value: T): boolean;
63
+ values(): SetIterator<T>;
64
+ entries(): SetIterator<[T, T]>;
65
+ keys(): SetIterator<T>;
66
+ forEach(callbackfn: (value: T, value2: T, set: Set<T>, ...restOfArgs: unknown[]) => void, ...restOfArgs: unknown[]): void;
67
+ [Symbol.iterator](): SetIterator<T>;
68
+ get size(): number;
69
+ }
70
+ export declare const config: {
71
+ clazz: SetConstructor;
72
+ readTracker: typeof SetReadTracker;
73
+ changeTracker: typeof SetChangeTracker;
74
+ receiverMustBeNonProxied: boolean;
75
+ worksForSubclasses: boolean;
76
+ knownHighLevelMethods: Set<ObjKey>;
77
+ readOnlyMethods: Set<ObjKey>;
78
+ readOnlyFields: Set<ObjKey>;
79
+ trackTreads: boolean;
80
+ trackSettingObjectProperties: boolean;
81
+ proxyUnhandledMethodResults: boolean;
82
+ getTrackerClasses(): import("../common").Clazz[];
83
+ };
84
+ export {};
85
+ //# sourceMappingURL=Set.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Set.d.ts","sourceRoot":"","sources":["Set.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.config = exports.SetReadTracker = exports.RecordedSetValuesRead = exports.RecordedSet_has = exports.SetChangeTracker = exports.changeHooksForSet = void 0;
4
+ exports.getChangeHooksForSet = getChangeHooksForSet;
5
+ const common_1 = require("../common");
6
+ const objectChangeTracking_1 = require("../objectChangeTracking");
7
+ const Util_1 = require("../Util");
8
+ const RecordedReadOnProxiedObjectExt_1 = require("../RecordedReadOnProxiedObjectExt");
9
+ /**
10
+ * Listeners for one set.
11
+ * Note for specificity: There will be only one of the **change** events fired. The Recorded...Read.onChange handler will add the listeners to all possible candidates. It's this way around.
12
+ * {@link ObjectChangeHooks} are also subscribed on Sets
13
+ */
14
+ class SetChangeHooks {
15
+ constructor() {
16
+ this.afterSpecificValueChanged = (0, Util_1.newDefaultMap)(() => new common_1.EventHook());
17
+ this.afterAnyValueChanged = new common_1.EventHook();
18
+ }
19
+ }
20
+ exports.changeHooksForSet = new WeakMap();
21
+ function getChangeHooksForSet(set) {
22
+ let result = exports.changeHooksForSet.get(set);
23
+ if (result === undefined) {
24
+ exports.changeHooksForSet.set(set, result = new SetChangeHooks());
25
+ }
26
+ return result;
27
+ }
28
+ /**
29
+ * Can be either used as a supervisor-class in a WatchedProxyHandler, or installed on the non-proxied object via Object.setPrototypeOf
30
+ * The "this" may be different in these cases.
31
+ */
32
+ class SetChangeTracker extends Set {
33
+ get _watchedProxyHandler() {
34
+ return undefined;
35
+ }
36
+ _withUnspecificChange(changeFn) {
37
+ return (0, common_1.runChangeOperation)(this, new common_1.UnspecificObjectChange(this), [(0, objectChangeTracking_1.getChangeHooksForObject)(this).unspecificChange], changeFn);
38
+ }
39
+ /**
40
+ * Will return the original object when this class is used as supervisor class in the WatchedProxyHandler
41
+ */
42
+ get _target() {
43
+ return this;
44
+ }
45
+ /**
46
+ * Pretend that this is a Set
47
+ */
48
+ get ["constructor"]() {
49
+ return Set;
50
+ }
51
+ add(value) {
52
+ value = this._watchedProxyHandler ? this._watchedProxyHandler.getFacade().getUnproxiedValue(value) : value; // Translate to unproxied value
53
+ if (this._target.has(value)) { // No change?
54
+ return this;
55
+ }
56
+ (0, common_1.runChangeOperation)(this, new common_1.UnspecificObjectChange(this), [getChangeHooksForSet(this).afterSpecificValueChanged.get(value), getChangeHooksForSet(this).afterAnyValueChanged], () => {
57
+ (0, common_1.dualUseTracker_callOrigMethodOnTarget)(this, "add", [value]);
58
+ });
59
+ return this;
60
+ }
61
+ delete(value) {
62
+ value = this._watchedProxyHandler ? this._watchedProxyHandler.getFacade().getUnproxiedValue(value) : value; // Translate to unproxied value
63
+ if (!this._target.has(value)) { // no change?
64
+ return false;
65
+ }
66
+ return (0, common_1.runChangeOperation)(this, new common_1.UnspecificObjectChange(this), [getChangeHooksForSet(this).afterSpecificValueChanged.get(value), getChangeHooksForSet(this).afterAnyValueChanged], () => {
67
+ return (0, common_1.dualUseTracker_callOrigMethodOnTarget)(this, "delete", [value]);
68
+ });
69
+ }
70
+ clear() {
71
+ return (0, common_1.runChangeOperation)(this, new common_1.UnspecificObjectChange(this), [getChangeHooksForSet(this).afterAnyValueChanged, (0, objectChangeTracking_1.getChangeHooksForObject)(this).unspecificChange], () => {
72
+ return (0, common_1.dualUseTracker_callOrigMethodOnTarget)(this, "clear", []);
73
+ });
74
+ }
75
+ }
76
+ exports.SetChangeTracker = SetChangeTracker;
77
+ class RecordedSet_has extends RecordedReadOnProxiedObjectExt_1.RecordedReadOnProxiedObjectExt {
78
+ constructor(value, result) {
79
+ super();
80
+ this.value = value;
81
+ this.result = result;
82
+ }
83
+ get isChanged() {
84
+ return this.result !== this.obj.has(this.value);
85
+ }
86
+ getAffectingChangeHooks(target) {
87
+ return [
88
+ getChangeHooksForSet(target).afterSpecificValueChanged.get(this.value),
89
+ (0, objectChangeTracking_1.getChangeHooksForObject)(target).unspecificChange
90
+ ];
91
+ }
92
+ equals(other) {
93
+ if (!(other instanceof RecordedSet_has)) {
94
+ return false;
95
+ }
96
+ return this.proxyHandler === other.proxyHandler && this.obj === other.obj && this.value === other.value && this.result === other.result;
97
+ }
98
+ }
99
+ exports.RecordedSet_has = RecordedSet_has;
100
+ class RecordedSetValuesRead extends RecordedReadOnProxiedObjectExt_1.RecordedReadOnProxiedObjectExt {
101
+ constructor(values) {
102
+ super();
103
+ this.values = values;
104
+ }
105
+ getAffectingChangeHooks(target) {
106
+ return [
107
+ getChangeHooksForSet(target).afterAnyValueChanged,
108
+ (0, objectChangeTracking_1.getChangeHooksForObject)(target).unspecificChange
109
+ ];
110
+ }
111
+ equals(other) {
112
+ if (!(other instanceof RecordedSetValuesRead)) {
113
+ return false;
114
+ }
115
+ return this.proxyHandler === other.proxyHandler && this.obj === other.obj && (0, Util_1.arraysAreShallowlyEqual)(this.values, other.values);
116
+ }
117
+ get isChanged() {
118
+ return !(0, Util_1.arraysAreShallowlyEqual)(this.values, [...(this.obj).values()]);
119
+ }
120
+ }
121
+ exports.RecordedSetValuesRead = RecordedSetValuesRead;
122
+ class SetReadTracker extends Set {
123
+ get _watchedProxyHandler() {
124
+ throw new Error("not calling from inside a WatchedProxyHandler"); // Will return the handler when called through the handler
125
+ }
126
+ get _target() {
127
+ throw new Error("not calling from inside a WatchedProxyHandler"); // Will return the value when called through the handler
128
+ }
129
+ _fireAfterValuesRead() {
130
+ var _a;
131
+ let recordedSetValuesRead = new RecordedSetValuesRead([...this._target]);
132
+ (_a = this._watchedProxyHandler) === null || _a === void 0 ? void 0 : _a.fireAfterRead(recordedSetValuesRead);
133
+ }
134
+ /**
135
+ * Pretend that this is a Set
136
+ */
137
+ get ["constructor"]() {
138
+ return Set;
139
+ }
140
+ has(value) {
141
+ var _a;
142
+ value = this._watchedProxyHandler.getFacade().getUnproxiedValue(value);
143
+ const result = this._target.has(value);
144
+ const read = new RecordedSet_has(value, result);
145
+ (_a = this._watchedProxyHandler) === null || _a === void 0 ? void 0 : _a.fireAfterRead(read);
146
+ return result;
147
+ }
148
+ values() {
149
+ const result = this._target.values();
150
+ this._fireAfterValuesRead();
151
+ return (0, common_1.makeIteratorTranslateValue)(result, (value) => this._watchedProxyHandler.getFacade().getProxyFor(value));
152
+ }
153
+ entries() {
154
+ const result = this._target.entries();
155
+ this._fireAfterValuesRead();
156
+ const facade = this._watchedProxyHandler.getFacade();
157
+ return (0, common_1.makeIteratorTranslateValue)(result, ([value1, value2]) => [facade.getProxyFor(value1), facade.getProxyFor(value2)]);
158
+ }
159
+ keys() {
160
+ const result = this._target.keys();
161
+ this._fireAfterValuesRead();
162
+ return (0, common_1.makeIteratorTranslateValue)(result, (value) => this._watchedProxyHandler.getFacade().getProxyFor(value));
163
+ }
164
+ forEach(callbackfn, ...restOfArgs) {
165
+ const getProxyFor = (value) => this._watchedProxyHandler.getFacade().getProxyFor(value);
166
+ /**
167
+ * Calls callbackFn but supplies it it's arguments *proxied*
168
+ */
169
+ function callCallbackFnWithProxies(value, value2, set, ...restOfArgs) {
170
+ callbackfn.apply(this, [getProxyFor(value), getProxyFor(value2), getProxyFor(set), ...restOfArgs]);
171
+ }
172
+ const result = this._target.forEach(callCallbackFnWithProxies, ...restOfArgs);
173
+ this._fireAfterValuesRead();
174
+ return result;
175
+ }
176
+ [Symbol.iterator]() {
177
+ const result = this._target[Symbol.iterator]();
178
+ this._fireAfterValuesRead();
179
+ return (0, common_1.makeIteratorTranslateValue)(result, (value) => this._watchedProxyHandler.getFacade().getProxyFor(value));
180
+ }
181
+ get size() {
182
+ const result = this._target.size;
183
+ this._fireAfterValuesRead();
184
+ return result;
185
+ }
186
+ }
187
+ exports.SetReadTracker = SetReadTracker;
188
+ exports.config = new class extends common_1.ClassTrackingConfiguration {
189
+ constructor() {
190
+ super(...arguments);
191
+ this.clazz = Set;
192
+ this.readTracker = SetReadTracker;
193
+ this.changeTracker = SetChangeTracker;
194
+ this.receiverMustBeNonProxied = true;
195
+ }
196
+ };
197
+ //# sourceMappingURL=Set.js.map