j-templates 8.0.9 → 8.0.11
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.
package/Store/Store/store.js
CHANGED
|
@@ -63,7 +63,6 @@ class Store {
|
|
|
63
63
|
this.UpdateRootObject(rootGroup[0].path[0], rootGroup);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
// protected SpliceRootMap(spliceResult: DiffSpliceResult) {
|
|
67
66
|
SpliceRootObject(rootPath, start, deleteCount, items) {
|
|
68
67
|
const rootObject = this.rootMap.get(rootPath);
|
|
69
68
|
observableNode_1.ObservableNode.ApplySplice(rootObject[rootPath], start, deleteCount, items, this.cloneData);
|
|
@@ -125,12 +125,13 @@ class StoreAsync extends store_1.Store {
|
|
|
125
125
|
* @returns The array of deleted elements.
|
|
126
126
|
*/
|
|
127
127
|
async Splice(key, start, deleteCount, ...items) {
|
|
128
|
+
items = (0, json_1.JsonDeepClone)(items);
|
|
128
129
|
return await this.queue.Next(async () => {
|
|
129
130
|
if (!this.Has(key))
|
|
130
131
|
throw "Key not found in store";
|
|
131
132
|
const spliceResult = await this.diff.SplicePath(key, start, deleteCount, items);
|
|
132
133
|
this.UpdateRootMap(spliceResult.diffResult);
|
|
133
|
-
this.SpliceRootObject(spliceResult.path[0], spliceResult.start, spliceResult.deleteCount,
|
|
134
|
+
this.SpliceRootObject(spliceResult.path[0], spliceResult.start, spliceResult.deleteCount, items);
|
|
134
135
|
return spliceResult.spliceResult;
|
|
135
136
|
});
|
|
136
137
|
}
|
|
@@ -39,6 +39,7 @@ export declare namespace ObservableNode {
|
|
|
39
39
|
* @returns A proxied version of the value that emits change events.
|
|
40
40
|
*/
|
|
41
41
|
function Create<T>(value: T): T;
|
|
42
|
+
function Snapshot<T>(proxy: T): T | undefined;
|
|
42
43
|
/**
|
|
43
44
|
* Marks an observable node or its property as changed, triggering reactive updates.
|
|
44
45
|
* Used internally to notify dependencies that a value has been modified.
|
|
@@ -6,6 +6,7 @@ const json_2 = require("../../Utils/json");
|
|
|
6
6
|
const observableScope_1 = require("./observableScope");
|
|
7
7
|
const NODE_VALUE = Symbol("NODE_VALUE");
|
|
8
8
|
const NODE_PROXY = Symbol("NODE_PROXY");
|
|
9
|
+
const NODE_SNAPSHOT = Symbol("NODE_SNAPSHOT");
|
|
9
10
|
const toJSON = "toJSON";
|
|
10
11
|
const IS_NODE = Symbol("IS_NODE");
|
|
11
12
|
const OBJECT_SCOPE = Symbol("OBJECT_SCOPE");
|
|
@@ -17,6 +18,24 @@ function Property(value, prop) {
|
|
|
17
18
|
return value[prop];
|
|
18
19
|
}
|
|
19
20
|
const wrapperCache = new WeakMap();
|
|
21
|
+
const valueSnapshotCache = new WeakMap();
|
|
22
|
+
const valueSnapshotHierarchy = new WeakMap();
|
|
23
|
+
function CreateSnapshotLink(child, parent) {
|
|
24
|
+
let parents = valueSnapshotHierarchy.get(child);
|
|
25
|
+
if (!parents)
|
|
26
|
+
valueSnapshotHierarchy.set(child, (parents = new Set()));
|
|
27
|
+
parents.add(parent);
|
|
28
|
+
}
|
|
29
|
+
function InvalidateSnapshotForValue(value) {
|
|
30
|
+
valueSnapshotCache.delete(value);
|
|
31
|
+
const parents = valueSnapshotHierarchy.get(value);
|
|
32
|
+
if (parents === undefined)
|
|
33
|
+
return;
|
|
34
|
+
valueSnapshotHierarchy.delete(value);
|
|
35
|
+
for (const parent of parents)
|
|
36
|
+
if (valueSnapshotCache.has(parent))
|
|
37
|
+
InvalidateSnapshotForValue(parent);
|
|
38
|
+
}
|
|
20
39
|
function getOwnPropertyDescriptor(target, prop) {
|
|
21
40
|
const descriptor = Object.getOwnPropertyDescriptor(target[NODE_VALUE], prop);
|
|
22
41
|
return {
|
|
@@ -93,45 +112,67 @@ function CloneProxy(value, type = (0, json_2.JsonType)(value)) {
|
|
|
93
112
|
function GetPropertyScope(object, prop) {
|
|
94
113
|
return object[prop] ??= observableScope_1.ObservableScope.Basic(Property.bind(null, object[NODE_VALUE], prop));
|
|
95
114
|
}
|
|
115
|
+
function SetObjectValue(object, prop, value) {
|
|
116
|
+
const propExists = Object.hasOwn(object[NODE_VALUE], prop);
|
|
117
|
+
object[NODE_VALUE][prop] = value;
|
|
118
|
+
InvalidateSnapshotForValue(object[NODE_VALUE]);
|
|
119
|
+
observableScope_1.ObservableScope.Update(object[prop]);
|
|
120
|
+
!propExists && observableScope_1.ObservableScope.Update(object[ITERATOR_SCOPE]);
|
|
121
|
+
}
|
|
122
|
+
function SetArrayValue(object, prop, value) {
|
|
123
|
+
object[NODE_VALUE][prop] = value;
|
|
124
|
+
InvalidateSnapshotForValue(object[NODE_VALUE]);
|
|
125
|
+
observableScope_1.ObservableScope.Update(object[OBJECT_SCOPE]);
|
|
126
|
+
}
|
|
96
127
|
function CreateProxyFactory(alias) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
128
|
+
/**
|
|
129
|
+
* An immutable snapshot of a raw node value (arrays and plain objects; other values are
|
|
130
|
+
* returned as they are). A snapshot is cached per raw value in valueSnapshotCache and
|
|
131
|
+
* returned as-is until a write invalidates it: every write path calls Invalidate, which
|
|
132
|
+
* clears the written value and every cached ancestor, found through the parent links
|
|
133
|
+
* recorded here. A rebuild makes new containers but reuses the cached snapshots of
|
|
134
|
+
* unchanged children, so a snapshot handed out never changes and unchanged parts are
|
|
135
|
+
* shared between snapshots. Keyed children are read through their root.
|
|
136
|
+
*/
|
|
137
|
+
function CreateSnapshot(value) {
|
|
138
|
+
if ((0, json_2.JsonType)(value) === "value")
|
|
139
|
+
return value;
|
|
140
|
+
const cached = valueSnapshotCache.get(value);
|
|
141
|
+
if (cached !== undefined)
|
|
142
|
+
return cached;
|
|
143
|
+
let snapshot;
|
|
144
|
+
if (Array.isArray(value)) {
|
|
145
|
+
snapshot = new Array(value.length);
|
|
146
|
+
for (let x = 0; x < value.length; x++)
|
|
147
|
+
snapshot[x] = ChildSnapshot(value, value[x]);
|
|
116
148
|
}
|
|
149
|
+
else {
|
|
150
|
+
snapshot = {};
|
|
151
|
+
const keys = Object.keys(value);
|
|
152
|
+
for (let x = 0; x < keys.length; x++)
|
|
153
|
+
snapshot[keys[x]] = ChildSnapshot(value, value[keys[x]]);
|
|
154
|
+
}
|
|
155
|
+
valueSnapshotCache.set(value, snapshot);
|
|
156
|
+
return snapshot;
|
|
117
157
|
}
|
|
118
|
-
|
|
119
|
-
|
|
158
|
+
/**
|
|
159
|
+
* A child's snapshot, linking the child to its parent so a write to the child
|
|
160
|
+
* invalidates the parent. A keyed child's snapshot comes from its root, so the root is
|
|
161
|
+
* linked too; the parent's own embedded copy stays linked because a positional write
|
|
162
|
+
* (one that changes which entity a slot holds) mutates that copy in place.
|
|
163
|
+
*/
|
|
164
|
+
function ChildSnapshot(parent, child) {
|
|
165
|
+
if ((0, json_2.JsonType)(child) === "value")
|
|
166
|
+
return child;
|
|
167
|
+
CreateSnapshotLink(child, parent);
|
|
168
|
+
const resolved = alias?.(child, false);
|
|
169
|
+
if (resolved !== undefined && resolved !== child) {
|
|
170
|
+
CreateSnapshotLink(resolved, parent);
|
|
171
|
+
return CreateSnapshot(resolved);
|
|
172
|
+
}
|
|
173
|
+
return CreateSnapshot(child);
|
|
120
174
|
}
|
|
121
|
-
const ToJson = alias !== undefined ? ToJsonCopy : ToJsonDefault;
|
|
122
175
|
const readOnly = alias !== undefined;
|
|
123
|
-
function SetObjectValue(object, prop, value) {
|
|
124
|
-
object[NODE_VALUE][prop] = value;
|
|
125
|
-
observableScope_1.ObservableScope.Update(object[prop]);
|
|
126
|
-
}
|
|
127
|
-
function SetArrayValue(object, prop, value) {
|
|
128
|
-
object[NODE_VALUE][prop] = value;
|
|
129
|
-
observableScope_1.ObservableScope.Update(object[OBJECT_SCOPE]);
|
|
130
|
-
}
|
|
131
|
-
function CreateProxy(value) {
|
|
132
|
-
value = UnwrapProxy(value);
|
|
133
|
-
return CreateProxyFromValue(value);
|
|
134
|
-
}
|
|
135
176
|
function CreateArrayProxy(value) {
|
|
136
177
|
const wrapper = Object.assign([], {
|
|
137
178
|
[NODE_VALUE]: value,
|
|
@@ -172,10 +213,12 @@ function CreateProxyFactory(alias) {
|
|
|
172
213
|
return true;
|
|
173
214
|
case toJSON:
|
|
174
215
|
return function () {
|
|
175
|
-
return
|
|
216
|
+
return CreateSnapshot(object[NODE_VALUE]);
|
|
176
217
|
};
|
|
177
218
|
case NODE_VALUE:
|
|
178
219
|
return object[NODE_VALUE];
|
|
220
|
+
case NODE_SNAPSHOT:
|
|
221
|
+
return CreateSnapshot(object[NODE_VALUE]);
|
|
179
222
|
default: {
|
|
180
223
|
const scope = object[OBJECT_SCOPE];
|
|
181
224
|
const array = observableScope_1.ObservableScope.Value(scope);
|
|
@@ -199,6 +242,7 @@ function CreateProxyFactory(alias) {
|
|
|
199
242
|
array.length = proxyArray.length;
|
|
200
243
|
for (let x = 0; x < proxyArray.length; x++)
|
|
201
244
|
array[x] = UnwrapProxy(proxyArray[x]);
|
|
245
|
+
InvalidateSnapshotForValue(object[NODE_VALUE]);
|
|
202
246
|
observableScope_1.ObservableScope.Update(scope);
|
|
203
247
|
break;
|
|
204
248
|
}
|
|
@@ -237,9 +281,11 @@ function CreateProxyFactory(alias) {
|
|
|
237
281
|
switch (prop) {
|
|
238
282
|
case IS_NODE:
|
|
239
283
|
return true;
|
|
284
|
+
case NODE_SNAPSHOT:
|
|
285
|
+
return CreateSnapshot(object[NODE_VALUE]);
|
|
240
286
|
case toJSON:
|
|
241
287
|
return function () {
|
|
242
|
-
return
|
|
288
|
+
return CreateSnapshot(object[NODE_VALUE]);
|
|
243
289
|
};
|
|
244
290
|
case NODE_VALUE:
|
|
245
291
|
return object[NODE_VALUE];
|
|
@@ -334,6 +380,12 @@ var ObservableNode;
|
|
|
334
380
|
return DefaultCreateProxy(value);
|
|
335
381
|
}
|
|
336
382
|
ObservableNode.Create = Create;
|
|
383
|
+
function Snapshot(proxy) {
|
|
384
|
+
if (proxy[IS_NODE])
|
|
385
|
+
return proxy[NODE_SNAPSHOT];
|
|
386
|
+
return undefined;
|
|
387
|
+
}
|
|
388
|
+
ObservableNode.Snapshot = Snapshot;
|
|
337
389
|
/**
|
|
338
390
|
* Marks an observable node or its property as changed, triggering reactive updates.
|
|
339
391
|
* Used internally to notify dependencies that a value has been modified.
|
|
@@ -349,23 +401,18 @@ var ObservableNode;
|
|
|
349
401
|
}
|
|
350
402
|
ObservableNode.Update = Update;
|
|
351
403
|
function Assign(value, prop, propValue) {
|
|
352
|
-
const propExists = Object.hasOwn(value, prop);
|
|
353
|
-
value[prop] = propValue;
|
|
404
|
+
// const propExists = Object.hasOwn(value as Object, prop);
|
|
405
|
+
// value[prop] = propValue;
|
|
354
406
|
const wrapper = wrapperCache.get(value);
|
|
355
407
|
if (wrapper) {
|
|
356
408
|
if (Array.isArray(wrapper))
|
|
357
|
-
|
|
358
|
-
else
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
observableScope_1.ObservableScope.Update(scope);
|
|
365
|
-
}
|
|
366
|
-
else
|
|
367
|
-
observableScope_1.ObservableScope.Update(wrapper[ITERATOR_SCOPE]);
|
|
368
|
-
}
|
|
409
|
+
SetArrayValue(wrapper, prop, propValue);
|
|
410
|
+
else
|
|
411
|
+
SetObjectValue(wrapper, prop, propValue);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
InvalidateSnapshotForValue(value);
|
|
415
|
+
value[prop] = propValue;
|
|
369
416
|
}
|
|
370
417
|
}
|
|
371
418
|
ObservableNode.Assign = Assign;
|
|
@@ -411,6 +458,7 @@ var ObservableNode;
|
|
|
411
458
|
ObservableNode.Apply = Apply;
|
|
412
459
|
function ApplySplice(rootNode, start, deleteCount, items, cloneData = true) {
|
|
413
460
|
const root = rootNode[NODE_VALUE];
|
|
461
|
+
InvalidateSnapshotForValue(rootNode[NODE_VALUE]);
|
|
414
462
|
const addItems = cloneData ? (0, json_1.JsonDeepClone)(items) : items;
|
|
415
463
|
root.splice(start, deleteCount, ...addItems);
|
|
416
464
|
ObservableNode.Update(root);
|
|
@@ -426,6 +474,7 @@ var ObservableNode;
|
|
|
426
474
|
const root = rootNode[NODE_VALUE];
|
|
427
475
|
if (diffResult.length === 1 && diffResult[0].path.length === 0) {
|
|
428
476
|
// Replacing rootNode
|
|
477
|
+
InvalidateSnapshotForValue(root);
|
|
429
478
|
const rootPatch = cloneData ? (0, json_1.JsonDeepClone)(diffResult[0].value) : diffResult[0].value;
|
|
430
479
|
const rootType = (0, json_2.JsonType)(root);
|
|
431
480
|
const rootPatchType = (0, json_2.JsonType)(rootPatch);
|