j-templates 7.0.73 → 7.0.74

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/index.d.ts CHANGED
@@ -1,3 +1 @@
1
1
  export * from "./elements";
2
- export * from "./createPropertyAssignment";
3
- export * from "./createEventAssignment";
package/DOM/index.js CHANGED
@@ -16,5 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./elements"), exports);
18
18
  // export * from "./svgElements";
19
- __exportStar(require("./createPropertyAssignment"), exports);
20
- __exportStar(require("./createEventAssignment"), exports);
19
+ // export * from "./createPropertyAssignment";
20
+ // export * from "./createEventAssignment";
package/Node/vNode.js CHANGED
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.vNode = void 0;
4
4
  const Store_1 = require("../Store");
5
5
  const observableScope_1 = require("../Store/Tree/observableScope");
6
- const emitter_1 = require("../Utils/emitter");
7
6
  const functions_1 = require("../Utils/functions");
8
7
  const injector_1 = require("../Utils/injector");
9
8
  const thread_1 = require("../Utils/thread");
@@ -22,7 +21,6 @@ var vNode;
22
21
  node: definition.node ?? null,
23
22
  children: null,
24
23
  destroyed: false,
25
- onDestroyed: null,
26
24
  component: null,
27
25
  scopes: [],
28
26
  };
@@ -36,7 +34,6 @@ var vNode;
36
34
  node: nodeConfig_1.NodeConfig.createTextNode(text),
37
35
  children: null,
38
36
  destroyed: false,
39
- onDestroyed: null,
40
37
  component: null,
41
38
  scopes: [],
42
39
  };
@@ -59,7 +56,6 @@ var vNode;
59
56
  vnode.destroyed = true;
60
57
  vnode.component?.Destroy();
61
58
  Store_1.ObservableScope.DestroyAll(vnode.scopes);
