j-templates 7.0.90 → 7.0.92

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.
@@ -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.
@@ -28,12 +32,22 @@ function CreateDynamicScope(getFunction, greedy, value) {
28
32
  value,
29
33
  emitter: emitter_1.Emitter.Create(),
30
34
  emitters: null,
35
+ onUpdated: null,
31
36
  onDestroyed: null,
32
37
  scopes: null,
38
+ mappedScopes: null,
33
39
  };
34
40
  scope.setCallback = OnSet.bind(scope);
35
41
  return scope;
36
42
  }
43
+ function CreateBasicScope(getFunction) {
44
+ return {
45
+ type: "basic",
46
+ getFunction,
47
+ emitter: emitter_1.Emitter.Create(),
48
+ destroyed: false
49
+ };
50
+ }
37
51
  /**
38
52
  * Creates a static (non-reactive) observable scope.
39
53
  * Static scopes are optimized for values that never change and don't need dependency tracking.
@@ -45,6 +59,8 @@ function CreateStaticScope(initialValue) {
45
59
  return {
46
60
  type: "static",
47
61
  value: initialValue,
62
+ onDestroyed: null,
63
+ destroyed: false
48
64
  };
49
65
  }
50
66
  let scopeQueue = [];
@@ -173,6 +189,8 @@ function RegisterScope(scope) {
173
189
  * @returns The scope's current value.
174
190
  */
