-
Notifications
You must be signed in to change notification settings - Fork 24
/
object.js
95 lines (70 loc) · 1.84 KB
/
object.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import {
createStorage,
getValue,
setValue,
} from 'ember-tracked-storage-polyfill';
export default class TrackedObject {
static fromEntries(entries) {
return new TrackedObject(Object.fromEntries(entries));
}
constructor(obj = {}) {
let proto = Object.getPrototypeOf(obj);
let descs = Object.getOwnPropertyDescriptors(obj);
let clone = Object.create(proto);
for (let prop in descs) {
Object.defineProperty(clone, prop, descs[prop]);
}
// eslint-disable-next-line @typescript-eslint/no-this-alias
let self = this;
return new Proxy(clone, {
get(target, prop) {
self.#readStorageFor(prop);
return target[prop];
},
has(target, prop) {
self.#readStorageFor(prop);
return prop in target;
},
ownKeys(target) {
getValue(self.#collection);
return Reflect.ownKeys(target);
},
set(target, prop, value) {
target[prop] = value;
self.#dirtyStorageFor(prop);
self.#dirtyCollection();
return true;
},
deleteProperty(target, prop) {
if (prop in target) {
delete target[prop];
self.#dirtyStorageFor(prop);
self.#dirtyCollection();
}
return true;
},
getPrototypeOf() {
return TrackedObject.prototype;
},
});
}
#storages = new Map();
#collection = createStorage(null, () => false);
#readStorageFor(key) {
let storage = this.#storages.get(key);
if (storage === undefined) {
storage = createStorage(null, () => false);
this.#storages.set(key, storage);
}
getValue(storage);
}
#dirtyStorageFor(key) {
const storage = this.#storages.get(key);
if (storage) {
setValue(storage, null);
}
}
#dirtyCollection() {
setValue(this.#collection, null);
}
}