solarite 0.5.2 → 0.7.1
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/LICENSE +21 -0
- package/dist/Solarite-debug.js +4847 -3878
- package/dist/Solarite.js +4583 -3626
- package/dist/Solarite.min.js +2 -4
- package/package.json +19 -6
- package/readme.md +58 -11
- package/src/Globals.js +54 -72
- package/src/HtmlParser.js +90 -90
- package/src/MultiValueMap.js +57 -105
- package/src/NodeGroup.js +624 -470
- package/src/Path.js +224 -211
- package/src/PathToAttribValue.js +401 -261
- package/src/PathToAttribs.js +113 -80
- package/src/PathToComment.js +7 -7
- package/src/PathToComponent.js +183 -188
- package/src/PathToEvent.js +76 -64
- package/src/PathToKey.js +19 -0
- package/src/PathToNodes.js +1053 -566
- package/src/RootNodeGroup.js +120 -8
- package/src/Shell.js +570 -348
- package/src/Solarite.d.ts +134 -113
- package/src/Solarite.js +243 -286
- package/src/Template.js +195 -274
- package/src/Util.js +353 -351
- package/src/assert.js +10 -10
- package/src/assignAttributes.js +63 -0
- package/src/delve.js +55 -43
- package/src/h.js +220 -138
- package/src/jsx-dev-runtime.d.ts +1 -0
- package/src/jsx-dev-runtime.js +5 -0
- package/src/jsx-runtime.d.ts +21 -0
- package/src/jsx-runtime.js +84 -0
- package/src/jsx.js +194 -0
- package/src/toEl.js +77 -82
- package/dist/udomdiff-license.txt +0 -18
- package/src/getArg.js +0 -137
- package/src/hash.js +0 -89
- package/src/udomdiff.js +0 -176
- 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/Misc.js +0 -13
- package/src/unused/Perf.js +0 -47
- package/src/unused/TrackedArray.js +0 -54
- package/src/unused/WeakArray.js +0 -33
- package/src/watch.js +0 -543
package/src/Path.js
CHANGED
|
@@ -1,212 +1,225 @@
|
|
|
1
|
-
import assert from "./assert.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Path to where an expression should be evaluated within a Shell or NodeGroup. */
|
|
5
|
-
export default class Path {
|
|
6
|
-
|
|
7
|
-
// Used for attributes:
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @type {Node} Node that occurs before this Path's first Node.
|
|
11
|
-
* This is necessary because
|
|
12
|
-
* If we had a pointer to our own startNode then that node could be moved somewhere else w/o us knowing it.
|
|
13
|
-
* Used only for type='content'
|
|
14
|
-
* Will be null if Path has no Nodes. */
|
|
15
|
-
nodeBefore;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* If type is AttribType.Multiple or AttribType.Value, points to the node having the attribute.
|
|
19
|
-
* If type is 'content', points to a node that never changes that this NodeGroup should always insert its nodes before.
|
|
20
|
-
* An empty text node will be created to insertBefore if there's no other NodeMarker and this isn't at the last position.
|
|
21
|
-
* @type {Node|HTMLElement} */
|
|
22
|
-
nodeMarker;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* [
|
|
74
|
-
* [
|
|
75
|
-
* [
|
|
76
|
-
* []
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
*
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
let
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
//#
|
|
97
|
-
root
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
*
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
let
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
1
|
+
import assert from "./assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Path to where an expression should be evaluated within a Shell or NodeGroup. */
|
|
5
|
+
export default class Path {
|
|
6
|
+
|
|
7
|
+
// Used for attributes:
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @type {Node} Node that occurs before this Path's first Node.
|
|
11
|
+
* This is necessary because reconcileNodes() can steal nodes from another Path.
|
|
12
|
+
* If we had a pointer to our own startNode then that node could be moved somewhere else w/o us knowing it.
|
|
13
|
+
* Used only for type='content'
|
|
14
|
+
* Will be null if Path has no Nodes. */
|
|
15
|
+
nodeBefore;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* If type is AttribType.Multiple or AttribType.Value, points to the node having the attribute.
|
|
19
|
+
* If type is 'content', points to a node that never changes that this NodeGroup should always insert its nodes before.
|
|
20
|
+
* An empty text node will be created to insertBefore if there's no other NodeMarker and this isn't at the last position.
|
|
21
|
+
* @type {Node|HTMLElement} */
|
|
22
|
+
nodeMarker;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @type {boolean} True if the expression is the only child of its parent element.
|
|
26
|
+
* Then nodeMarker is that parent element, nodeBefore is null, and no marker comments exist. */
|
|
27
|
+
wholeParent = false;
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
// These are set after an expression is assigned:
|
|
31
|
+
|
|
32
|
+
/** @type {NodeGroup} */
|
|
33
|
+
parentNg;
|
|
34
|
+
|
|
35
|
+
// Caches to make things faster
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @private
|
|
39
|
+
* @type {Node[]} Cached result of getNodes() */
|
|
40
|
+
nodesCache;
|
|
41
|
+
|
|
42
|
+
// Set only on Shell paths, never on cloned instances, so they're not declared as
|
|
43
|
+
// class fields; that would cost a store per field on every clone:
|
|
44
|
+
// nodeBeforeIndex {int} Index of nodeBefore among its parentNode's children.
|
|
45
|
+
// nodeMarkerPath {int[]} Path to the node marker, in reverse for performance reasons.
|
|
46
|
+
// markerSlot/beforeSlot {int} Slot indexes into the Shell's resolve program.
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param nodeBefore {Node}
|
|
51
|
+
* @param nodeMarker {?Node}*/
|
|
52
|
+
constructor(nodeBefore, nodeMarker) {
|
|
53
|
+
this.nodeBefore = nodeBefore;
|
|
54
|
+
this.nodeMarker = nodeMarker;
|
|
55
|
+
/*#IFDEV*/this.verify();/*#ENDIF*/
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Apply expressions to a path.
|
|
60
|
+
* This is called by NodeGroup.applyExprs() when it's time to put the expression values into the DOM.
|
|
61
|
+
*
|
|
62
|
+
* @param exprs {Expr[]}
|
|
63
|
+
* Suppose we have the following tagged template:
|
|
64
|
+
* `<div title=${expr1} class="big ${expr2} muted ${expr3}">
|
|
65
|
+
* ${expr4}
|
|
66
|
+
* <my-component></my-component>
|
|
67
|
+
* <my-component user=${expr5} roles="${expr6},${expr7}"></my-component>
|
|
68
|
+
* </div>`
|
|
69
|
+
* The exprs arrays will look like this, with each being passed to a path.
|
|
70
|
+
* [expr1] // title attribute value.
|
|
71
|
+
* [expr2, expr3] // class attribute values.
|
|
72
|
+
* [expr4] // children of div.
|
|
73
|
+
* [] // arguments to first my-component constructor.
|
|
74
|
+
* [[expr5], [expr6, expr7]] // arguments to second my-component constructor.
|
|
75
|
+
* [expr5] // user attribute value.
|
|
76
|
+
* [expr6, expr7] // role attribute value. */
|
|
77
|
+
apply(exprs) {}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Fast path used by NodeGroup.applyExprs() when every path consumes exactly one expression.
|
|
81
|
+
* Avoids allocating per-path expression arrays.
|
|
82
|
+
* @param expr {Expr} */
|
|
83
|
+
applySingle(expr) {}
|
|
84
|
+
|
|
85
|
+
getExpressionCount() { return 1 }
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Resolve nodeMarkerPath to new root.
|
|
90
|
+
* TODO: Make clone() use this.*/
|
|
91
|
+
getNewNodeMarker(newRoot, pathOffset) {
|
|
92
|
+
let root = newRoot;
|
|
93
|
+
let path = this.nodeMarkerPath;
|
|
94
|
+
let pathLength = path.length - pathOffset;
|
|
95
|
+
for (let i=pathLength-1; i>0; i--) { // Resolve the path.
|
|
96
|
+
//#IFDEV
|
|
97
|
+
assert(root.childNodes[path[i]]);
|
|
98
|
+
//#ENDIF
|
|
99
|
+
root = root.childNodes[path[i]];
|
|
100
|
+
}
|
|
101
|
+
let childNodes = root.childNodes;
|
|
102
|
+
|
|
103
|
+
return pathLength
|
|
104
|
+
? childNodes[path[0]]
|
|
105
|
+
: newRoot;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Copy this path, pointing it at already-resolved nodes.
|
|
111
|
+
* Used by the Shell resolve-program fast path in NodeGroup.setPathsFromFragment().
|
|
112
|
+
* @param nodeBefore {?Node}
|
|
113
|
+
* @param nodeMarker {Node}
|
|
114
|
+
* @return {Path} */
|
|
115
|
+
cloneWithNodes(nodeBefore, nodeMarker) {
|
|
116
|
+
let result = new this.constructor(nodeBefore, nodeMarker, this.attrName, this.attrValue);
|
|
117
|
+
result.isComponentAttrib = this.isComponentAttrib;
|
|
118
|
+
result.wholeParent = this.wholeParent;
|
|
119
|
+
result.isHtmlProperty = this.isHtmlProperty;
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param newRoot {HTMLElement}
|
|
125
|
+
* @param pathOffset {int}
|
|
126
|
+
* @return {Path} */
|
|
127
|
+
clone(newRoot, pathOffset=0) {
|
|
128
|
+
/*#IFDEV*/this.verify();/*#ENDIF*/
|
|
129
|
+
|
|
130
|
+
// Resolve node paths.
|
|
131
|
+
let nodeMarker, nodeBefore;
|
|
132
|
+
let root = newRoot;
|
|
133
|
+
let path = this.nodeMarkerPath;
|
|
134
|
+
let pathLength = path.length - pathOffset;
|
|
135
|
+
for (let i=pathLength-1; i>0; i--) { // Resolve the path.
|
|
136
|
+
//#IFDEV
|
|
137
|
+
assert(root.childNodes[path[i]]);
|
|
138
|
+
//#ENDIF
|
|
139
|
+
root = root.childNodes[path[i]];
|
|
140
|
+
}
|
|
141
|
+
let childNodes = root.childNodes;
|
|
142
|
+
|
|
143
|
+
nodeMarker = pathLength
|
|
144
|
+
? childNodes[path[0]]
|
|
145
|
+
: newRoot;
|
|
146
|
+
if (this.nodeBefore) {
|
|
147
|
+
//#IFDEV
|
|
148
|
+
assert(childNodes[this.nodeBeforeIndex]);
|
|
149
|
+
//#ENDIF
|
|
150
|
+
nodeBefore = childNodes[this.nodeBeforeIndex];
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let result = new this.constructor(nodeBefore, nodeMarker, this.attrName, this.attrValue);
|
|
155
|
+
|
|
156
|
+
result.isComponentAttrib = this.isComponentAttrib;
|
|
157
|
+
result.wholeParent = this.wholeParent;
|
|
158
|
+
|
|
159
|
+
// TODO: Put this in PathToAttribValue.clone().
|
|
160
|
+
result.isHtmlProperty = this.isHtmlProperty;
|
|
161
|
+
|
|
162
|
+
//#IFDEV
|
|
163
|
+
result.verify();
|
|
164
|
+
//#ENDIF
|
|
165
|
+
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** @return {int[]} Returns indices in reverse order, because doing it that way is faster. */
|
|
170
|
+
static get(node) {
|
|
171
|
+
let result = [];
|
|
172
|
+
while(true) {
|
|
173
|
+
let parent = node.parentNode
|
|
174
|
+
if (!parent)
|
|
175
|
+
break;
|
|
176
|
+
result.push(Array.prototype.indexOf.call(node.parentNode.childNodes, node))
|
|
177
|
+
node = parent;
|
|
178
|
+
}
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Note that the path is backward, with the outermost element at the end.
|
|
184
|
+
* @param root {HTMLElement|Document|DocumentFragment|ParentNode}
|
|
185
|
+
* @param path {int[]}
|
|
186
|
+
* @returns {Node|HTMLElement|HTMLStyleElement} */
|
|
187
|
+
static resolve(root, path) {
|
|
188
|
+
for (let i=path.length-1; i>=0; i--)
|
|
189
|
+
root = root.childNodes[path[i]];
|
|
190
|
+
return root;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
//#IFDEV
|
|
194
|
+
|
|
195
|
+
/** @return {HTMLElement|ParentNode} */
|
|
196
|
+
getParentNode() {
|
|
197
|
+
return this.nodeMarker.parentNode
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
verify() {
|
|
201
|
+
if (!window.verify)
|
|
202
|
+
return;
|
|
203
|
+
|
|
204
|
+
// Need either nodeMarker or parentNode
|
|
205
|
+
assert(this.nodeMarker)
|
|
206
|
+
|
|
207
|
+
// nodeMarker must be attached, unless it's an element that is itself the top of a
|
|
208
|
+
// singleRoot shell clone (no fragment wrapper exists above it).
|
|
209
|
+
assert(!this.nodeMarker || this.nodeMarker.parentNode || this.wholeParent || this.nodeMarker.nodeType === 1)
|
|
210
|
+
|
|
211
|
+
assert(this.nodeBefore !== this.nodeMarker)
|
|
212
|
+
|
|
213
|
+
// Detect cyclic parent and grandparent references.
|
|
214
|
+
assert(this.parentNg?.parentPath !== this)
|
|
215
|
+
assert(this.parentNg?.parentPath?.parentNg?.parentPath !== this)
|
|
216
|
+
assert(this.parentNg?.parentPath?.parentNg?.parentPath?.parentNg?.parentPath !== this)
|
|
217
|
+
|
|
218
|
+
for (let ng of this.nodeGroups || [])
|
|
219
|
+
ng.verify();
|
|
220
|
+
|
|
221
|
+
// Make sure the nodesCache matches the nodes.
|
|
222
|
+
//this.checkNodesCache();
|
|
223
|
+
}
|
|
224
|
+
//#ENDIF
|
|
212
225
|
}
|