j-templates 6.1.11 → 6.1.12

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.
@@ -58,7 +58,7 @@ exports.DOMNodeConfig = {
58
58
  return window_1.wndw.document.createTextNode(value);
59
59
  },
60
60
  isTextNode(target) {
61
- return target.nodeType === Node.TEXT_NODE;
61
+ return target?.nodeType === Node.TEXT_NODE;
62
62
  },
63
63
  scheduleUpdate,
64
64
  wrapPriorityUpdates,
package/Node/nodeRef.js CHANGED
@@ -8,6 +8,7 @@ const elementNode_1 = require("./elementNode");
8
8
  const componentNode_1 = require("./componentNode");
9
9
  const list_1 = require("../Utils/list");
10
10
  const Store_1 = require("../Store");
11
+ const domNodeConfig_1 = require("../DOM/domNodeConfig");
11
12
  var NodeRefType;
12
13
  (function (NodeRefType) {
13
14
  NodeRefType[NodeRefType["NodeRef"] = 0] = "NodeRef";
@@ -116,10 +117,10 @@ var NodeRef;
116
117
  }
117
118
  NodeRef.Create = Create;
118
119
  function Init(nodeRef) {
119
- if (nodeRef.node || nodeRef.type === NodeRefType.TextNode)
120
+ if (nodeRef.type === NodeRefType.TextNode || nodeRef.node)
120
121
  return;
121
- nodeRef.node = nodeRef.nodeType === 'text' ? nodeConfig_1.NodeConfig.createTextNode() : nodeConfig_1.NodeConfig.createNode(nodeRef.nodeType, nodeRef.nodeNamespace);
122
- nodeRef.childNodes = nodeRef.nodeType !== 'text' ? [] : null;
122
+ nodeRef.node = nodeConfig_1.NodeConfig.createNode(nodeRef.nodeType, nodeRef.nodeNamespace);
123
+ nodeRef.childNodes = nodeRef.nodeType !== NodeRefType.TextNode ? [] : null;
123
124
  switch (nodeRef.type) {
124
125
  case NodeRefType.BoundNode:
125
126
  boundNode_1.BoundNode.Init(nodeRef);
@@ -189,15 +190,15 @@ var NodeRef;
189
190
  for (let x = 0; x < curDataNode.data.nodes.length; x++) {
190
191
  const virtualNode = curDataNode.data.nodes[x];
191
192
  const actualNode = priorNode ? nodeConfig_1.NodeConfig.getNextSibling(priorNode) : nodeConfig_1.NodeConfig.getFirstChild(rootNode);
192
- let expectedNode;
193
- if (virtualNode.type === NodeRefType.TextNode && actualNode !== null && nodeConfig_1.NodeConfig.isTextNode(actualNode)) {
194
- nodeConfig_1.NodeConfig.setText(actualNode, virtualNode.value);
195
- virtualNode.node = expectedNode = actualNode;
193
+ if (virtualNode.type === NodeRefType.TextNode && virtualNode.node === null) {
194
+ if (domNodeConfig_1.DOMNodeConfig.isTextNode(actualNode)) {
195
+ domNodeConfig_1.DOMNodeConfig.setText(actualNode, virtualNode.value);
196
+ virtualNode.node = actualNode;
197
+ }
198
+ else
199
+ virtualNode.node = domNodeConfig_1.DOMNodeConfig.createTextNode(virtualNode.value);
196
200
  }
197
- else if (virtualNode.type === NodeRefType.TextNode)
198
- expectedNode = nodeConfig_1.NodeConfig.createTextNode(virtualNode.value);
199
- else
200
- expectedNode = virtualNode.node;
201
+ const expectedNode = virtualNode.node;
201
202
  if (actualNode !== expectedNode) {
202
203
  nodeConfig_1.NodeConfig.addChildBefore(rootNode, actualNode, expectedNode);
203
204
  !remove && insert && actualNode && nodeConfig_1.NodeConfig.removeChild(rootNode, actualNode);
@@ -41,11 +41,9 @@ export interface IObservableScope<T> extends IDestroyable {
41
41
  dirty: boolean;
42
42
  emitter: Emitter;
43
43
  emitters: (Emitter | null)[];
44
- calcFunctions: ICalcFunction<any>[] | null;
44
+ calcFunctions: ICalcFunction<any>[];
45
45
  onDestroyed: Emitter | null;
46
46
  destroyed: boolean;
47
- watchEmitters: Emitter[] | null;
48
- watchEmittersSet: Set<Emitter> | null;
49
47
  }
50
48
  export declare function CalcScope<T>(callback: () => T): T;
51
49
  export declare namespace ObservableScope {
@@ -55,7 +53,6 @@ export declare namespace ObservableScope {
55
53
  function Register(emitter: Emitter): void;
56
54
  function Init<T>(scope: IObservableScope<T>): void;
57
55
  function Value<T>(scope: IObservableScope<T>): T;
58
- function Watching(): boolean;
59
56
  function Touch<T>(scope: IObservableScope<T>): void;
60
57
  function Watch<T>(scope: IObservableScope<T>, callback: EmitterCallback<[IObservableScope<T>]>): void;
61
58
  function Unwatch<T>(scope: IObservableScope<T>, callback: EmitterCallback<[IObservableScope<T> | ObservableScopeValue<T>]>): void;
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ObservableScope = exports.ObservableScopeWrapper = exports.ObservableScopeValue = void 0;
4
4
  exports.CalcScope = CalcScope;
5
5
  const array_1 = require("../../Utils/array");
6
+ const avlTree_1 = require("../../Utils/avlTree");
6
7
  const emitter_1 = require("../../Utils/emitter");
7
- const list_1 = require("../../Utils/list");
8
8
  class ObservableScopeValue {
9
9
  get Value() {
10
10
  return ObservableScope.Value(this.scope);
@@ -48,28 +48,22 @@ class ObservableScope extends ObservableScopeWrapper {
48
48
  }
49
49
  }
50
50
  exports.ObservableScope = ObservableScope;
51
- let watchingScope = null;
52
- let currentlyWatching = false;
51
+ let watchState = null;
53
52
  function WatchScope(scope) {
54
- const parentScope = watchingScope;
55
- const parentWatching = currentlyWatching;
56
- watchingScope = scope;
57
- currentlyWatching = true;
53
+ const parent = watchState;
54
+ watchState = [avlTree_1.AVL.Create(emitter_1.Emitter.Compare), []];
58
55
  const value = scope.getFunction();
59
- watchingScope.watchEmittersSet = null;
60
- watchingScope = parentScope;
61
- currentlyWatching = parentWatching;
62
- return value;
56
+ const result = [value, avlTree_1.AVL.ToArray(watchState[0]), watchState[1]];
57
+ watchState = parent;
58
+ return result;
63
59
  }
64
60
  function CalcScope(callback) {
65
61
  const value = callback();
66
- if (currentlyWatching) {
67
- watchingScope.calcFunctions ??= [];
68
- watchingScope.calcFunctions.push({
62
+ if (watchState !== null)
63
+ watchState[1].push({
69
64
  getFunction: callback,
70
65
  value
71
66
  });
72
- }
73
67
  return value;
74
68
  }
75
69
  (function (ObservableScope) {
@@ -82,11 +76,9 @@ function CalcScope(callback) {
82
76
  dirty: true,
83
77
  emitter: emitter_1.Emitter.Create(),
84
78
  emitters: [],
85
- calcFunctions: null,
79
+ calcFunctions: [],
86
80
  onDestroyed: null,
87
81
  destroyed: false,
88
- watchEmitters: null,
89
- watchEmittersSet: null,
90
82
  setCallback: function () {
91
83
  return OnSet(scope);
92
84
  },
@@ -95,35 +87,25 @@ function CalcScope(callback) {
95
87
  }
96
88
  ObservableScope.Create = Create;
97
89
  function Register(emitter) {
98
- if (!currentlyWatching)
90
+ if (watchState === null)
99
91
  return;
100
- watchingScope.watchEmitters ??= [];
101
- if (watchingScope.watchEmitters.length === 10)
102
- watchingScope.watchEmittersSet ??= new Set(watchingScope.watchEmitters);
103
- if (watchingScope.watchEmittersSet === null ? !watchingScope.watchEmitters.includes(emitter) : !watchingScope.watchEmittersSet.has(emitter)) {
104
- watchingScope.watchEmittersSet?.add(emitter);
105
- watchingScope.watchEmitters.push(emitter);
106
- }
92
+ avlTree_1.AVL.Insert(watchState[0], emitter);
107
93
  }
108
94
  ObservableScope.Register = Register;
109
95
  function Init(scope) {
110
96
  if (!scope)
111
97
  return;
112
- UpdateScope(scope);
98
+ UpdateValue(scope);
113
99
  }
114
100
  ObservableScope.Init = Init;
115
101
  function Value(scope) {
116
102
  if (!scope)
117
103
  return undefined;
118
104
  Register(scope.emitter);
119
- UpdateScope(scope);
105
+ UpdateValue(scope);
120
106
  return scope.value;
121
107
  }
122
108
  ObservableScope.Value = Value;
123
- function Watching() {
124
- return currentlyWatching;
125
- }
126
- ObservableScope.Watching = Watching;
127
109
  function Touch(scope) {
128
110
  if (!scope || !scope.emitter)
129
111
  return;
@@ -148,6 +130,8 @@ function CalcScope(callback) {
148
130
  }
149
131
  ObservableScope.OnDestroyed = OnDestroyed;
150
132
  function Update(scope) {
133
+ if (!scope || scope.dirty || scope.destroyed)
134
+ return;
151
135
  OnSet(scope);
152
136
  }
153
137
  ObservableScope.Update = Update;
@@ -156,25 +140,6 @@ function CalcScope(callback) {
156
140
  }
157
141
  ObservableScope.Destroy = Destroy;
158
142
  })(ObservableScope || (exports.ObservableScope = ObservableScope = {}));
159
- function UpdateScope(scope) {
160
- const prePromise = scope.promise;
161
- UpdateValue(scope);
162
- scope.async && prePromise !== scope.promise && scope.promise.then(function () {
163
- emitter_1.Emitter.Emit(scope.emitter, scope);
164
- });
165
- }
166
- const updateScopeQueue = list_1.List.Create();
167
- function ProcessScopeUpdateQueue() {
168
- const processList = list_1.List.Split(updateScopeQueue, 0);
169
- for (let node = processList.head; node !== null; node = node.next)
170
- UpdateScope(node.data);
171
- list_1.List.Clear(processList);
172
- }
173
- function QueueScopeUpdate(scope) {
174
- list_1.List.Add(updateScopeQueue, scope);
175
- if (updateScopeQueue.size === 1)
176
- queueMicrotask(ProcessScopeUpdateQueue);
177
- }
178
143
  function CalcChanged(calc) {
179
144
  const value = calc.getFunction();
180
145
  const changed = calc.value !== value;
@@ -182,35 +147,48 @@ function CalcChanged(calc) {
182
147
  return changed;
183
148
  }
184
149
  function DirtyScope(scope) {
185
- scope.dirty = scope.calcFunctions === null || scope.calcFunctions.some(CalcChanged);
186
- scope.dirty && (scope.async ? QueueScopeUpdate(scope) : emitter_1.Emitter.Emit(scope.emitter, scope));
150
+ if (scope.dirty || !scope.getFunction)
151
+ return;
152
+ scope.dirty = scope.calcFunctions.length === 0 || scope.calcFunctions.some(CalcChanged);
153
+ scope.dirty && emitter_1.Emitter.Emit(scope.emitter, scope);
154
+ }
155
+ const scopeQueue = new Set();
156
+ function ProcessScopeQueue() {
157
+ const scopes = Array.from(scopeQueue);
158
+ scopeQueue.clear();
159
+ for (let x = 0; x < scopes.length; x++)
160
+ DirtyScope(scopes[x]);
187
161
  }
188
162
  function OnSet(scope) {
189
- if (!scope || scope.dirty || scope.destroyed)
190
- return scope?.destroyed;
163
+ if (scope.destroyed)
164
+ return true;
165
+ if (scope.async || scope.calcFunctions.length > 0) {
166
+ if (scopeQueue.size === 0)
167
+ queueMicrotask(ProcessScopeQueue);
168
+ scopeQueue.add(scope);
169
+ return;
170
+ }
191
171
  DirtyScope(scope);
192
- return false;
193
172
  }
194
173
  function UpdateValue(scope) {
195
174
  if (!scope.dirty)
196
175
  return;
197
176
  scope.dirty = false;
198
- scope.watchEmitters = null;
199
- scope.calcFunctions = null;
200
- const value = WatchScope(scope);
177
+ const [value, emitters, calcFunctions] = WatchScope(scope);
201
178
  if (scope.async) {
202
179
  scope.promise = value.then(function (result) {
203
180
  scope.value = result;
181
+ emitter_1.Emitter.Emit(scope.emitter, scope);
204
182
  return result;
205
183
  });
206
184
  }
207
185
  else
208
186
  scope.value = value;
209
- UpdateEmitters(scope);
187
+ scope.calcFunctions = calcFunctions;
188
+ UpdateEmitters(scope, emitters);
210
189
  }
211
- function UpdateEmitters(scope) {
212
- const right = scope.watchEmitters;
213
- if (right === null) {
190
+ function UpdateEmitters(scope, right) {
191
+ if (right.length === 0) {
214
192
  if (scope.emitters.length > 0) {
215
193
  for (let x = 0; x < scope.emitters.length; x++)
216
194
  emitter_1.Emitter.Remove(scope.emitters[x], scope.setCallback);
@@ -218,7 +196,6 @@ function UpdateEmitters(scope) {
218
196
  }
219
197
  return;
220
198
  }
221
- emitter_1.Emitter.Sort(right);
222
199
  (0, array_1.ReconcileSortedArrays)(scope.emitters, right, function (emitter) {
223
200
  emitter_1.Emitter.On(emitter, scope.setCallback);
224
201
  }, function (emitter) {
@@ -0,0 +1,15 @@
1
+ type Compare<T> = (a: T, b: T) => number;
2
+ export interface AvlTree<T> {
3
+ size: number;
4
+ root: AvlTreeNode<T> | null;
5
+ compare: Compare<T>;
6
+ }
7
+ export type AvlTreeNode<T> = [T, number, number, AvlTreeNode<T> | null, AvlTreeNode<T> | null];
8
+ export declare namespace AVL {
9
+ function Create<T>(compare: Compare<T>): AvlTree<T>;
10
+ function Clear(tree: AvlTree<unknown>): void;
11
+ function Insert<T>(tree: AvlTree<T>, value: T): void;
12
+ function ForEach<T>(tree: AvlTree<T>, callback: (value: T) => void): void;
13
+ function ToArray<T>(tree: AvlTree<T>): T[];
14
+ }
15
+ export {};
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AVL = void 0;
4
+ const VALUE = 0;
5
+ const BALANCE = 1;
6
+ const HEIGHT = 2;
7
+ const LEFT = 3;
8
+ const RIGHT = 4;
9
+ function Squash(x) {
10
+ return x ? x < 0 ? -1 : 1 : 0;
11
+ }
12
+ var AVL;
13
+ (function (AVL) {
14
+ function Create(compare) {
15
+ return CreateTree(compare);
16
+ }
17
+ AVL.Create = Create;
18
+ function Clear(tree) {
19
+ tree.root = null;
20
+ tree.size = 0;
21
+ }
22
+ AVL.Clear = Clear;
23
+ function Insert(tree, value) {
24
+ if (tree.size === 0) {
25
+ tree.root = CreateNode(value);
26
+ tree.size = 1;
27
+ return;
28
+ }
29
+ InsertValue(tree, value);
30
+ }
31
+ AVL.Insert = Insert;
32
+ function ForEach(tree, callback) {
33
+ PreOrder(tree.root, callback);
34
+ }
35
+ AVL.ForEach = ForEach;
36
+ function ToArray(tree) {
37
+ const result = new Array(tree.size);
38
+ let index = 0;
39
+ ForEach(tree, function (value) {
40
+ result[index++] = value;
41
+ });
42
+ return result;
43
+ }
44
+ AVL.ToArray = ToArray;
45
+ })(AVL || (exports.AVL = AVL = {}));
46
+ function PreOrder(node, callback) {
47
+ if (node === null)
48
+ return;
49
+ PreOrder(node[LEFT], callback);
50
+ callback(node[VALUE]);
51
+ PreOrder(node[RIGHT], callback);
52
+ }
53
+ function CreateTree(compare) {
54
+ return {
55
+ size: 0,
56
+ compare,
57
+ root: null,
58
+ };
59
+ }
60
+ function CreateNode(value) {
61
+ return [value, 0, 1, null, null];
62
+ }
63
+ function InsertValue(tree, value) {
64
+ const startSize = tree.size;
65
+ let node = tree.root;
66
+ let comp = 0;
67
+ const path = [];
68
+ while (node !== null) {
69
+ comp = Squash(tree.compare(value, node[VALUE]));
70
+ path.push([comp, node]);
71
+ switch (comp) {
72
+ case 0:
73
+ node = null;
74
+ break;
75
+ case -1:
76
+ node = node[LEFT] ??= (tree.size++, CreateNode(value));
77
+ break;
78
+ case 1:
79
+ node = node[RIGHT] ??= (tree.size++, CreateNode(value));
80
+ break;
81
+ }
82
+ }
83
+ if (tree.size === startSize)
84
+ return;
85
+ for (let x = path.length - 2; x >= 0; x--) {
86
+ SetHeight(path[x][1]);
87
+ if (Math.abs(path[x][1][BALANCE]) === 2) {
88
+ const newRoot = BalanceNode(path[x][1]);
89
+ if (x === 0)
90
+ tree.root = newRoot;
91
+ else {
92
+ const [comp, parent] = path[x - 1];
93
+ switch (comp) {
94
+ case -1:
95
+ parent[LEFT] = newRoot;
96
+ break;
97
+ case 1:
98
+ parent[RIGHT] = newRoot;
99
+ break;
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ function BalanceNode(node) {
106
+ if (node[BALANCE] < 0) {
107
+ if (node[LEFT][BALANCE] > 0)
108
+ node[LEFT] = RotateLeft(node[LEFT]);
109
+ return RotateRight(node);
110
+ }
111
+ if (node[RIGHT][BALANCE] < 0)
112
+ node[RIGHT] = RotateRight(node[RIGHT]);
113
+ return RotateLeft(node);
114
+ }
115
+ function RotateLeft(node) {
116
+ const startRightLeft = node[RIGHT][LEFT];
117
+ const root = node[RIGHT];
118
+ root[LEFT] = node;
119
+ node[RIGHT] = startRightLeft;
120
+ SetHeight(node);
121
+ SetHeight(root);
122
+ return root;
123
+ }
124
+ function RotateRight(node) {
125
+ const startLeftRight = node[LEFT][RIGHT];
126
+ const root = node[LEFT];
127
+ root[RIGHT] = node;
128
+ node[LEFT] = startLeftRight;
129
+ SetHeight(node);
130
+ SetHeight(root);
131
+ return root;
132
+ }
133
+ function SetHeight(node) {
134
+ const leftHeight = node[LEFT]?.[HEIGHT] ?? 0;
135
+ const rightHeight = node[RIGHT]?.[HEIGHT] ?? 0;
136
+ const balance = rightHeight - leftHeight;
137
+ const height = leftHeight > rightHeight ? leftHeight : rightHeight;
138
+ node[HEIGHT] = height + 1;
139
+ node[BALANCE] = balance;
140
+ }
@@ -0,0 +1,10 @@
1
+ export type DistinctArray<T> = {
2
+ id: (value: T) => number;
3
+ distinct: T[];
4
+ array: T[];
5
+ };
6
+ export declare namespace DistinctArray {
7
+ function Create<T>(id: (value: T) => number): DistinctArray<T>;
8
+ function Push<T>({ id, distinct, array }: DistinctArray<T>, value: T): void;
9
+ function Get<T>({ array }: DistinctArray<T>): T[];
10
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DistinctArray = void 0;
4
+ var DistinctArray;
5
+ (function (DistinctArray) {
6
+ function Create(id) {
7
+ return {
8
+ id,
9
+ distinct: [],
10
+ array: []
11
+ };
12
+ }
13
+ DistinctArray.Create = Create;
14
+ function Push({ id, distinct, array }, value) {
15
+ const vId = id(value);
16
+ if (distinct[vId] === undefined) {
17
+ distinct[vId] = value;
18
+ array.push(value);
19
+ }
20
+ }
21
+ DistinctArray.Push = Push;
22
+ function Get({ array }) {
23
+ return array;
24
+ }
25
+ DistinctArray.Get = Get;
26
+ })(DistinctArray || (exports.DistinctArray = DistinctArray = {}));
@@ -2,9 +2,11 @@ export type EmitterCallback<T extends readonly any[] = any[]> = (...args: T) =>
2
2
  export type Emitter = [number, ...EmitterCallback[]];
3
3
  export declare namespace Emitter {
4
4
  function Create(): Emitter;
5
+ function GetId(emitter: Emitter): number;
5
6
  function On(emitter: Emitter, callback: EmitterCallback): void;
6
7
  function Emit(emitter: Emitter, ...args: any[]): void;
7
8
  function Remove(emitter: Emitter, callback: EmitterCallback): void;
8
9
  function Clear(emitter: Emitter): void;
9
10
  function Sort(emitters: Emitter[]): Emitter[];
11
+ function Compare(a: Emitter, b: Emitter): number;
10
12
  }
package/Utils/emitter.js CHANGED
@@ -10,6 +10,10 @@ var Emitter;
10
10
  return emitter;
11
11
  }
12
12
  Emitter.Create = Create;
13
+ function GetId(emitter) {
14
+ return emitter[0];
15
+ }
16
+ Emitter.GetId = GetId;
13
17
  function On(emitter, callback) {
14
18
  emitter.push(callback);
15
19
  }
@@ -43,4 +47,5 @@ var Emitter;
43
47
  function Compare(a, b) {
44
48
  return a[0] - b[0];
45
49
  }
50
+ Emitter.Compare = Compare;
46
51
  })(Emitter || (exports.Emitter = Emitter = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "j-templates",
3
- "version": "6.1.11",
3
+ "version": "6.1.12",
4
4
  "description": "j-templates",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/TypesInCode/jTemplates",