j-templates 7.0.89 → 7.0.91
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/DOM/createAssignment.d.ts +3 -0
- package/DOM/createAssignment.js +6 -0
- package/DOM/createAttributeAssignment.d.ts +1 -0
- package/DOM/createAttributeAssignment.js +4 -0
- package/DOM/createEventAssignment.d.ts +1 -0
- package/DOM/createEventAssignment.js +4 -0
- package/DOM/createPropertyAssignment.d.ts +1 -0
- package/DOM/createPropertyAssignment.js +29 -0
- package/DOM/domNodeConfig.js +45 -31
- package/Node/component.js +2 -0
- package/Node/nodeConfig.d.ts +3 -0
- package/Node/vNode.js +61 -160
- package/Node/vNode.types.d.ts +1 -5
- package/Store/Store/store.js +1 -1
- package/Store/Store/storeAsync.js +1 -1
- package/Store/Store/storeSync.js +3 -3
- package/Store/Tree/observableNode.d.ts +1 -15
- package/Store/Tree/observableNode.js +131 -112
- package/Store/Tree/observableScope.d.ts +33 -12
- package/Store/Tree/observableScope.js +170 -55
- package/Utils/decorators.js +4 -4
- package/Utils/emitter.d.ts +1 -1
- package/Utils/emitter.js +45 -14
- package/Utils/functions.js +1 -1
- package/Utils/json.js +3 -3
- package/index.d.ts +1 -1
- package/index.js +2 -1
- package/package.json +1 -1
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ObservableScope = void 0;
|
|
4
4
|
exports.InlineScope = InlineScope;
|
|
5
|
+
exports.MappedScope = MappedScope;
|
|
5
6
|
exports.GateScope = GateScope;
|
|
6
7
|
exports.PeekScope = PeekScope;
|
|
7
8
|
const emitter_1 = require("../../Utils/emitter");
|
|
8
9
|
const functions_1 = require("../../Utils/functions");
|
|
10
|
+
function Invoke(param, callback) {
|
|
11
|
+
return callback(param);
|
|
12
|
+
}
|
|
9
13
|
/**
|
|
10
14
|
* Creates a dynamic (reactive) observable scope.
|
|
11
15
|
* @template T The type of value stored in the scope.
|
|
@@ -19,6 +23,7 @@ function CreateDynamicScope(getFunction, greedy, value) {
|
|
|
19
23
|
const scope = {
|
|
20
24
|
type: "dynamic",
|
|
21
25
|
async,
|
|
26
|
+
pending: null,
|
|
22
27
|
greedy: greedy || async,
|
|
23
28
|
dirty: false,
|
|
24
29
|
destroyed: false,
|
|
@@ -27,12 +32,22 @@ function CreateDynamicScope(getFunction, greedy, value) {
|
|
|
27
32
|
value,
|
|
28
33
|
emitter: emitter_1.Emitter.Create(),
|
|
29
34
|
emitters: null,
|
|
35
|
+
onUpdated: null,
|
|
30
36
|
onDestroyed: null,
|
|
31
37
|
scopes: null,
|
|
38
|
+
mappedScopes: null,
|
|
32
39
|
};
|
|
33
40
|
scope.setCallback = OnSet.bind(scope);
|
|
34
41
|
return scope;
|
|
35
42
|
}
|
|
43
|
+
function CreateBasicScope(getFunction) {
|
|
44
|
+
return {
|
|
45
|
+
type: "basic",
|
|
46
|
+
getFunction,
|
|
47
|
+
emitter: emitter_1.Emitter.Create(),
|
|
48
|
+
destroyed: false
|
|
49
|
+
};
|
|
50
|
+
}
|
|
36
51
|
/**
|
|
37
52
|
* Creates a static (non-reactive) observable scope.
|
|
38
53
|
* Static scopes are optimized for values that never change and don't need dependency tracking.
|
|
@@ -44,6 +59,8 @@ function CreateStaticScope(initialValue) {
|
|
|
44
59
|
return {
|
|
45
60
|
type: "static",
|
|
46
61
|
value: initialValue,
|
|
62
|
+
onDestroyed: null,
|
|
63
|
+
destroyed: false
|
|
47
64
|
};
|
|
48
65
|
}
|
|
49
66
|
let scopeQueue = [];
|
|
@@ -80,7 +97,7 @@ function OnSetQueued(scope) {
|
|
|
80
97
|
* @returns true if the scope is static or destroyed, false if queued or non-greedy scope emitted.
|
|
81
98
|
*/
|
|
82
99
|
function OnSet() {
|
|
83
|
-
if (this.dirty)
|
|
100
|
+
if (this.dirty || this.destroyed)
|
|
84
101
|
return;
|
|
85
102
|
this.dirty = true;
|
|
86
103
|
if (this.greedy) {
|
|
@@ -172,6 +189,8 @@ function RegisterScope(scope) {
|
|
|
172
189
|
* @returns The scope's current value.
|
|
173
190
|
*/
|
|
174
191
|
function GetScopeValue(scope) {
|
|
192
|
+
if (scope.type === "basic")
|
|
193
|
+
return scope.getFunction();
|
|
175
194
|
if (scope.type === "static" || !scope.dirty || scope.destroyed)
|
|
176
195
|
return scope.value;
|
|
177
196
|
ExecuteScope(scope);
|
|
@@ -194,15 +213,17 @@ let watchState = null;
|
|
|
194
213
|
* @param currentCalc Optional map of existing inline scopes to reuse.
|
|
195
214
|
* @returns The watch state containing tracked dependencies and result.
|
|
196
215
|
*/
|
|
197
|
-
function WatchFunction(callback,
|
|
216
|
+
function WatchFunction(callback, currentScopes, currentMappedScopes, initialEmitters) {
|
|
198
217
|
const parent = watchState;
|
|
199
218
|
watchState = {
|
|
200
219
|
emitterIndex: 0,
|
|
201
220
|
value: null,
|
|
202
221
|
emitters: initialEmitters,
|
|
203
222
|
emitterSet: null,
|
|
204
|
-
|
|
205
|
-
|
|
223
|
+
currentScopes,
|
|
224
|
+
nextScopes: null,
|
|
225
|
+
currentMappedScopes: currentMappedScopes,
|
|
226
|
+
nextMappedScopes: null,
|
|
206
227
|
strategy: initialEmitters === null ? INIT_STRATEGY : SAME_STRATEGY,
|
|
207
228
|
};
|
|
208
229
|
watchState.value = callback();
|
|
@@ -222,23 +243,35 @@ function WatchFunction(callback, currentCalc, initialEmitters) {
|
|
|
222
243
|
*/
|
|
223
244
|
function ExecuteScope(scope) {
|
|
224
245
|
scope.dirty = false;
|
|
225
|
-
const state = WatchFunction(scope.getFunction, scope.scopes, scope.emitters);
|
|
246
|
+
const state = WatchFunction(scope.getFunction, scope.scopes, scope.mappedScopes, scope.emitters);
|
|
226
247
|
UpdateEmitters(scope, state);
|
|
227
|
-
const
|
|
228
|
-
scope.scopes = state.
|
|
229
|
-
|
|
230
|
-
|
|
248
|
+
const currentScopes = state.currentScopes;
|
|
249
|
+
scope.scopes = state.nextScopes;
|
|
250
|
+
const currentMappedScopes = state.currentMappedScopes;
|
|
251
|
+
scope.mappedScopes = state.nextMappedScopes;
|
|
252
|
+
if (currentScopes)
|
|
253
|
+
for (let x = 0; x < currentScopes.length; x++)
|
|
254
|
+
currentScopes[x] && DestroyScope(currentScopes[x][1]);
|
|
255
|
+
if (currentMappedScopes && currentMappedScopes.size > 0)
|
|
256
|
+
for (const scopes of currentMappedScopes.values())
|
|
257
|
+
DestroyAllScopes(scopes);
|
|
231
258
|
if (scope.async) {
|
|
232
|
-
const promise = state.value;
|
|
259
|
+
const promise = (scope.pending = state.value);
|
|
233
260
|
promise.then(function (result) {
|
|
234
|
-
if (
|
|
261
|
+
if (scope.destroyed || scope.pending !== promise)
|
|
235
262
|
return;
|
|
263
|
+
scope.pending = null;
|
|
264
|
+
const lastValue = scope.value;
|
|
236
265
|
scope.value = result;
|
|
266
|
+
scope.onUpdated && emitter_1.Emitter.Emit(scope.onUpdated, lastValue, scope);
|
|
237
267
|
emitter_1.Emitter.Emit(scope.emitter, scope);
|
|
238
268
|
});
|
|
239
269
|
}
|
|
240
|
-
else
|
|
270
|
+
else {
|
|
271
|
+
const lastValue = scope.value;
|
|
241
272
|
scope.value = state.value;
|
|
273
|
+
scope.onUpdated && emitter_1.Emitter.Emit(scope.onUpdated, lastValue, scope);
|
|
274
|
+
}
|
|
242
275
|
}
|
|
243
276
|
/**
|
|
244
277
|
* Creates a scope from a function, choosing between static and dynamic based on dependencies.
|
|
@@ -248,18 +281,20 @@ function ExecuteScope(scope) {
|
|
|
248
281
|
* @param allowStatic Whether to return a static scope if no dependencies are found.
|
|
249
282
|
* @returns A new observable scope.
|
|
250
283
|
*/
|
|
251
|
-
function ExecuteFunction(callback, greedy
|
|
284
|
+
function ExecuteFunction(callback, greedy) {
|
|
252
285
|
const async = (0, functions_1.IsAsync)(callback);
|
|
253
|
-
const state = WatchFunction(callback, null, null);
|
|
254
|
-
if (
|
|
286
|
+
const state = WatchFunction(callback, null, null, null);
|
|
287
|
+
if (async || state.emitters !== null) {
|
|
255
288
|
const scope = CreateDynamicScope(callback, greedy, async ? null : state.value);
|
|
256
|
-
scope.scopes = state.
|
|
289
|
+
scope.scopes = state.nextScopes;
|
|
290
|
+
scope.mappedScopes = state.nextMappedScopes;
|
|
257
291
|
UpdateEmitters(scope, state);
|
|
258
292
|
if (async) {
|
|
259
|
-
const promise = state.value;
|
|
293
|
+
const promise = (scope.pending = state.value);
|
|
260
294
|
promise.then(function (result) {
|
|
261
|
-
if (
|
|
295
|
+
if (scope.destroyed || scope.pending !== promise)
|
|
262
296
|
return;
|
|
297
|
+
scope.pending = null;
|
|
263
298
|
scope.value = result;
|
|
264
299
|
emitter_1.Emitter.Emit(scope.emitter, scope);
|
|
265
300
|
});
|
|
@@ -269,17 +304,57 @@ function ExecuteFunction(callback, greedy, allowStatic) {
|
|
|
269
304
|
const value = state.value;
|
|
270
305
|
return CreateStaticScope(value);
|
|
271
306
|
}
|
|
272
|
-
function ScopeHelper(callback,
|
|
273
|
-
const nextScopes = (watchState.
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
307
|
+
function ScopeHelper(callback, key, greedy) {
|
|
308
|
+
const nextScopes = (watchState.nextScopes ??= []);
|
|
309
|
+
const currentScopes = watchState.currentScopes;
|
|
310
|
+
let x = 0;
|
|
311
|
+
if (currentScopes)
|
|
312
|
+
for (; x < currentScopes.length && (currentScopes[x] === null || currentScopes[x][0] !== key); x++) { }
|
|
313
|
+
if (!currentScopes || x === currentScopes.length) {
|
|
314
|
+
const nextScope = ExecuteFunction(callback, greedy);
|
|
315
|
+
nextScopes.push([key, nextScope]);
|
|
316
|
+
return nextScope;
|
|
317
|
+
}
|
|
318
|
+
const nextScopePair = currentScopes[x];
|
|
319
|
+
currentScopes[x] = null;
|
|
320
|
+
nextScopes.push(nextScopePair);
|
|
321
|
+
return nextScopePair[1];
|
|
282
322
|
}
|
|
323
|
+
function MappedScopeHelper(callback, data, onUpdated, onDestroyed) {
|
|
324
|
+
const nextScopes = (watchState.nextMappedScopes ??= new Map());
|
|
325
|
+
const currentScopes = watchState.currentMappedScopes;
|
|
326
|
+
if (currentScopes?.has(data)) {
|
|
327
|
+
const nextScopeArray = currentScopes.get(data);
|
|
328
|
+
if (nextScopeArray.length === 1) {
|
|
329
|
+
currentScopes.delete(data);
|
|
330
|
+
nextScopes.set(data, nextScopeArray);
|
|
331
|
+
return nextScopeArray[0];
|
|
332
|
+
}
|
|
333
|
+
const nullIndex = nextScopeArray.lastIndexOf(null);
|
|
334
|
+
const valueIndex = nullIndex < 0 ? 0 : nullIndex + 1;
|
|
335
|
+
if (valueIndex === nextScopeArray.length - 1)
|
|
336
|
+
currentScopes.delete(data);
|
|
337
|
+
else {
|
|
338
|
+
const scope = nextScopeArray[valueIndex];
|
|
339
|
+
nextScopeArray[valueIndex] = null;
|
|
340
|
+
const scopes = nextScopes.get(data) ?? [];
|
|
341
|
+
scopes.push(scope);
|
|
342
|
+
nextScopes.set(data, scopes);
|
|
343
|
+
return scope;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const getFunction = Invoke.bind(null, data, callback);
|
|
347
|
+
const scope = ExecuteFunction(getFunction, false);
|
|
348
|
+
onUpdated && ObservableScope.OnUpdated(scope, onUpdated);
|
|
349
|
+
onDestroyed && ObservableScope.OnDestroyed(scope, onDestroyed);
|
|
350
|
+
const scopes = nextScopes.get(data) ?? [];
|
|
351
|
+
scopes.push(scope);
|
|
352
|
+
nextScopes.set(data, scopes);
|
|
353
|
+
return scope;
|
|
354
|
+
}
|
|
355
|
+
const SCOPE_DEFAULT = Symbol("SCOPE_DEFAULT");
|
|
356
|
+
const GATE_DEFAULT = Symbol("GATE_DEFAULT");
|
|
357
|
+
const PEEK_DEFAULT = Symbol("PEEK_DEFAULT");
|
|
283
358
|
/**
|
|
284
359
|
* Creates an inline computed scope registered as a dependency of the parent.
|
|
285
360
|
* The scope is memoized by ID and reused across reads within the same parent evaluation.
|
|
@@ -300,11 +375,19 @@ function InlineScope(callback, idOverride) {
|
|
|
300
375
|
if (watchState === null) {
|
|
301
376
|
throw new Error("scope() must be called within a watch context");
|
|
302
377
|
}
|
|
303
|
-
const id = idOverride ??
|
|
378
|
+
const id = idOverride ?? SCOPE_DEFAULT;
|
|
304
379
|
const scope = ScopeHelper(callback, id, false);
|
|
305
380
|
RegisterScope(scope);
|
|
306
381
|
return GetScopeValue(scope);
|
|
307
382
|
}
|
|
383
|
+
function MappedScope(data, callback, onUpdated, onDestroyed) {
|
|
384
|
+
if (watchState === null) {
|
|
385
|
+
throw new Error("scope() must be called within a watch context");
|
|
386
|
+
}
|
|
387
|
+
const scope = MappedScopeHelper(callback, data, onUpdated, onDestroyed);
|
|
388
|
+
RegisterScope(scope);
|
|
389
|
+
return GetScopeValue(scope);
|
|
390
|
+
}
|
|
308
391
|
/**
|
|
309
392
|
* Creates a gatekeeper scope that only emits when the value actually changes (===).
|
|
310
393
|
* Prevents unnecessary downstream re-evaluations when the derived value stays the same.
|
|
@@ -327,7 +410,7 @@ function GateScope(callback, idOverride) {
|
|
|
327
410
|
if (watchState === null) {
|
|
328
411
|
throw new Error("gate() must be called within a watch context");
|
|
329
412
|
}
|
|
330
|
-
const id = idOverride ??
|
|
413
|
+
const id = idOverride ?? GATE_DEFAULT;
|
|
331
414
|
const scope = ScopeHelper(callback, id, true);
|
|
332
415
|
RegisterScope(scope);
|
|
333
416
|
return GetScopeValue(scope);
|
|
@@ -356,7 +439,7 @@ function PeekScope(callback, idOverride) {
|
|
|
356
439
|
if (watchState === null) {
|
|
357
440
|
throw new Error("peek() must be called within a watch context");
|
|
358
441
|
}
|
|
359
|
-
const id = idOverride ??
|
|
442
|
+
const id = idOverride ?? PEEK_DEFAULT;
|
|
360
443
|
const scope = ScopeHelper(callback, id, false);
|
|
361
444
|
return GetScopeValue(scope);
|
|
362
445
|
}
|
|
@@ -417,22 +500,38 @@ function DestroyAllScopes(scopes) {
|
|
|
417
500
|
* @param scope The scope to destroy.
|
|
418
501
|
*/
|
|
419
502
|
function DestroyScope(scope) {
|
|
420
|
-
if (!scope || scope.
|
|
503
|
+
if (!scope || scope.destroyed)
|
|
421
504
|
return;
|
|
422
|
-
emitter_1.Emitter.Clear(scope.emitter);
|
|
423
|
-
for (const key in scope.scopes)
|
|
424
|
-
DestroyScope(scope.scopes[key]);
|
|
425
|
-
if (scope.emitters !== null)
|
|
426
|
-
for (let x = 0; x < scope.emitters.length; x++)
|
|
427
|
-
emitter_1.Emitter.Remove(scope.emitters[x], scope.setCallback);
|
|
428
|
-
scope.value = undefined;
|
|
429
|
-
scope.scopes = null;
|
|
430
|
-
scope.emitters = null;
|
|
431
|
-
scope.emitter = null;
|
|
432
|
-
scope.getFunction = null;
|
|
433
|
-
scope.setCallback = null;
|
|
434
505
|
scope.destroyed = true;
|
|
435
|
-
|
|
506
|
+
switch (scope.type) {
|
|
507
|
+
case "basic": {
|
|
508
|
+
scope.emitter = null;
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
case "dynamic": {
|
|
512
|
+
if (scope.scopes)
|
|
513
|
+
for (let x = 0; x < scope.scopes.length; x++)
|
|
514
|
+
DestroyScope(scope.scopes[x][1]);
|
|
515
|
+
if (scope.mappedScopes && scope.mappedScopes.size > 0)
|
|
516
|
+
for (const childScopes of scope.mappedScopes.values())
|
|
517
|
+
DestroyAllScopes(childScopes);
|
|
518
|
+
if (scope.emitters !== null)
|
|
519
|
+
for (let x = 0; x < scope.emitters.length; x++)
|
|
520
|
+
emitter_1.Emitter.Remove(scope.emitters[x], scope.setCallback);
|
|
521
|
+
scope.scopes = null;
|
|
522
|
+
scope.mappedScopes = null;
|
|
523
|
+
scope.emitters = null;
|
|
524
|
+
scope.emitter = null;
|
|
525
|
+
scope.getFunction = null;
|
|
526
|
+
scope.setCallback = null;
|
|
527
|
+
}
|
|
528
|
+
case "static": {
|
|
529
|
+
const lastValue = scope.value;
|
|
530
|
+
scope.value = undefined;
|
|
531
|
+
scope.onDestroyed && emitter_1.Emitter.Emit(scope.onDestroyed, lastValue);
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
436
535
|
}
|
|
437
536
|
var ObservableScope;
|
|
438
537
|
(function (ObservableScope) {
|
|
@@ -444,10 +543,18 @@ var ObservableScope;
|
|
|
444
543
|
* @param force If true, always creates a dynamic scope even without dependencies. Defaults to false.
|
|
445
544
|
* @returns A new observable scope.
|
|
446
545
|
*/
|
|
447
|
-
function Create(valueFunction
|
|
448
|
-
return ExecuteFunction(valueFunction,
|
|
546
|
+
function Create(valueFunction) {
|
|
547
|
+
return ExecuteFunction(valueFunction, false);
|
|
449
548
|
}
|
|
450
549
|
ObservableScope.Create = Create;
|
|
550
|
+
function Greedy(valueFunction) {
|
|
551
|
+
return ExecuteFunction(valueFunction, true);
|
|
552
|
+
}
|
|
553
|
+
ObservableScope.Greedy = Greedy;
|
|
554
|
+
function Basic(valueFunction) {
|
|
555
|
+
return CreateBasicScope(valueFunction);
|
|
556
|
+
}
|
|
557
|
+
ObservableScope.Basic = Basic;
|
|
451
558
|
/**
|
|
452
559
|
* Registers an emitter as a dependency for the current watch context.
|
|
453
560
|
* @param emitter The emitter to register as a dependency.
|
|
@@ -473,7 +580,7 @@ var ObservableScope;
|
|
|
473
580
|
* @returns The scope's current value.
|
|
474
581
|
*/
|
|
475
582
|
function Value(scope) {
|
|
476
|
-
if (!scope)
|
|
583
|
+
if (!scope || scope.destroyed)
|
|
477
584
|
return undefined;
|
|
478
585
|
Touch(scope);
|
|
479
586
|
return Peek(scope);
|
|
@@ -485,7 +592,7 @@ var ObservableScope;
|
|
|
485
592
|
* @param scope The scope to register as a dependency.
|
|
486
593
|
*/
|
|
487
594
|
function Touch(scope) {
|
|
488
|
-
if (!scope)
|
|
595
|
+
if (!scope || scope.destroyed)
|
|
489
596
|
return;
|
|
490
597
|
RegisterScope(scope);
|
|
491
598
|
}
|
|
@@ -497,7 +604,7 @@ var ObservableScope;
|
|
|
497
604
|
* @param callback Function to invoke when the scope's value changes.
|
|
498
605
|
*/
|
|
499
606
|
function Watch(scope, callback) {
|
|
500
|
-
if (!scope || scope.type === "static")
|
|
607
|
+
if (!scope || scope.destroyed || scope.type === "static")
|
|
501
608
|
return;
|
|
502
609
|
emitter_1.Emitter.On(scope.emitter, callback);
|
|
503
610
|
}
|
|
@@ -509,19 +616,24 @@ var ObservableScope;
|
|
|
509
616
|
* @param callback The callback function to remove.
|
|
510
617
|
*/
|
|
511
618
|
function Unwatch(scope, callback) {
|
|
512
|
-
if (!scope || scope.type === "static")
|
|
619
|
+
if (!scope || scope.destroyed || scope.type === "static")
|
|
513
620
|
return;
|
|
514
621
|
emitter_1.Emitter.Remove(scope.emitter, callback);
|
|
515
622
|
}
|
|
516
623
|
ObservableScope.Unwatch = Unwatch;
|
|
624
|
+
function OnUpdated(scope, callback) {
|
|
625
|
+
if (scope.type !== "dynamic")
|
|
626
|
+
return;
|
|
627
|
+
scope.onUpdated ??= emitter_1.Emitter.Create();
|
|
628
|
+
emitter_1.Emitter.On(scope.onUpdated, callback);
|
|
629
|
+
}
|
|
630
|
+
ObservableScope.OnUpdated = OnUpdated;
|
|
517
631
|
/**
|
|
518
632
|
* Registers a callback to be invoked when the scope is destroyed.
|
|
519
633
|
* @param scope The scope to monitor for destruction.
|
|
520
634
|
* @param callback Function to invoke when the scope is destroyed.
|
|
521
635
|
*/
|
|
522
636
|
function OnDestroyed(scope, callback) {
|
|
523
|
-
if (scope.type === "static")
|
|
524
|
-
return;
|
|
525
637
|
scope.onDestroyed ??= emitter_1.Emitter.Create();
|
|
526
638
|
emitter_1.Emitter.On(scope.onDestroyed, callback);
|
|
527
639
|
}
|
|
@@ -531,9 +643,12 @@ var ObservableScope;
|
|
|
531
643
|
* @param scope The scope to mark for update.
|
|
532
644
|
*/
|
|
533
645
|
function Update(scope) {
|
|
534
|
-
if (!scope || scope.type === "static")
|
|
646
|
+
if (!scope || scope.destroyed || scope.type === "static")
|
|
535
647
|
return;
|
|
536
|
-
|
|
648
|
+
if (scope.type === "basic") {
|
|
649
|
+
emitter_1.Emitter.Emit(scope.emitter, this);
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
537
652
|
scope.setCallback();
|
|
538
653
|
}
|
|
539
654
|
ObservableScope.Update = Update;
|
package/Utils/decorators.js
CHANGED
|
@@ -134,7 +134,7 @@ function GetDestroyArrayForPrototype(prototype, create = true) {
|
|
|
134
134
|
return array;
|
|
135
135
|
}
|
|
136
136
|
function CreateComputedScope(getter, store, defaultValue) {
|
|
137
|
-
const getterScope = observableScope_1.ObservableScope.
|
|
137
|
+
const getterScope = observableScope_1.ObservableScope.Greedy(getter);
|
|
138
138
|
observableScope_1.ObservableScope.Watch(getterScope, (scope) => {
|
|
139
139
|
const data = observableScope_1.ObservableScope.Peek(scope);
|
|
140
140
|
store.Write(data, "root");
|
|
@@ -566,9 +566,9 @@ function Value() {
|
|
|
566
566
|
* @returns An observable scope created from the tuple's value.
|
|
567
567
|
*/
|
|
568
568
|
function CreateValueScope(tuple) {
|
|
569
|
-
return observableScope_1.ObservableScope.
|
|
569
|
+
return observableScope_1.ObservableScope.Basic(function () {
|
|
570
570
|
return tuple[1];
|
|
571
|
-
}
|
|
571
|
+
});
|
|
572
572
|
}
|
|
573
573
|
/**
|
|
574
574
|
* Value decorator implementation for creating value properties.
|
|
@@ -814,7 +814,7 @@ function WatchDecorator(target, propertyKey, descriptor, scopeFunction) {
|
|
|
814
814
|
function scopeFunctionWrapper() {
|
|
815
815
|
return scopeFunction(instance);
|
|
816
816
|
}
|
|
817
|
-
const scope = observableScope_1.ObservableScope.
|
|
817
|
+
const scope = observableScope_1.ObservableScope.Greedy(scopeFunctionWrapper);
|
|
818
818
|
const propertyMap = GetScopeMapForInstance(this);
|
|
819
819
|
propertyMap[propertyKey] = [scope, undefined];
|
|
820
820
|
observableScope_1.ObservableScope.Watch(scope, function (scope) {
|
package/Utils/emitter.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type EmitterCallback<T extends readonly any[] = any[]> = (...args: T) => void;
|
|
2
|
-
export type Emitter = EmitterCallback[];
|
|
2
|
+
export type Emitter = [number, ...EmitterCallback[]];
|
|
3
3
|
export declare namespace Emitter {
|
|
4
4
|
function Create(): Emitter;
|
|
5
5
|
function On(emitter: Emitter, callback: EmitterCallback): void;
|
package/Utils/emitter.js
CHANGED
|
@@ -1,10 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Emitter = void 0;
|
|
4
|
+
const scheduleCallback = typeof requestIdleCallback !== "undefined"
|
|
5
|
+
? requestIdleCallback
|
|
6
|
+
: setTimeout;
|
|
7
|
+
const pendingCompactEmitters = new Set();
|
|
8
|
+
function Compact(emitter) {
|
|
9
|
+
if (emitter.length === 1 || emitter[0] === 0)
|
|
10
|
+
return;
|
|
11
|
+
pendingCompactEmitters.add(emitter);
|
|
12
|
+
ScheduleCompact();
|
|
13
|
+
}
|
|
14
|
+
let compactScheduled = false;
|
|
15
|
+
function ScheduleCompact() {
|
|
16
|
+
if (compactScheduled)
|
|
17
|
+
return;
|
|
18
|
+
compactScheduled = true;
|
|
19
|
+
scheduleCallback(PerformCompact);
|
|
20
|
+
}
|
|
21
|
+
function PerformCompact() {
|
|
22
|
+
compactScheduled = false;
|
|
23
|
+
let compactEmitters = Array.from(pendingCompactEmitters);
|
|
24
|
+
pendingCompactEmitters.clear();
|
|
25
|
+
for (let x = 0; x < compactEmitters.length; x++)
|
|
26
|
+
CompactEmitter(compactEmitters[x]);
|
|
27
|
+
}
|
|
28
|
+
function CompactEmitter(emitter) {
|
|
29
|
+
if (emitter[0] === 0)
|
|
30
|
+
return;
|
|
31
|
+
emitter.splice(1, emitter[0]);
|
|
32
|
+
emitter[0] = 0;
|
|
33
|
+
}
|
|
4
34
|
var Emitter;
|
|
5
35
|
(function (Emitter) {
|
|
6
36
|
function Create() {
|
|
7
|
-
return [];
|
|
37
|
+
return [0];
|
|
8
38
|
}
|
|
9
39
|
Emitter.Create = Create;
|
|
10
40
|
function On(emitter, callback) {
|
|
@@ -12,25 +42,26 @@ var Emitter;
|
|
|
12
42
|
}
|
|
13
43
|
Emitter.On = On;
|
|
14
44
|
function Emit(emitter, ...args) {
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
if (emitter[x] !== null) {
|
|
18
|
-
emitter[x](...args);
|
|
19
|
-
emitter[writePos++] = emitter[x];
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
if (writePos < emitter.length)
|
|
23
|
-
emitter.splice(writePos);
|
|
45
|
+
for (let x = emitter[0] + 1; x < emitter.length; x++)
|
|
46
|
+
emitter[x](...args);
|
|
24
47
|
}
|
|
25
48
|
Emitter.Emit = Emit;
|
|
26
49
|
function Remove(emitter, callback) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
50
|
+
if (emitter.length === 1)
|
|
51
|
+
return;
|
|
52
|
+
const startIndex = emitter[0] + 1;
|
|
53
|
+
const index = emitter.indexOf(callback, startIndex);
|
|
54
|
+
if (index > 0) {
|
|
55
|
+
emitter[0]++;
|
|
56
|
+
emitter[index] = emitter[startIndex];
|
|
57
|
+
emitter[startIndex] = null;
|
|
58
|
+
Compact(emitter);
|
|
59
|
+
}
|
|
30
60
|
}
|
|
31
61
|
Emitter.Remove = Remove;
|
|
32
62
|
function Clear(emitter) {
|
|
33
|
-
emitter.splice(
|
|
63
|
+
emitter.length > 1 && emitter.splice(1);
|
|
64
|
+
emitter[0] = 0;
|
|
34
65
|
}
|
|
35
66
|
Emitter.Clear = Clear;
|
|
36
67
|
})(Emitter || (exports.Emitter = Emitter = {}));
|
package/Utils/functions.js
CHANGED
package/Utils/json.js
CHANGED
|
@@ -55,9 +55,9 @@ function JsonDiffFactory() {
|
|
|
55
55
|
case "array": {
|
|
56
56
|
const typedSource = source;
|
|
57
57
|
const typedPatch = patch;
|
|
58
|
-
const result = typedPatch.
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
const result = new Array(typedPatch.length);
|
|
59
|
+
for (let x = 0; x < typedPatch.length; x++)
|
|
60
|
+
result[x] = JsonMerge(typedSource[x], typedPatch[x]);
|
|
61
61
|
return result;
|
|
62
62
|
}
|
|
63
63
|
case "object": {
|
package/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Component } from './Node/component';
|
|
2
|
-
export { InlineScope as scope, GateScope as gate, PeekScope as peek } from './Store/Tree/observableScope';
|
|
2
|
+
export { InlineScope as scope, GateScope as gate, PeekScope as peek, MappedScope as mapped } from './Store/Tree/observableScope';
|
package/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.peek = exports.gate = exports.scope = exports.Component = void 0;
|
|
3
|
+
exports.mapped = exports.peek = exports.gate = exports.scope = exports.Component = void 0;
|
|
4
4
|
var component_1 = require("./Node/component");
|
|
5
5
|
Object.defineProperty(exports, "Component", { enumerable: true, get: function () { return component_1.Component; } });
|
|
6
6
|
var observableScope_1 = require("./Store/Tree/observableScope");
|
|
7
7
|
Object.defineProperty(exports, "scope", { enumerable: true, get: function () { return observableScope_1.InlineScope; } });
|
|
8
8
|
Object.defineProperty(exports, "gate", { enumerable: true, get: function () { return observableScope_1.GateScope; } });
|
|
9
9
|
Object.defineProperty(exports, "peek", { enumerable: true, get: function () { return observableScope_1.PeekScope; } });
|
|
10
|
+
Object.defineProperty(exports, "mapped", { enumerable: true, get: function () { return observableScope_1.MappedScope; } });
|