solarite 0.3.0 → 0.3.2
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/dist/Solarite-debug.js +411 -524
- package/dist/Solarite.js +394 -507
- package/dist/Solarite.min.js +2 -2
- package/package.json +5 -6
- package/readme.md +2 -2
- package/src/{solarite/ExprPath.js → ExprPath.js} +43 -58
- package/src/{solarite/Globals.js → Globals.js} +4 -4
- package/src/{util/MultiValueMap.js → MultiValueMap.js} +1 -32
- package/src/{solarite/NodeGroup.js → NodeGroup.js} +30 -26
- package/src/{solarite/Shell.js → Shell.js} +8 -7
- package/src/Solarite.d.ts +62 -0
- package/src/{solarite/Solarite.js → Solarite.js} +13 -15
- package/src/{solarite/Template.js → Template.js} +1 -1
- package/src/{solarite/Util.js → Util.js} +49 -45
- package/src/{solarite/createSolarite.js → createSolarite.js} +12 -10
- package/src/{solarite/getArg.js → getArg.js} +24 -3
- package/src/{solarite/h.js → h.js} +4 -12
- package/src/unused/FastLookupArray.js +54 -0
- package/src/unused/Hashes.js +339 -0
- package/src/unused/InUse.test.js +92 -0
- package/src/unused/InUseMap.js +98 -0
- package/src/unused/LinkedList.js +117 -0
- package/src/unused/LinkedList.test.js +115 -0
- package/src/unused/Misc.js +13 -0
- package/src/unused/Perf.js +47 -0
- package/src/unused/TrackedArray.js +54 -0
- package/src/unused/WeakArray.js +33 -0
- package/src/{solarite/watch.js → watch.js} +4 -4
- package/src/util/Util.js +0 -101
- /package/src/{solarite/HtmlParser.js → HtmlParser.js} +0 -0
- /package/src/{util/Errors.js → assert.js} +0 -0
- /package/src/{util/delve.js → delve.js} +0 -0
- /package/src/{solarite/hash.js → hash.js} +0 -0
- /package/src/{solarite/udomdiff.js → udomdiff.js} +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import Testimony, {assert} from "../../tests/Testimony.js";
|
|
2
|
+
import LinkedList from "./LinkedList.js";
|
|
3
|
+
|
|
4
|
+
Testimony.test('LinkedList.constructor with Array input', () => {
|
|
5
|
+
const linkedList = new LinkedList(['A', 'B', 'C']);
|
|
6
|
+
assert.eq([...linkedList], ['A', 'B', 'C']);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
Testimony.test('LinkedList.constructor with LinkedList input', () => {
|
|
10
|
+
const originalList = new LinkedList(['X', 'Y', 'Z']);
|
|
11
|
+
const copiedList = new LinkedList(originalList);
|
|
12
|
+
assert.eq([...copiedList], ['X', 'Y', 'Z']);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
Testimony.test('LinkedList.constructor with mixed input', () => {
|
|
16
|
+
const originalList = new LinkedList(['D', 'E']);
|
|
17
|
+
const extendedList = new LinkedList([...originalList, 'F', 'G']);
|
|
18
|
+
assert.eq([...extendedList], ['D', 'E', 'F', 'G']);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
Testimony.test('LinkedList.constructor with no input', () => {
|
|
22
|
+
const emptyList = new LinkedList();
|
|
23
|
+
assert.eq([...emptyList], []);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Testimony.test('LinkedList.push', () => {
|
|
28
|
+
const linkedList = new LinkedList();
|
|
29
|
+
linkedList.push("A");
|
|
30
|
+
linkedList.push("B");
|
|
31
|
+
assert.eq([...linkedList], ['A', 'B']);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
Testimony.test('LinkedList.unshift', () => {
|
|
35
|
+
const linkedList = new LinkedList();
|
|
36
|
+
linkedList.unshift("B");
|
|
37
|
+
linkedList.unshift("A");
|
|
38
|
+
assert.eq([...linkedList], ['A', 'B']);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
Testimony.test('LinkedList.shift', () => {
|
|
42
|
+
const linkedList = new LinkedList();
|
|
43
|
+
linkedList.push("A");
|
|
44
|
+
linkedList.push("B");
|
|
45
|
+
linkedList.shift();
|
|
46
|
+
assert.eq([...linkedList], ['B']);
|
|
47
|
+
linkedList.shift();
|
|
48
|
+
assert.eq([...linkedList], []);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
Testimony.test('LinkedList.pop', () => {
|
|
52
|
+
const linkedList = new LinkedList();
|
|
53
|
+
linkedList.push("A");
|
|
54
|
+
linkedList.push("B");
|
|
55
|
+
linkedList.pop();
|
|
56
|
+
assert.eq([...linkedList], ['A']);
|
|
57
|
+
linkedList.pop();
|
|
58
|
+
assert.eq([...linkedList], []);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
Testimony.test('LinkedList.slice', () => {
|
|
62
|
+
const linkedList = new LinkedList();
|
|
63
|
+
linkedList.push("A");
|
|
64
|
+
linkedList.push("B");
|
|
65
|
+
linkedList.push("C");
|
|
66
|
+
const subList = linkedList.slice("A", "B");
|
|
67
|
+
assert.eq([...subList], ['A', 'B']);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
Testimony.test('LinkedList._splice', () => {
|
|
71
|
+
const linkedList = new LinkedList();
|
|
72
|
+
linkedList.push("A");
|
|
73
|
+
linkedList.push("B");
|
|
74
|
+
linkedList.splice("A", null, ["X", "Y"]);
|
|
75
|
+
assert.eq([...linkedList], ['A', 'X', 'Y', 'B']);
|
|
76
|
+
linkedList.splice("X", "Y");
|
|
77
|
+
assert.eq([...linkedList], ['B']);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
function buildData(count = rowCount) {
|
|
84
|
+
function _random(max) {
|
|
85
|
+
return Math.round(Math.random()*1000)%max;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
var adjectives = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"];
|
|
89
|
+
var colours = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"];
|
|
90
|
+
var nouns = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"];
|
|
91
|
+
var data = [];
|
|
92
|
+
for (let i=0; i<count; i++)
|
|
93
|
+
data.push({id: i, label: adjectives[_random(adjectives.length)] + " " + colours[_random(colours.length)] + " " + nouns[_random(nouns.length)] });
|
|
94
|
+
return data;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
Testimony.test('LinkedList.benchmark', () => {
|
|
99
|
+
|
|
100
|
+
let data = buildData(10_000)
|
|
101
|
+
let start = performance.now()
|
|
102
|
+
let list = new LinkedList(data);
|
|
103
|
+
console.log(performance.now() - start)
|
|
104
|
+
|
|
105
|
+
start = performance.now()
|
|
106
|
+
let i = 0;
|
|
107
|
+
for (let item in list) {
|
|
108
|
+
i++;
|
|
109
|
+
}
|
|
110
|
+
console.log(i)
|
|
111
|
+
console.log(performance.now() - start)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
var Perf = {
|
|
2
|
+
_timers: {},
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Start a timer with a given name.
|
|
6
|
+
* @param timerName {string}
|
|
7
|
+
*/
|
|
8
|
+
start(timerName) {
|
|
9
|
+
if (!Perf._timers[timerName]) {
|
|
10
|
+
Perf._timers[timerName] = {
|
|
11
|
+
startTime: null,
|
|
12
|
+
elapsedTime: 0
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
Perf._timers[timerName].startTime = performance.now();
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Stop a timer with a given name and calculate the elapsed time.
|
|
20
|
+
* @param timerName {string}
|
|
21
|
+
*/
|
|
22
|
+
stop(timerName) {
|
|
23
|
+
if (Perf._timers[timerName] && Perf._timers[timerName].startTime !== null) {
|
|
24
|
+
let stopTime = performance.now();
|
|
25
|
+
Perf._timers[timerName].elapsedTime += stopTime - Perf._timers[timerName].startTime;
|
|
26
|
+
Perf._timers[timerName].startTime = null; // Reset start time
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get the total time elapsed for each timer.
|
|
32
|
+
* @return {string[]}
|
|
33
|
+
*/
|
|
34
|
+
getReport() {
|
|
35
|
+
let report = [];
|
|
36
|
+
for (let timerName in Perf._timers) {
|
|
37
|
+
report.push(`${timerName}: ${Perf._timers[timerName].elapsedTime.toFixed(2)} ms`);
|
|
38
|
+
}
|
|
39
|
+
return report;
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
clear() {
|
|
43
|
+
this._timers = {};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default Perf;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
|
|
2
|
+
export default class TrackedArray extends Array {
|
|
3
|
+
constructor(...args) {
|
|
4
|
+
super(...args);
|
|
5
|
+
this.ops = [];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Intercepting 'push' as 'insert'
|
|
9
|
+
push(...items) {
|
|
10
|
+
const startIdx = this.length;
|
|
11
|
+
super.push(...items);
|
|
12
|
+
this.ops.push({ op: 'insert', index: startIdx, values: items });
|
|
13
|
+
return this.length;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Intercepting 'pop' as 'remove'
|
|
17
|
+
pop() {
|
|
18
|
+
const removedIndex = this.length - 1;
|
|
19
|
+
const removedItem = super.pop();
|
|
20
|
+
this.ops.push({ op: 'remove', index: removedIndex, length: 1 });
|
|
21
|
+
return removedItem;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Intercepting 'shift' as 'remove'
|
|
25
|
+
shift() {
|
|
26
|
+
const removedItem = super.shift();
|
|
27
|
+
this.ops.push({ op: 'remove', index: 0, length: 1 });
|
|
28
|
+
return removedItem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Intercepting 'unshift' as 'insert'
|
|
32
|
+
unshift(...items) {
|
|
33
|
+
super.unshift(...items);
|
|
34
|
+
this.ops.push({ op: 'insert', index: 0, values: items });
|
|
35
|
+
return this.length;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Intercepting 'splice' for insert, update, or remove
|
|
39
|
+
splice(start, deleteCount, ...items) {
|
|
40
|
+
const removedItems = super.splice(start, deleteCount, ...items);
|
|
41
|
+
|
|
42
|
+
if (deleteCount > 0) {
|
|
43
|
+
this.ops.push({ op: 'remove', index: start, length: deleteCount });
|
|
44
|
+
}
|
|
45
|
+
if (items.length > 0) {
|
|
46
|
+
const operation = deleteCount > 0 ? 'update' : 'insert';
|
|
47
|
+
this.ops.push({ op, index: start, values: items });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return removedItems;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// TODO: reverse, sorty, copyWithin, fill
|
|
54
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default class WeakArray {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.items = [];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
push(...items) {
|
|
7
|
+
for (let item of items) {
|
|
8
|
+
if (typeof item === 'object' && item)
|
|
9
|
+
this.items.push(new WeakRef(item));
|
|
10
|
+
else
|
|
11
|
+
throw new TypeError("Only objects can be added to a WeakArray");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get(index) {
|
|
16
|
+
const ref = this.items[index];
|
|
17
|
+
if (ref)
|
|
18
|
+
return ref.deref();
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
cleanup() {
|
|
23
|
+
this.items = this.items.filter(ref => ref.deref() !== undefined);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
*[Symbol.iterator]() {
|
|
27
|
+
for (const ref of this.items) {
|
|
28
|
+
const value = ref.deref();
|
|
29
|
+
if (value !== undefined)
|
|
30
|
+
yield value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -51,8 +51,8 @@ a.items.push({name: 'Fred'});
|
|
|
51
51
|
*/
|
|
52
52
|
|
|
53
53
|
import Globals from "./Globals.js";
|
|
54
|
-
import Util from "
|
|
55
|
-
import {assert} from "
|
|
54
|
+
import Util from "./Util.js";
|
|
55
|
+
import {assert} from "./assert.js";
|
|
56
56
|
|
|
57
57
|
let unusedArg = Symbol('unusedArg');
|
|
58
58
|
|
|
@@ -210,7 +210,7 @@ export function renderWatched(root, trackModified=false) {
|
|
|
210
210
|
* Handles getting and setting properties on the proxied object. */
|
|
211
211
|
class ProxyHandler {
|
|
212
212
|
|
|
213
|
-
/** @type {
|
|
213
|
+
/** @type {Record<string, [Proxy, ProxyHandler]>} Proxies for child properties. */
|
|
214
214
|
proxies = {}
|
|
215
215
|
|
|
216
216
|
/** @type Set<ExprPath> ExprPaths that will need to be re-rendered when this variable is modified. */
|
|
@@ -219,7 +219,7 @@ class ProxyHandler {
|
|
|
219
219
|
/**
|
|
220
220
|
* ExprPaths that will need to be re-rendered when one of this variable's primitive properties is modified,
|
|
221
221
|
* since primitives can't have their own ProxyHandler.
|
|
222
|
-
* @type {
|
|
222
|
+
* @type {Record<prop:string, affected:Set<ExprPath>>} */
|
|
223
223
|
childExprPaths = {};
|
|
224
224
|
|
|
225
225
|
|
package/src/util/Util.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @typedef {Array|function(...*)} Callbacks
|
|
6
|
-
* @property {function(function)} push
|
|
7
|
-
* @property {function()} remove
|
|
8
|
-
* @property {function()} pause
|
|
9
|
-
* @property {function()} resume
|
|
10
|
-
* */
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* A place for functions that have no other home. */
|
|
15
|
-
var Util = {
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Create an array-like object that stores a group of callbacks.
|
|
19
|
-
* Supports all array functions and properties like push() and .length.
|
|
20
|
-
* Can be called directly.
|
|
21
|
-
*
|
|
22
|
-
* @param functions {function[]}
|
|
23
|
-
* @return {Callbacks|function}
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* var c = Util.callback();
|
|
27
|
-
* var f = () => console.log(3);
|
|
28
|
-
* c.push(f);
|
|
29
|
-
* c();
|
|
30
|
-
* c.remove(f);
|
|
31
|
-
* c();
|
|
32
|
-
*/
|
|
33
|
-
callback(...functions) {
|
|
34
|
-
var paused = false;
|
|
35
|
-
|
|
36
|
-
// Make it callable. When we call it, call all callbacks() with the given args.
|
|
37
|
-
let result = async function(...args) {
|
|
38
|
-
let result2 = [];
|
|
39
|
-
if (!paused)
|
|
40
|
-
for (let i=0; i<result.length; i++)
|
|
41
|
-
result2.push(result[i](...args));
|
|
42
|
-
return await Promise.all(result2);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// Make it iterable.
|
|
46
|
-
result[Symbol.iterator] = function() {
|
|
47
|
-
let index = 0;
|
|
48
|
-
return {
|
|
49
|
-
next: () => index < result.length
|
|
50
|
-
? {value: result[index++], done: false}
|
|
51
|
-
: {done: true}
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// Use properties from Array
|
|
56
|
-
for (let prop of Object.getOwnPropertyNames(Array.prototype))
|
|
57
|
-
if (prop !== 'length' && prop !== 'constructor')
|
|
58
|
-
result[prop] = Array.prototype[prop];
|
|
59
|
-
|
|
60
|
-
result.l = 0; // Internal length
|
|
61
|
-
Object.defineProperty(result, 'length', {
|
|
62
|
-
get() { return result.l },
|
|
63
|
-
set(val) { result.l = val}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Add the remove() function.
|
|
67
|
-
result.remove = func => {
|
|
68
|
-
let idx = result.findIndex(item => item === func);
|
|
69
|
-
if (idx !== -1)
|
|
70
|
-
result.splice(idx, 1);
|
|
71
|
-
};
|
|
72
|
-
result.pause = () => paused = true;
|
|
73
|
-
|
|
74
|
-
result.resume = () => paused = false;
|
|
75
|
-
|
|
76
|
-
// Add initial functions
|
|
77
|
-
for (let f of functions)
|
|
78
|
-
result.push(f);
|
|
79
|
-
|
|
80
|
-
return result;
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Use an array as the value of a map, appending to it when we add.
|
|
85
|
-
* Used by watch.js.
|
|
86
|
-
* @param map {Map|WeakMap|Object}
|
|
87
|
-
* @param key
|
|
88
|
-
* @param value */
|
|
89
|
-
mapArrayAdd(map, key, value) {
|
|
90
|
-
let result = map.get(key);
|
|
91
|
-
if (!result) {
|
|
92
|
-
result = [value];
|
|
93
|
-
map.set(key, result);
|
|
94
|
-
}
|
|
95
|
-
else
|
|
96
|
-
result.push(value);
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
export default Util;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|