175
191
  function GetScopeValue(scope) {
192
+ if (scope.type === "basic")
193
+ return scope.getFunction();
176
194
  if (scope.type === "static" || !scope.dirty || scope.destroyed)
177
195
  return scope.value;
178
196
  ExecuteScope(scope);
@@ -195,15 +213,17 @@ let watchState = null;
195
213
  * @param currentCalc Optional map of existing inline scopes to reuse.
196
214
  * @returns The watch state containing tracked dependencies and result.
197
215
  */
198
- function WatchFunction(callback, currentCalc, initialEmitters) {
216
+ function WatchFunction(callback, currentScopes, currentMappedScopes, initialEmitters) {
199
217
  const parent = watchState;
200
218
  watchState = {
201
219
  emitterIndex: 0,
202
220
  value: null,
203
221
  emitters: initialEmitters,
204
222
  emitterSet: null,
205
- currentCalc,
206
- nextCalc: null,
223
+ currentScopes,
224
+ nextScopes: null,
225
+ currentMappedScopes: currentMappedScopes,
226
+ nextMappedScopes: null,
207
227
  strategy: initialEmitters === null ? INIT_STRATEGY : SAME_STRATEGY,
208
228
  };
209
229
  watchState.value = callback();
@@ -223,24 +243,35 @@ function WatchFunction(callback, currentCalc, initialEmitters) {
223
243
  */
224
244
  function ExecuteScope(scope) {
225
245
  scope.dirty = false;
226
- const state = WatchFunction(scope.getFunction, scope.scopes, scope.emitters);
246
+ const state = WatchFunction(scope.getFunction, scope.scopes, scope.mappedScopes, scope.emitters);
227
247
  UpdateEmitters(scope, state);
228
- const calcScopes = state.currentCalc;
229
- scope.scopes = state.nextCalc;
230
- for (const key in calcScopes)
231
- DestroyScope(calcScopes[key]);
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);
232
258
  if (scope.async) {
233
259
  const promise = (scope.pending = state.value);
234
260
  promise.then(function (result) {
235
261
  if (scope.destroyed || scope.pending !== promise)
236
262
  return;
237
263
  scope.pending = null;
264
+ const lastValue = scope.value;
238
265
  scope.value = result;
266
+ scope.onUpdated && emitter_1.Emitter.Emit(scope.onUpdated, lastValue, scope);
239
267
  emitter_1.Emitter.Emit(scope.emitter, scope);
240
268
  });
241
269
  }
242
- else
270
+ else {
271
+ const lastValue = scope.value;
243
272
  scope.value = state.value;
273
+ scope.onUpdated && emitter_1.Emitter.Emit(scope.onUpdated, lastValue, scope);
274
+ }
244
275
  }
245
276
  /**
246
277
  * Creates a scope from a function, choosing between static and dynamic based on dependencies.
@@ -250,15 +281,15 @@ function ExecuteScope(scope) {
250
281
  * @param allowStatic Whether to return a static scope if no dependencies are found.
251
282
  * @returns A new observable scope.
252
283
  */
253
- function ExecuteFunction(callback, greedy, allowStatic) {
284
+ function ExecuteFunction(callback, greedy) {
254
285
  const async = (0, functions_1.IsAsync)(callback);
255
- const state = WatchFunction(callback, null, null);
256
- if (!allowStatic || async || state.emitters !== null) {
286
+ const state = WatchFunction(callback, null, null, null);
287
+ if (async || state.emitters !== null) {
257
288
  const scope = CreateDynamicScope(callback, greedy, async ? null : state.value);
258
- scope.scopes = state.nextCalc;
289
+ scope.scopes = state.nextScopes;
290
+ scope.mappedScopes = state.nextMappedScopes;
259
291
  UpdateEmitters(scope, state);
260
292
  if (async) {
261
- console.log("resolving async scope");
262
293
  const promise = (scope.pending = state.value);
263
294
  promise.then(function (result) {
264
295
  if (scope.destroyed || scope.pending !== promise)
@@ -273,17 +304,57 @@ function ExecuteFunction(callback, greedy, allowStatic) {
273
304
  const value = state.value;
274
305
  return CreateStaticScope(value);
275
306
  }
276
- function ScopeHelper(callback, id, greedy) {
277
- const nextScopes = (watchState.nextCalc ??= {});
278
- if (nextScopes[id])
279
- return nextScopes[id];
280
- const currentScopes = watchState.currentCalc;
281
- nextScopes[id] =
282
- currentScopes?.[id] ?? ExecuteFunction(callback, greedy, true);
283
- if (currentScopes?.[id])
284
- delete currentScopes[id];
285
- return nextScopes[id];
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];
286
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");
287
358
  /**
288
359
  * Creates an inline computed scope registered as a dependency of the parent.
289
360
  * The scope is memoized by ID and reused across reads within the same parent evaluation.
@@ -304,11 +375,19 @@ function InlineScope(callback, idOverride) {
304
375
  if (watchState === null) {
305
376
  throw new Error("scope() must be called within a watch context");
306
377
  }
307
- const id = idOverride ?? "scope_default";
378
+ const id = idOverride ?? SCOPE_DEFAULT;
308
379
  const scope = ScopeHelper(callback, id, false);
309
380
  RegisterScope(scope);
310
381
  return GetScopeValue(scope);
311
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
+ }
312
391
  /**
313
392
  * Creates a gatekeeper scope that only emits when the value actually changes (===).
314
393
  * Prevents unnecessary downstream re-evaluations when the derived value stays the same.
@@ -331,7 +410,7 @@ function GateScope(callback, idOverride) {
331
410
  if (watchState === null) {
332
411
  throw new Error("gate() must be called within a watch context");
333
412
  }
334
- const id = idOverride ?? "gate_default";
413
+ const id = idOverride ?? GATE_DEFAULT;
335
414
  const scope = ScopeHelper(callback, id, true);
336
415
  RegisterScope(scope);
337
416
  return GetScopeValue(scope);
@@ -360,7 +439,7 @@ function PeekScope(callback, idOverride) {
360
439
  if (watchState === null) {
361
440
  throw new Error("peek() must be called within a watch context");
362
441
  }
363
- const id = idOverride ?? "peek_default";
442
+ const id = idOverride ?? PEEK_DEFAULT;
364
443
  const scope = ScopeHelper(callback, id, false);
365
444
  return GetScopeValue(scope);
366
445
  }
@@ -421,23 +500,38 @@ function DestroyAllScopes(scopes) {
421
500
  * @param scope The scope to destroy.
422
501
  */
423
502
  function DestroyScope(scope) {
424
- if (!scope || scope.type === "static")
503
+ if (!scope || scope.destroyed)
425
504
  return;
426
- for (const key in scope.scopes)
427
- DestroyScope(scope.scopes[key]);
428
- // Emitter.Destroy(scope.emitter);
429
- emitter_1.Emitter.DestroyCallback(scope.setCallback);
430
- if (scope.emitters !== null)
431
- for (let x = 0; x < scope.emitters.length; x++)
432
- emitter_1.Emitter.Compact(scope.emitters[x]);
433
- scope.value = undefined;
434
- scope.scopes = null;
435
- scope.emitters = null;
436
- scope.emitter = null;
437
- scope.getFunction = null;
438
- scope.setCallback = null;
439
505
  scope.destroyed = true;
440
- scope.onDestroyed && emitter_1.Emitter.Emit(scope.onDestroyed, scope);
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
+ }
441
535
  }
442
536
  var ObservableScope;
443
537
  (function (ObservableScope) {
@@ -449,10 +543,18 @@ var ObservableScope;
449
543
  * @param force If true, always creates a dynamic scope even without dependencies. Defaults to false.
450
544
  * @returns A new observable scope.
451
545
  */
452
- function Create(valueFunction, greedy = false, force = false) {
453
- return ExecuteFunction(valueFunction, greedy, !force);
546
+ function Create(valueFunction) {
547
+ return ExecuteFunction(valueFunction, false);
454
548
  }
455
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;
456
558
  /**
457
559
  * Registers an emitter as a dependency for the current watch context.
458
560
  * @param emitter The emitter to register as a dependency.
@@ -478,7 +580,7 @@ var ObservableScope;
478
580
  * @returns The scope's current value.
479
581
  */
480
582
  function Value(scope) {
481
- if (!scope)
583
+ if (!scope || scope.destroyed)
482
584
  return undefined;
483
585
  Touch(scope);
484
586
  return Peek(scope);
@@ -490,7 +592,7 @@ var ObservableScope;
490
592
  * @param scope The scope to register as a dependency.
491
593
  */
492
594
  function Touch(scope) {
493
- if (!scope)
595
+ if (!scope || scope.destroyed)
494
596
  return;
495
597
  RegisterScope(scope);
496
598
  }
@@ -502,7 +604,7 @@ var ObservableScope;
502
604
  * @param callback Function to invoke when the scope's value changes.
503
605
  */
504
606
  function Watch(scope, callback) {
505
- if (!scope || scope.type === "static")
607
+ if (!scope || scope.destroyed || scope.type === "static")
506
608
  return;
507
609
  emitter_1.Emitter.On(scope.emitter, callback);
508
610
  }
@@ -514,19 +616,24 @@ var ObservableScope;
514
616
  * @param callback The callback function to remove.
515
617
  */
516
618
  function Unwatch(scope, callback) {
517
- if (!scope || scope.type === "static")
619
+ if (!scope || scope.destroyed || scope.type === "static")
518
620
  return;
519
621
  emitter_1.Emitter.Remove(scope.emitter, callback);
520
622
  }
521
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;
522
631
  /**
523
632
  * Registers a callback to be invoked when the scope is destroyed.
524
633
  * @param scope The scope to monitor for destruction.
525
634
  * @param callback Function to invoke when the scope is destroyed.
526
635
  */
527
636
  function OnDestroyed(scope, callback) {
528
- if (scope.type === "static")
529
- return;
530
637
  scope.onDestroyed ??= emitter_1.Emitter.Create();
531
638
  emitter_1.Emitter.On(scope.onDestroyed, callback);
532
639
  }
@@ -536,9 +643,12 @@ var ObservableScope;
536
643
  * @param scope The scope to mark for update.
537
644
  */
538
645
  function Update(scope) {
539
- if (!scope || scope.type === "static")
646
+ if (!scope || scope.destroyed || scope.type === "static")
540
647
  return;
541
- // OnSet(scope);
648
+ if (scope.type === "basic") {
649
+ emitter_1.Emitter.Emit(scope.emitter, this);
650
+ return;
651
+ }
542
652
  scope.setCallback();
543
653
  }
544
654
  ObservableScope.Update = Update;
@@ -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.Create(getter, true);
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.Create(function () {
569
+ return observableScope_1.ObservableScope.Basic(function () {
570
570
  return tuple[1];
571
- }, false, true);
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.Create(scopeFunctionWrapper, true);
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) {
@@ -1,9 +1,7 @@
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
- function Compact(emitter: Emitter): void;
6
- function DestroyCallback(callback: EmitterCallback): void;
7
5
  function On(emitter: Emitter, callback: EmitterCallback): void;
8
6
  function Emit(emitter: Emitter, ...args: any[]): void;
9
7
  function Remove(emitter: Emitter, callback: EmitterCallback): void;
package/Utils/emitter.js CHANGED
@@ -1,116 +1,67 @@
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
- const destroyed = new WeakSet();
7
- // const pendingCompactEmitters = new Set<Emitter>();
8
- let pendingCompactEmitters = [];
9
36
  function Create() {
10
- return [];
37
+ return [0];
11
38
  }
12
39
  Emitter.Create = Create;
13
- const scheduleCallback = typeof requestIdleCallback !== "undefined"
14
- ? requestIdleCallback
15
- : setTimeout;
16
- function Compact(emitter) {
17
- if (emitter.length === 0)
18
- return;
19
- pendingCompactEmitters.push(emitter);
20
- ScheduleCompact();
21
- }
22
- Emitter.Compact = Compact;
23
- let compactScheduled = false;
24
- function ScheduleCompact() {
25
- if (compactScheduled)
26
- return;
27
- compactScheduled = true;
28
- scheduleCallback(PerformCompact);
29
- }
30
- function PerformCompact() {
31
- compactScheduled = false;
32
- let compactEmitters = pendingCompactEmitters;
33
- pendingCompactEmitters = [];
34
- const processedEmitters = new Set();
35
- for (let x = 0; x < compactEmitters.length; x++)
36
- if (!processedEmitters.has(compactEmitters[x])) {
37
- CompactEmitter(compactEmitters[x]);
38
- processedEmitters.add(compactEmitters[x]);
39
- }
40
- }
41
- /* export function Compact(emitter: Emitter) {
42
- if (emitter.length === 0 || destroyed.has(emitter)) {
43
- return;
44
- }
45
-
46
- if (pendingCompactEmitters.size === 0) {
47
- scheduleCallback(CompactPending);
48
- }
49
-
50
- pendingCompactEmitters.add(emitter);
51
- }
52
-
53
- function CompactPending() {
54
- if (pendingCompactEmitters.size === 0) return;
55
-
56
- const pending = Array.from(pendingCompactEmitters);
57
- pendingCompactEmitters.clear();
58
-
59
- for (let x = 0; x < pending.length; x++)
60
- if (!destroyed.has(pending[x])) CompactEmitter(pending[x]);
61
- } */
62
- function CompactEmitter(emitter) {
63
- let count = 0;
64
- for (; count < emitter.length &&
65
- (emitter[count] === null || destroyed.has(emitter[count])); count++) { }
66
- if (count > 0)
67
- emitter.splice(0, count);
68
- let writePos = 0;
69
- for (let x = 0; x < emitter.length; x++) {
70
- if (emitter[x] !== null && !destroyed.has(emitter[x]))
71
- emitter[writePos++] = emitter[x];
72
- }
73
- if (writePos < emitter.length)
74
- emitter.splice(writePos);
75
- }
76
- function DestroyCallback(callback) {
77
- destroyed.add(callback);
78
- }
79
- Emitter.DestroyCallback = DestroyCallback;
80
- /* export function Destroy(emitter: Emitter) {
81
- pendingCompactEmitters.delete(emitter);
82
- destroyed.add(emitter);
83
- } */
84
40
  function On(emitter, callback) {
85
41
  emitter.push(callback);
86
42
  }
87
43
  Emitter.On = On;
88
44
  function Emit(emitter, ...args) {
89
- // pendingCompactEmitters.delete(emitter);
90
- let writePos = 0;
91
- for (let x = 0; x < emitter.length; x++) {
92
- if (emitter[x] !== null && !destroyed.has(emitter[x])) {
93
- emitter[x](...args);
94
- emitter[writePos++] = emitter[x];
95
- }
96
- }
97
- if (writePos < emitter.length)
98
- emitter.splice(writePos);
45
+ for (let x = emitter[0] + 1; x < emitter.length; x++)
46
+ emitter[x](...args);
99
47
  }
100
48
  Emitter.Emit = Emit;
101
49
  function Remove(emitter, callback) {
102
- const index = emitter.indexOf(callback);
103
- if (index >= 0) {
104
- emitter[index] = null;
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;
105
58
  Compact(emitter);
106
59
  }
107
60
  }
108
61
  Emitter.Remove = Remove;
109
62
  function Clear(emitter) {
110
- if (emitter.length === 0)
111
- return;
112
- // pendingCompactEmitters.delete(emitter);
113
- emitter.splice(0);
63
+ emitter.length > 1 && emitter.splice(1);
64
+ emitter[0] = 0;
114
65
  }
115
66
  Emitter.Clear = Clear;
116
67
  })(Emitter || (exports.Emitter = Emitter = {}));
@@ -7,5 +7,5 @@ exports.IsAsync = IsAsync;
7
7
  * @returns true if the function is async, false otherwise
8
8
  */
9
9
  function IsAsync(func) {
10
- return func[Symbol.toStringTag] === "AsyncFunction";
10
+ return func && func[Symbol.toStringTag] === "AsyncFunction";
11
11
  }
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.map(function (patch, index) {
59
- return JsonMerge(typedSource[index], patch);
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; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "j-templates",
3
- "version": "7.0.90",
3
+ "version": "7.0.92",
4
4
  "description": "j-templates",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/TypesInCode/jTemplates",