solarite 0.2.2 → 0.2.3
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/package.json +3 -2
- package/src/unused/FastLookupArray.js +0 -54
- package/src/unused/Hashes.js +0 -339
- package/src/unused/InUse.test.js +0 -92
- package/src/unused/InUseMap.js +0 -98
- package/src/unused/LinkedList.js +0 -117
- package/src/unused/LinkedList.test.js +0 -115
- package/src/unused/NodeGroupManager.js +0 -444
- package/src/unused/Perf.js +0 -47
- package/src/unused/Template.js +0 -108
- package/src/unused/onConnect.js +0 -79
- package/src/unused/watch.js +0 -302
- package/src/unused/watch2.js +0 -439
package/src/unused/onConnect.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// TODO: Everything here fails because our own connectedCallback function is never called.
|
|
2
|
-
// Perhaps b/c these callbacks must be defined before we register the custom element.
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @type {Map<HTMLElement, Set<function(HTMLElement)>>} */
|
|
7
|
-
let connectCallbacks = new Map();
|
|
8
|
-
/**
|
|
9
|
-
* @type {Map<HTMLElement, Set<function(HTMLElement)>>} */
|
|
10
|
-
let firstConnectCallbacks = new Map();
|
|
11
|
-
/**
|
|
12
|
-
* @type {Map<HTMLElement, Set<function(HTMLElement)>>} */
|
|
13
|
-
let disconnectCallbacks = new Map();
|
|
14
|
-
|
|
15
|
-
function getElCallbacks(el, map) {
|
|
16
|
-
let callbacks = connectCallbacks.get(el);
|
|
17
|
-
if (!callbacks) {
|
|
18
|
-
callbacks = new Set();
|
|
19
|
-
connectCallbacks.set(el, callbacks);
|
|
20
|
-
}
|
|
21
|
-
return callbacks;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
let createConnectedCallback = el => () => {
|
|
25
|
-
debugger;
|
|
26
|
-
for (let cb of getElCallbacks(el, connectCallbacks))
|
|
27
|
-
cb();
|
|
28
|
-
|
|
29
|
-
let cbs = getElCallbacks(el, firstConnectCallbacks);
|
|
30
|
-
for (let cb of cbs) {
|
|
31
|
-
cb();
|
|
32
|
-
cbs.delete(cb);
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
* @param el {HTMLElement}
|
|
40
|
-
* @param callback {function}
|
|
41
|
-
* @return {function()} A function that removes the callback. */
|
|
42
|
-
export function onConnect(el, callback) {
|
|
43
|
-
let callbacks = getElCallbacks(el, connectCallbacks);
|
|
44
|
-
callbacks.add(callback);
|
|
45
|
-
|
|
46
|
-
if (!el.constructor.prototype.hasOwnProperty('connectedCallback'))
|
|
47
|
-
el.constructor.prototype.connectedCallback = createConnectedCallback(el);
|
|
48
|
-
|
|
49
|
-
return () => {
|
|
50
|
-
callbacks.delete(callback);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function onFirstConnect(el, callback) {
|
|
55
|
-
let callbacks = getElCallbacks(el, firstConnectCallbacks);
|
|
56
|
-
callbacks.add(callback);
|
|
57
|
-
|
|
58
|
-
if (!el.hasOwnProperty('connectedCallback'))
|
|
59
|
-
el.connectedCallback = createConnectedCallback(el);
|
|
60
|
-
|
|
61
|
-
return () => {
|
|
62
|
-
callbacks.delete(callback);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function onDisconnect(el, callback) {
|
|
67
|
-
let callbacks = getElCallbacks(el, disconnectCallbacks);
|
|
68
|
-
callbacks.add(callback);
|
|
69
|
-
|
|
70
|
-
if (!el.hasOwnProperty('connectedCallback'))
|
|
71
|
-
el.connectedCallback = () => {
|
|
72
|
-
for (let cb of callbacks)
|
|
73
|
-
cb();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return () => {
|
|
77
|
-
callbacks.delete(callback);
|
|
78
|
-
}
|
|
79
|
-
}
|
package/src/unused/watch.js
DELETED
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tools for watch variables and performing precise renders.
|
|
3
|
-
*/
|
|
4
|
-
import {assert} from "../util/Errors.js";
|
|
5
|
-
import delve from "../util/delve.js";
|
|
6
|
-
import {getObjectHash, getObjectId} from "./hash.js";
|
|
7
|
-
import MultiValueMap from "./MultiValueMap.js";
|
|
8
|
-
//import NodeGroupManager, {LoopInfo} from "./NodeGroupManager.js";
|
|
9
|
-
import Template from "./Template.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Stores info how to transform a path to a template. */
|
|
14
|
-
export class TransformerInfo {
|
|
15
|
-
constructor(path, transformer, hash) {
|
|
16
|
-
this.path = path;
|
|
17
|
-
this.transformer = transformer;
|
|
18
|
-
this.hash = hash;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Maps an object path to the function that converts it to a Template.
|
|
25
|
-
* Once it's convert to a template, we can get the hash of that Tempate.
|
|
26
|
-
* Then that hash tells us what NodeGroups are affected by the object.
|
|
27
|
-
*
|
|
28
|
-
* We store the function to get the Template, instead of the Template itself,
|
|
29
|
-
* so we can call that function again when the object has a new value.
|
|
30
|
-
* @type {MultiValueMap<Object, function(...Object):Template>} */
|
|
31
|
-
let pathToTransformer = new MultiValueMap(); // uses a Set() for each value.
|
|
32
|
-
export {pathToTransformer}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Watch the given properties on obj and call obj.render() when any of them are changed.
|
|
38
|
-
* @param obj {Object}
|
|
39
|
-
* @param props {string[]} */
|
|
40
|
-
export function renderWhenChanged(obj, ...props) {
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
*
|
|
46
|
-
* @param objectPaths {(*|function)[]}
|
|
47
|
-
* @returns {Template} */
|
|
48
|
-
export function watchGet(...objectPaths) {
|
|
49
|
-
|
|
50
|
-
/** @type {function} */
|
|
51
|
-
let transformer = objectPaths.at(-1);
|
|
52
|
-
let paths;
|
|
53
|
-
if (typeof transformer === 'function') {
|
|
54
|
-
paths = objectPaths.slice(0, -1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// No transformer provided, so we create our own.
|
|
58
|
-
else if (objectPaths.length === 1) {
|
|
59
|
-
paths = [objectPaths[0].slice(0, -1)];
|
|
60
|
-
let prop = objectPaths[0].at(-1);
|
|
61
|
-
transformer = (...args) => (args[0][prop])
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// Save arguments used to call the template, so we can call it again when those args have their values change.
|
|
66
|
-
let args = [];
|
|
67
|
-
for (let path of paths) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
let obj = delve(watchSet(path[0]), path.slice(1));
|
|
71
|
-
args.push(obj);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
let template = transformer(...args);
|
|
75
|
-
|
|
76
|
-
// If the result isn't a Template, convert the function to return a Template that wraps the result.
|
|
77
|
-
// This way NodeGroupManager.findAndDelete() can find a NodeGroup that matches this Template's hash.
|
|
78
|
-
if (!(template instanceof Template)) {
|
|
79
|
-
let oldToTemplate = transformer;
|
|
80
|
-
transformer = function() {
|
|
81
|
-
return new Template(['', ''], [oldToTemplate(...arguments)]);
|
|
82
|
-
}
|
|
83
|
-
template = transformer(...args);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Map the object paths to the function that creates a template.
|
|
87
|
-
let hash = getObjectHash(template);
|
|
88
|
-
for (let path of paths) {
|
|
89
|
-
let serializedPath = serializePath(path);
|
|
90
|
-
pathToTransformer.add(serializedPath, new TransformerInfo(path, transformer, hash)); // Uses a Set() to ensure no duplicates.
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return template;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
//let proxyCache = new WeakMap();
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Set the value of a variable in a way that's watched, so later when we call .renderWatched()
|
|
101
|
-
* We can find what NodeGroups to update.*/
|
|
102
|
-
export function watchSet(obj) {
|
|
103
|
-
if (obj?.$isProxy===true)
|
|
104
|
-
return obj; // It's already a Proxy.
|
|
105
|
-
|
|
106
|
-
// This cache doesn't make things faster.
|
|
107
|
-
// let result = proxyCache.get(obj);
|
|
108
|
-
// if (!result) {
|
|
109
|
-
// result = new Proxy(obj, new ProxyHandler(obj));
|
|
110
|
-
// proxyCache.set(obj, result);
|
|
111
|
-
// }
|
|
112
|
-
// return result;
|
|
113
|
-
return new Proxy(obj, new ProxyHandler(obj));
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Loop over each item and apply watchGet() to each item.
|
|
118
|
-
* @param arrayPath {*[]}
|
|
119
|
-
* @param callback {function(obj:Object, index:int):Template}
|
|
120
|
-
* @returns {Template} */
|
|
121
|
-
export function forEach(arrayPath, callback) {
|
|
122
|
-
let array = delve(arrayPath[0], arrayPath.slice(1));
|
|
123
|
-
|
|
124
|
-
// This is retrieved on the 'insert' path inside renderWatched()
|
|
125
|
-
let ngm = NodeGroupManager.get(arrayPath[0]);
|
|
126
|
-
if (ngm.clearSubscribers) {
|
|
127
|
-
ngm.clearSubscribers = false;
|
|
128
|
-
ngm.pathToLoopInfo = new MultiValueMap();
|
|
129
|
-
} // TODO: Move tis into NodeGroupMAnager.get() without breaking things?
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
let newItems = [...array.map((item, i) => {
|
|
133
|
-
// TODO: This needs to wrap callback so we can pass it the index also.
|
|
134
|
-
return watchGet([...arrayPath, i], callback); // calls callback(array[i], i)
|
|
135
|
-
})
|
|
136
|
-
];
|
|
137
|
-
|
|
138
|
-
// We return a template that wraps the array
|
|
139
|
-
// So that ExprPath.apply() can set the ExprPath and nextSibling on the template.
|
|
140
|
-
// Then the 'insert' path in renderWatched() uses that data fora dding more nodes.
|
|
141
|
-
let result = new Template(['', ''], [newItems])
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
// We get a unique hash for each foreach template because the [''] array is unique each time.
|
|
145
|
-
let loopInfo = new LoopInfo(result, callback);
|
|
146
|
-
ngm.pathToLoopInfo.add(serializePath(arrayPath), loopInfo);
|
|
147
|
-
return result;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export function serializePath(path) {
|
|
151
|
-
// Convert any array indices to strings, so serialized comparisons work.
|
|
152
|
-
return JSON.stringify([getObjectId(path[0]), ...path.slice(1).map(item => item+'')])
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* When an object property is accessed, a new Proxy with a new instance of this handler class is created,
|
|
159
|
-
* but it tracks the path from the root to the property.
|
|
160
|
-
* That way when a property is set, it can report the changed path. */
|
|
161
|
-
class ProxyHandler {
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* @param root An element managed by a NodeGroupManager. The same as the NodeGroupManager's rootEl.
|
|
165
|
-
* @param path {string[]} Used internally. */
|
|
166
|
-
constructor(root, path=[]) {
|
|
167
|
-
/*#IFDEV*/assert(NodeGroupManager.get(root))/*#ENDIF*/
|
|
168
|
-
this.root = root;
|
|
169
|
-
this.path = path; // path from root to this Proxy.
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* @param obj {Object}
|
|
174
|
-
* @param prop {string} */
|
|
175
|
-
get(obj, prop) {
|
|
176
|
-
|
|
177
|
-
// Special props. Currently unused.
|
|
178
|
-
// if (prop === '$path')
|
|
179
|
-
// return this.path;
|
|
180
|
-
// if (prop === '$root')
|
|
181
|
-
// return this.root;
|
|
182
|
-
if (prop === '$isProxy')
|
|
183
|
-
return true;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// 1. Array.splice()
|
|
187
|
-
if (prop === 'splice' && Array.isArray(obj)) {
|
|
188
|
-
return (index, deleteCount, ...items) => {
|
|
189
|
-
let ngm = NodeGroupManager.get(this.root)
|
|
190
|
-
|
|
191
|
-
if (deleteCount) {
|
|
192
|
-
|
|
193
|
-
// Get the hash of each object along the delete range. The process to get the hash is:
|
|
194
|
-
// Serialized Path -> transformer -> Template -> hash.
|
|
195
|
-
let hashes = [];
|
|
196
|
-
for (let i=index; i<index+deleteCount; i++) {
|
|
197
|
-
let serializedPath = serializePath([this.root, ...this.path, i+'']);
|
|
198
|
-
|
|
199
|
-
let obj = delve(this.root, [...this.path, i])
|
|
200
|
-
for (let transformerInfo of pathToTransformer.getAll(serializedPath)) {
|
|
201
|
-
let template = transformerInfo.transformer(obj);
|
|
202
|
-
let hash = getObjectHash(template);
|
|
203
|
-
hashes.push(hash); // Hashes may go to nodes in more than one loop.
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
ngm.changes.push(new Change('delete', this.root, [...this.path, index+''], hashes));
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
//let oldArray = [...obj];
|
|
211
|
-
let result = obj.splice(index, deleteCount);
|
|
212
|
-
|
|
213
|
-
// Inserting
|
|
214
|
-
if (items.length) {
|
|
215
|
-
|
|
216
|
-
let beforeNgs;
|
|
217
|
-
for (let loopInfo of ngm.getLoopInfo([this.root, ...this.path])) {
|
|
218
|
-
let beforeObj = delve(this.root, [...this.path, index]);
|
|
219
|
-
|
|
220
|
-
// Find where to insert before.
|
|
221
|
-
if (beforeObj) {
|
|
222
|
-
let beforeTemplate = loopInfo.itemTransformer(beforeObj);
|
|
223
|
-
let beforeHash = getObjectHash(beforeTemplate);
|
|
224
|
-
beforeNgs = ngm.nodeGroupsAvailable.data[beforeHash];
|
|
225
|
-
|
|
226
|
-
if (beforeNgs) {
|
|
227
|
-
let hash = getObjectHash(loopInfo.template)
|
|
228
|
-
let loopNgs = ngm.nodeGroupsAvailable.data[hash] || [];
|
|
229
|
-
for (let loopNg of loopNgs)
|
|
230
|
-
for (let beforeNg of beforeNgs)
|
|
231
|
-
if (beforeNg.startNode.parentNode === loopNg.startNode.parentNode)
|
|
232
|
-
ngm.changes.push(new Change('insert', this.root, [...this.path, index + ''], items, beforeTemplate));
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
if (!beforeNgs)
|
|
236
|
-
ngm.changes.push(new Change('insert', this.root, [...this.path, index + ''], items));
|
|
237
|
-
}
|
|
238
|
-
obj.splice(index, 0, ...items);
|
|
239
|
-
}
|
|
240
|
-
return result;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
// 2. Get property
|
|
247
|
-
// If we're getting an object or array property, apply watch() to it recursively.
|
|
248
|
-
let result = Reflect.get(obj, prop)
|
|
249
|
-
if (result && typeof result === 'object') {
|
|
250
|
-
let handler = new ProxyHandler(this.root, [...this.path, prop]); // same root, one level deeper on the path.
|
|
251
|
-
return new Proxy(result, handler);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return result;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
set(obj, prop, newValue) {
|
|
259
|
-
let ngm = NodeGroupManager.get(this.root);
|
|
260
|
-
ngm.changes.push(new Change('set', this.root, [...this.path, prop], newValue));
|
|
261
|
-
return Reflect.set(obj, prop, newValue)
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
*
|
|
268
|
-
*/
|
|
269
|
-
class Change {
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* @param action {string}
|
|
273
|
-
* @param root {Object|Array}
|
|
274
|
-
* @param path {string[]}
|
|
275
|
-
* @param value
|
|
276
|
-
* If setting a value, this is the new value.
|
|
277
|
-
* If deleting from an array, this is an array of all the NodeGroups to delete.
|
|
278
|
-
*
|
|
279
|
-
* @param beforeTemplate
|
|
280
|
-
* */
|
|
281
|
-
constructor(action, root, path, value, beforeTemplate=null) {
|
|
282
|
-
this.action = action;
|
|
283
|
-
|
|
284
|
-
// TODO: Store root as first item of path, to be consistent with code elsewhere.
|
|
285
|
-
this.root = root;
|
|
286
|
-
this.path = path;
|
|
287
|
-
this.value = value;
|
|
288
|
-
this.beforeTemplate = beforeTemplate;
|
|
289
|
-
|
|
290
|
-
/** @type {TransformerInfo[]} */
|
|
291
|
-
this.transformerInfo = [];
|
|
292
|
-
|
|
293
|
-
// Traverse up the path.
|
|
294
|
-
for (let i=this.path.length; i>0; i--) {
|
|
295
|
-
let path = this.path.slice(0, i);
|
|
296
|
-
let fullPath = [this.root, ...path];
|
|
297
|
-
|
|
298
|
-
let serializedPath = getObjectHash(fullPath); // TODO: Why not serializedPath() ?
|
|
299
|
-
this.transformerInfo.push(...pathToTransformer.getAll(serializedPath))
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|