62
- vnode.onDestroyed && emitter_1.Emitter.Emit(vnode.onDestroyed);
63
59
  for (let x = 0; vnode.children && x < vnode.children.length; x++) {
64
60
  DestroyAll(vnode.children[x][1]);
65
61
  Store_1.ObservableScope.Destroy(vnode.children[x][2]);
@@ -2,7 +2,6 @@ import { Component } from "./component";
2
2
  import { IObservableScope } from "../Store/Tree/observableScope";
3
3
  import { Injector } from "../Utils/injector";
4
4
  import { RecursivePartial } from "../Utils/utils.types";
5
- import { Emitter } from "../Utils/emitter";
6
5
  export type FunctionOr<T> = {
7
6
  (): T | Promise<T>;
8
7
  } | T;
@@ -21,7 +20,6 @@ export type vNode = {
21
20
  node: Node | null;
22
21
  children: [any, vNode[], IObservableScope<string | vNode | vNode[]> | null][] | null;
23
22
  destroyed: boolean;
24
- onDestroyed: Emitter | null;
25
23
  scopes: IObservableScope<unknown>[];
26
24
  component: Component;
27
25
  };
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ObservableScope = void 0;
4
4
  exports.CalcScope = CalcScope;
5
- const array_1 = require("../../Utils/array");
5
+ const bitSet_1 = require("../../Utils/bitSet");
6
6
  const emitter_1 = require("../../Utils/emitter");
7
7
  const functions_1 = require("../../Utils/functions");
8
8
  /**
@@ -45,6 +45,11 @@ function CreateStaticScope(initialValue) {
45
45
  value: initialValue,
46
46
  };
47
47
  }
48
+ /**
49
+ * Queue of scopes pending batched update processing.
50
+ * Scopes are added when their dependencies change and greedy batching is enabled.
51
+ * The queue is processed in a microtask to batch multiple updates efficiently.
52
+ */
48
53
  let scopeQueue = [];
49
54
  /**
50
55
  * Processes all queued scopes, recomputing dirty scopes and emitting changes.
@@ -89,93 +94,78 @@ function OnSet() {
89
94
  emitter_1.Emitter.Emit(this.emitter, this);
90
95
  }
91
96
  /**
92
- * Registers an emitter using SAME_STRATEGY.
93
- * If the emitter is already registered at the current index, increments the index.
94
- * Otherwise, switches to PUSH_STRATEGY and appends the emitter.
95
- * @param state The current watch state.
96
- * @param emitter The emitter to register.
97
- */
98
- function RegisterSame(state, emitter) {
99
- if (state.emitterIndex < state.emitters.length &&
100
- state.emitters[state.emitterIndex] === emitter) {
101
- state.emitterIndex++;
102
- return;
103
- }
104
- state.emitters = state.emitters.slice(0, state.emitterIndex);
105
- state.strategy = SORTED_STRATEGY;
106
- RegisterSorted(state, emitter);
107
- }
108
- /**
109
- * Registers an emitter while maintaining sorted order by emitter ID.
110
- * If insertion would break sort order, falls back to PUSH_STRATEGY.
111
- * @param state The current watch state.
112
- * @param emitter The emitter to register.
113
- */
114
- function RegisterSorted(state, emitter) {
115
- if (state.emitters.length === 0 ||
116
- state.emitters[state.emitters.length - 1][0] < emitter[0])
117
- state.emitters.push(emitter);
118
- else {
119
- state.strategy = PUSH_STRATEGY;
120
- RegisterPush(state, emitter);
121
- }
122
- }
123
- /**
124
- * Registers an emitter using PUSH_STRATEGY.
125
- * Switches to DISTINCT_STRATEGY when the emitter count exceeds 50 to optimize memory.
126
- * @param state The current watch state.
127
- * @param emitter The emitter to register.
97
+ * Strategy where emitters are accessed in the same order as the previous execution.
98
+ * This allows for efficient reconciliation by tracking which emitters were accessed
99
+ * at the same positions in the array.
128
100
  */
129
- function RegisterPush(state, emitter) {
130
- state.emitters.push(emitter);
131
- if (state.emitters.length > 50) {
132
- const idSet = (state.emitterIds = new Set([state.emitters[0][0]]));
133
- let writePos = 0;
134
- for (let x = 1; x < state.emitters.length; x++) {
135
- if (!idSet.has(state.emitters[x][0])) {
136
- state.emitters[++writePos] = state.emitters[x];
137
- idSet.add(state.emitters[x][0]);
138
- }
139
- }
140
- writePos++;
141
- if (writePos < state.emitters.length)
142
- state.emitters.splice(writePos);
143
- state.strategy = DISTINCT_STRATEGY;
144
- }
145
- }
101
+ const SAME_STRATEGY = 1;
146
102
  /**
147
- * Registers an emitter using DISTINCT_STRATEGY.
148
- * Only adds emitters that haven't been registered yet, using an ID set for O(1) lookup.
149
- * @param state The current watch state.
150
- * @param emitter The emitter to register.
103
+ * Strategy where new emitters are pushed to the array when accessed.
104
+ * Used when the access pattern changes from the previous execution.
151
105
  */
152
- function RegisterDistinct(state, emitter) {
153
- if (!state.emitterIds.has(emitter[0])) {
154
- state.emitters.push(emitter);
155
- state.emitterIds.add(emitter[0]);
156
- }
106
+ const PUSH_STRATEGY = 2;
107
+ function GetBitSetFor(emitters) {
108
+ const bitSet = bitSet_1.BitSetPool.Get(BIT_SET_POOL);
109
+ for (let x = 0; x < emitters.length; x++)
110
+ bitSet_1.BitSet.set(bitSet, emitters[x][0]);
111
+ return bitSet;
157
112
  }
158
113
  /**
159
- * Routes an emitter to the appropriate registration strategy based on current watch state.
160
- * Does nothing if not within a watch context.
161
- * @param emitter The emitter to register.
114
+ * Registers an emitter as a dependency during a watch operation.
115
+ *
116
+ * This function tracks which emitters are accessed while executing a scope's getFunction.
117
+ * It uses two strategies for efficiency:
118
+ *
119
+ * - **SAME_STRATEGY**: When emitters are accessed in the same order as the previous execution,
120
+ * it tracks this via emitterIndex and skips array operations. Only switches to PUSH_STRATEGY
121
+ * when the order changes.
122
+ *
123
+ * - **PUSH_STRATEGY**: When access order differs or is new, emitters are pushed to the array.
124
+ * The BitSet prevents duplicates (same emitter accessed multiple times).
125
+ *
126
+ * The function does nothing if called outside a watch context (watchState is null).
127
+ *
128
+ * @param emitter The emitter to register as a dependency. Must have a unique ID at index 0.
162
129
  */
163
130
  function RegisterEmitter(emitter) {
164
131
  if (watchState === null)
165
132
  return;
166
133
  switch (watchState.strategy) {
167
- case SAME_STRATEGY:
168
- RegisterSame(watchState, emitter);
169
- break;
170
- case SORTED_STRATEGY:
171
- RegisterSorted(watchState, emitter);
172
- break;
173
- case PUSH_STRATEGY:
174
- RegisterPush(watchState, emitter);
134
+ case SAME_STRATEGY: {
135
+ if (watchState.emitterIndex < watchState.emitters.length &&
136
+ watchState.emitters[watchState.emitterIndex][0] === emitter[0]) {
137
+ watchState.emitterIndex++;
138
+ // BitSet.set(watchState.emitterIds, emitter[0]);
139
+ }
140
+ else {
141
+ watchState.strategy = PUSH_STRATEGY;
142
+ watchState.emitters = watchState.emitters.slice(0, watchState.emitterIndex);
143
+ RegisterEmitter(emitter);
144
+ }
175
145
  break;
176
- case DISTINCT_STRATEGY:
177
- RegisterDistinct(watchState, emitter);
146
+ }
147
+ case PUSH_STRATEGY: {
148
+ switch (watchState.emitters.length) {
149
+ case 0: {
150
+ watchState.emitters.push(emitter);
151
+ break;
152
+ }
153
+ case 1: {
154
+ if (watchState.emitters[0][0] !== emitter[0])
155
+ watchState.emitters.push(emitter);
156
+ break;
157
+ }
158
+ default: {
159
+ if (watchState.emitters[watchState.emitters.length - 1][0] !== emitter[0]) {
160
+ watchState.emitterIds ??= GetBitSetFor(watchState.emitters);
161
+ if (bitSet_1.BitSet.add(watchState.emitterIds, emitter[0]))
162
+ watchState.emitters.push(emitter);
163
+ }
164
+ break;
165
+ }
166
+ }
178
167
  break;
168
+ }
179
169
  }
180
170
  }
181
171
  /**
@@ -200,15 +190,16 @@ function GetScopeValue(scope) {
200
190
  return scope.value;
201
191
  }
202
192
  /**
203
- * Strategy constants for optimizing emitter registration during watch operations.
204
- * Each strategy represents a different approach to tracking and deduplicating dependencies.
193
+ * Global watch state representing the current dependency tracking context.
194
+ * This is set during scope execution and tracks which emitters/scopes are accessed.
195
+ * Nested watch contexts are supported via the parent reference pattern.
205
196
  */
206
- const SAME_STRATEGY = 1;
207
- const PUSH_STRATEGY = 2;
208
- const SORTED_STRATEGY = 3;
209
- const DISTINCT_STRATEGY = 4;
210
- const SHRINK_STRATEGY = 5;
211
197
  let watchState = null;
198
+ /**
199
+ * Pool for recycling BitSet objects to reduce garbage collection overhead.
200
+ * BitSets are borrowed during watch operations and returned after use.
201
+ */
202
+ const BIT_SET_POOL = bitSet_1.BitSetPool.Create();
212
203
  /**
213
204
  * Executes a callback while tracking all scope and emitter dependencies.
214
205
  * Creates a watch context that records what was accessed during execution.
@@ -220,21 +211,16 @@ function WatchFunction(callback, currentCalc, initialEmitters) {
220
211
  const parent = watchState;
221
212
  watchState = {
222
213
  emitterIndex: 0,
214
+ strategy: initialEmitters === null ? PUSH_STRATEGY : SAME_STRATEGY,
223
215
  value: null,
224
216
  emitters: initialEmitters ?? [],
225
- emitterIds: null,
217
+ emitterIds: null, // BitSetPool.Get(BIT_SET_POOL),
226
218
  currentCalc,
227
219
  nextCalc: null,
228
- strategy: initialEmitters === null ? SORTED_STRATEGY : SAME_STRATEGY,
229
220
  };
230
221
  watchState.value = callback();
231
222
  const resultState = watchState;
232
223
  watchState = parent;
233
- if (resultState.strategy === SAME_STRATEGY &&
234
- resultState.emitterIndex < resultState.emitters.length) {
235
- resultState.emitters = resultState.emitters.slice(0, resultState.emitterIndex);
236
- resultState.strategy = SHRINK_STRATEGY;
237
- }
238
224
  return resultState;
239
225
  }
240
226
  /**
@@ -245,7 +231,11 @@ function WatchFunction(callback, currentCalc, initialEmitters) {
245
231
  function ExecuteScope(scope) {
246
232
  scope.dirty = false;
247
233
  const state = WatchFunction(scope.getFunction, scope.calcScopes, scope.emitters);
248
- UpdateEmitters(scope, state.emitters, state.strategy);
234
+ if (state.strategy === SAME_STRATEGY &&
235
+ state.emitterIndex < state.emitters.length)
236
+ state.emitters = state.emitters.slice(0, state.emitterIndex);
237
+ UpdateEmitters(scope, state);
238
+ state.emitterIds && bitSet_1.BitSetPool.Return(BIT_SET_POOL, state.emitterIds);
249
239
  const calcScopes = state.currentCalc;
250
240
  scope.calcScopes = state.nextCalc;
251
241
  for (const key in calcScopes)
@@ -272,7 +262,8 @@ function ExecuteFunction(callback, greedy, allowStatic) {
272
262
  if (!allowStatic || async || state.emitters !== null) {
273
263
  const scope = CreateDynamicScope(callback, greedy, async ? null : state.value);
274
264
  scope.calcScopes = state.nextCalc;
275
- UpdateEmitters(scope, state.emitters, state.strategy);
265
+ UpdateEmitters(scope, state);
266
+ state.emitterIds && bitSet_1.BitSetPool.Return(BIT_SET_POOL, state.emitterIds);
276
267
  if (async)
277
268
  state.value.then(function (result) {
278
269
  scope.value = result;
@@ -303,7 +294,7 @@ function CalcScope(callback, idOverride) {
303
294
  return callback();
304
295
  const nextScopes = (watchState.nextCalc ??= {});
305
296
  const id = idOverride ?? "default";
306
- if (nextScopes[id]) {
297
+ if (Object.hasOwn(nextScopes, id)) {
307
298
  RegisterScope(nextScopes[id]);
308
299
  return GetScopeValue(nextScopes[id]);
309
300
  }
@@ -315,39 +306,31 @@ function CalcScope(callback, idOverride) {
315
306
  return GetScopeValue(nextScopes[id]);
316
307
  }
317
308
  /**
318
- * Updates a scope's dependency emitters using efficient diffing.
319
- * Subscribes to new emitters and unsubscribes from removed ones.
320
- * @param scope The scope to update dependencies for.
321
- * @param right The new list of emitters to track.
322
- * @param distinct Whether emitters are already unique (sorted and deduplicated).
309
+ * Updates a scope's emitter subscriptions based on the new watch state.
310
+ * Efficiently reconciles old and new emitter lists starting from emitterIndex.
311
+ *
312
+ * Emitters before emitterIndex are in the same position and don't need updates.
313
+ * Emitters at/after emitterIndex are removed if no longer accessed or added if newly accessed.
314
+ *
315
+ * @param scope The scope to update emitter subscriptions for.
316
+ * @param state The watch state containing the new emitter list.
323
317
  */
324
- function UpdateEmitters(scope, right, strategy) {
325
- switch (strategy) {
326
- case SHRINK_STRATEGY: {
327
- for (let x = right.length; x < scope.emitters.length; x++)
328
- emitter_1.Emitter.Remove(scope.emitters[x], scope.setCallback);
329
- break;
318
+ function UpdateEmitters(scope, state) {
319
+ const currentEmitters = scope.emitters;
320
+ const nextEmitters = state.emitters;
321
+ const nextEmitterIds = state.emitterIds;
322
+ const sameIndex = state.emitterIndex;
323
+ if (currentEmitters !== null) {
324
+ for (let x = sameIndex; x < currentEmitters.length; x++) {
325
+ if (nextEmitterIds === null || !bitSet_1.BitSet.remove(nextEmitterIds, currentEmitters[x][0]))
326
+ emitter_1.Emitter.Remove(currentEmitters[x], scope.setCallback);
330
327
  }
331
- case PUSH_STRATEGY:
332
- case DISTINCT_STRATEGY:
333
- strategy === PUSH_STRATEGY
334
- ? emitter_1.Emitter.Distinct(right)
335
- : emitter_1.Emitter.Sort(right);
336
- case SORTED_STRATEGY:
337
- if (scope.emitters === null || scope.emitters.length === 0) {
338
- for (let x = 0; x < right.length; x++)
339
- emitter_1.Emitter.On(right[x], scope.setCallback);
340
- }
341
- else {
342
- (0, array_1.ReconcileSortedEmitters)(scope.emitters, right, function (emitter) {
343
- emitter_1.Emitter.On(emitter, scope.setCallback);
344
- }, function (emitter) {
345
- emitter_1.Emitter.Remove(emitter, scope.setCallback);
346
- });
347
- }
348
- break;
349
328
  }
350
- scope.emitters = right;
329
+ for (let x = sameIndex; x < nextEmitters.length; x++) {
330
+ if (nextEmitterIds === null || bitSet_1.BitSet.has(nextEmitterIds, nextEmitters[x][0]))
331
+ emitter_1.Emitter.On(nextEmitters[x], scope.setCallback);
332
+ }
333
+ scope.emitters = nextEmitters;
351
334
  }
352
335
  /**
353
336
  * Destroys multiple scopes, cleaning up their resources.
@@ -379,6 +362,7 @@ function DestroyScope(scope) {
379
362
  scope.setCallback = null;
380
363
  scope.destroyed = true;
381
364
  scope.onDestroyed && emitter_1.Emitter.Emit(scope.onDestroyed, scope);
365
+ scope.onDestroyed && emitter_1.Emitter.Destroy(scope.onDestroyed);
382
366
  }
383
367
  var ObservableScope;
384
368
  (function (ObservableScope) {
@@ -0,0 +1,23 @@
1
+ export type BitSet = {
2
+ init: boolean;
3
+ buffer: Uint32Array | null;
4
+ activeFrames: Set<number>;
5
+ minFrame: number;
6
+ maxFrame: number;
7
+ };
8
+ export type BitSetPool = {
9
+ pool: BitSet[];
10
+ index: number;
11
+ };
12
+ export declare namespace BitSetPool {
13
+ function Create(): BitSetPool;
14
+ function Get(pool: BitSetPool): BitSet;
15
+ function Return(pool: BitSetPool, bitSet: BitSet): void;
16
+ }
17
+ export declare namespace BitSet {
18
+ function Create(): BitSet;
19
+ function set(set: BitSet, num: number): void;
20
+ function has(set: BitSet, num: number): boolean;
21
+ function add(set: BitSet, num: number): boolean;
22
+ function remove(set: BitSet, num: number): boolean;
23
+ }
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BitSet = exports.BitSetPool = void 0;
4
+ // 100000 = 31
5
+ const FRAME_BIT_SHIFT = 5;
6
+ const DEFAULT_FRAME_COUNT = 1024;
7
+ const DEFAULT_FRAME_HALF = DEFAULT_FRAME_COUNT / 2;
8
+ function GetFrame(number) {
9
+ // Effectively equivalent to Math.floor(number / 32)
10
+ return number >>> FRAME_BIT_SHIFT;
11
+ }
12
+ function GetBit(number) {
13
+ // JavaScript only uses rightmost 5 bits of num for this operation
14
+ // Effectively equivalent to number % 32
15
+ return 1 << number;
16
+ }
17
+ function Resize(set, frame) {
18
+ if (set.minFrame <= frame && frame < set.maxFrame)
19
+ return;
20
+ const currentSize = set.maxFrame - set.minFrame;
21
+ let newMin = Math.min(set.minFrame, frame);
22
+ let newMax = Math.max(set.maxFrame, frame + 1);
23
+ let newSize = newMax - newMin;
24
+ const minimumNewSize = currentSize * 2;
25
+ if (newSize < minimumNewSize) {
26
+ const growBy = minimumNewSize - newSize;
27
+ const growByHalf = growBy / 2;
28
+ newMin = newMin - Math.floor(growByHalf);
29
+ newMax = newMax + Math.ceil(growByHalf);
30
+ if (newMin < 0) {
31
+ newMax -= newMin;
32
+ newMin = 0;
33
+ }
34
+ newSize = newMax - newMin;
35
+ }
36
+ const newBuffer = new Uint32Array(newSize);
37
+ newBuffer.set(set.buffer, set.minFrame - newMin);
38
+ set.buffer = newBuffer;
39
+ set.minFrame = newMin;
40
+ set.maxFrame = newMax;
41
+ }
42
+ function Initialize(set, initFrameNumber) {
43
+ if (set.init)
44
+ return;
45
+ set.init = true;
46
+ set.activeFrames.clear();
47
+ const frame = GetFrame(initFrameNumber);
48
+ const sizeHalf = (set.buffer?.length ?? DEFAULT_FRAME_COUNT) / 2;
49
+ set.buffer ??= new Uint32Array(DEFAULT_FRAME_COUNT);
50
+ set.minFrame = frame - Math.floor(sizeHalf);
51
+ set.maxFrame = frame + Math.ceil(sizeHalf);
52
+ if (set.minFrame < 0) {
53
+ set.maxFrame -= set.minFrame;
54
+ set.minFrame = 0;
55
+ }
56
+ }
57
+ var BitSetPool;
58
+ (function (BitSetPool) {
59
+ function Create() {
60
+ return {
61
+ pool: [],
62
+ index: 0
63
+ };
64
+ }
65
+ BitSetPool.Create = Create;
66
+ function Get(pool) {
67
+ return pool.index === 0 ? BitSet.Create() : pool.pool[--pool.index];
68
+ }
69
+ BitSetPool.Get = Get;
70
+ function Return(pool, bitSet) {
71
+ bitSet.init = false;
72
+ pool.pool[pool.index++] = bitSet;
73
+ }
74
+ BitSetPool.Return = Return;
75
+ })(BitSetPool || (exports.BitSetPool = BitSetPool = {}));
76
+ var BitSet;
77
+ (function (BitSet) {
78
+ function Create() {
79
+ return {
80
+ init: false,
81
+ buffer: null,
82
+ activeFrames: new Set(),
83
+ minFrame: -1,
84
+ maxFrame: -1,
85
+ };
86
+ }
87
+ BitSet.Create = Create;
88
+ function set(set, num) {
89
+ Initialize(set, num);
90
+ const frame = GetFrame(num);
91
+ Resize(set, frame);
92
+ if (!set.activeFrames.has(frame)) {
93
+ set.buffer[frame] = 0;
94
+ set.activeFrames.add(frame);
95
+ }
96
+ const frameOffset = frame - set.minFrame;
97
+ set.buffer[frameOffset] |= GetBit(num);
98
+ }
99
+ BitSet.set = set;
100
+ function has(set, num) {
101
+ if (set.buffer === null)
102
+ return false;
103
+ const frame = GetFrame(num);
104
+ if (!set.activeFrames.has(frame))
105
+ return false;
106
+ if (frame < set.minFrame || set.maxFrame <= frame)
107
+ return false;
108
+ const frameOffset = frame - set.minFrame;
109
+ const frameValue = set.buffer[frameOffset] & GetBit(num);
110
+ return frameValue !== 0;
111
+ }
112
+ BitSet.has = has;
113
+ function add(set, num) {
114
+ Initialize(set, num);
115
+ const frame = GetFrame(num);
116
+ Resize(set, frame);
117
+ if (!set.activeFrames.has(frame)) {
118
+ set.buffer[frame] = 0;
119
+ set.activeFrames.add(frame);
120
+ }
121
+ const frameOffset = frame - set.minFrame;
122
+ const frameStart = set.buffer[frameOffset];
123
+ set.buffer[frameOffset] |= GetBit(num);
124
+ return frameStart !== set.buffer[frameOffset];
125
+ }
126
+ BitSet.add = add;
127
+ function remove(set, num) {
128
+ if (set.buffer === null)
129
+ return false;
130
+ const frame = GetFrame(num);
131
+ if (!set.activeFrames.has(frame) || frame < set.minFrame || set.maxFrame <= frame)
132
+ return false;
133
+ const frameOffset = frame - set.minFrame;
134
+ const frameStart = set.buffer[frameOffset];
135
+ set.buffer[frameOffset] ^= GetBit(num);
136
+ return frameStart !== set.buffer[frameOffset];
137
+ }
138
+ BitSet.remove = remove;
139
+ })(BitSet || (exports.BitSet = BitSet = {}));
@@ -8,7 +8,4 @@ export declare namespace Emitter {
8
8
  function Destroy(emitter: Emitter): void;
9
9
  function Remove(emitter: Emitter, callback: EmitterCallback): void;
10
10
  function Clear(emitter: Emitter): void;
11
- function Distinct(emitters: Emitter[]): void;
12
- function Sort(emitters: Emitter[]): void;
13
- function Compare(a: Emitter, b: Emitter): number;
14
11
  }
package/Utils/emitter.js CHANGED
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Emitter = void 0;
4
- const array_1 = require("./array");
4
+ const idPool = [];
5
+ let idPoolIndex = 0;
6
+ let globalId = 0;
5
7
  var Emitter;
6
8
  (function (Emitter) {
7
- let globalId = 0;
8
9
  function Create() {
9
- const emitter = [++globalId];
10
+ const emitterId = idPoolIndex === 0 ? ++globalId : idPool[--idPoolIndex];
11
+ const emitter = [emitterId];
10
12
  return emitter;
11
13
  }
12
14
  Emitter.Create = Create;
@@ -33,6 +35,7 @@ var Emitter;
33
35
  }
34
36
  Emitter.Emit = Emit;
35
37
  function Destroy(emitter) {
38
+ idPool[idPoolIndex++] = emitter[0];
36
39
  emitter[0] = -1;
37
40
  }
38
41
  Emitter.Destroy = Destroy;
@@ -48,30 +51,4 @@ var Emitter;
48
51
  emitter.splice(1);
49
52
  }
50
53
  Emitter.Clear = Clear;
51
- function Distinct(emitters) {
52
- if (emitters.length < 2)
53
- return;
54
- Sort(emitters);
55
- let writePos = 0;
56
- for (let x = 1; x < emitters.length; x++) {
57
- if (emitters[x][0] !== emitters[writePos][0]) {
58
- emitters[++writePos] = emitters[x];
59
- }
60
- }
61
- writePos++;
62
- if (writePos < emitters.length)
63
- emitters.splice(writePos);
64
- }
65
- Emitter.Distinct = Distinct;
66
- function Sort(emitters) {
67
- if (emitters.length < 11)
68
- (0, array_1.InsertionSortTuples)(emitters);
69
- else
70
- emitters.sort(Compare);
71
- }
72
- Emitter.Sort = Sort;
73
- function Compare(a, b) {
74
- return a[0] - b[0];
75
- }
76
- Emitter.Compare = Compare;
77
54
  })(Emitter || (exports.Emitter = Emitter = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "j-templates",
3
- "version": "7.0.73",
3
+ "version": "7.0.74",
4
4
  "description": "j-templates",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/TypesInCode/jTemplates",