solarite 0.3.2 → 0.5.0
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 +2149 -2090
- package/dist/Solarite.js +1895 -1821
- package/dist/Solarite.min.js +2 -2
- package/package.json +12 -2
- package/readme.md +2 -2
- package/src/Globals.js +18 -24
- package/src/HtmlParser.js +1 -1
- package/src/MultiValueMap.js +3 -3
- package/src/NodeGroup.js +238 -483
- package/src/Path.js +212 -0
- package/src/PathToAttribValue.js +259 -0
- package/src/PathToAttribs.js +77 -0
- package/src/PathToComment.js +8 -0
- package/src/PathToComponent.js +169 -0
- package/src/PathToEvent.js +57 -0
- package/src/PathToNodes.js +566 -0
- package/src/RootNodeGroup.js +8 -0
- package/src/Shell.js +92 -83
- package/src/Solarite.d.ts +73 -29
- package/src/Solarite.js +133 -21
- package/src/Template.js +173 -42
- package/src/Util.js +74 -52
- package/src/assert.js +5 -5
- package/src/getArg.js +26 -24
- package/src/h.js +83 -128
- package/src/hash.js +11 -9
- package/src/toEl.js +83 -0
- package/src/udomdiff.js +0 -57
- package/src/watch.js +78 -81
- package/src/ExprPath.js +0 -1109
- package/src/createSolarite.js +0 -154
package/src/h.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Template from "./Template.js";
|
|
2
|
-
import Util from "./Util.js";
|
|
3
2
|
import Globals from "./Globals.js";
|
|
4
|
-
import
|
|
3
|
+
import toEl from "./toEl.js";
|
|
4
|
+
import Util from "./Util.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Convert strings to HTMLNodes.
|
|
@@ -9,175 +9,130 @@ import {assert} from "./assert.js";
|
|
|
9
9
|
* Using h() as a function() will always create a DOM element.
|
|
10
10
|
*
|
|
11
11
|
* Features beyond what standard js tagged template strings do:
|
|
12
|
-
* 1.
|
|
12
|
+
* 1. h`` sub-expressions
|
|
13
13
|
* 2. functions, nodes, and arrays of nodes as sub-expressions.
|
|
14
|
-
* 3. html-escape all expressions by default, unless wrapped in
|
|
14
|
+
* 3. html-escape all expressions by default, unless wrapped in h()
|
|
15
15
|
* 4. event binding
|
|
16
16
|
* 5. TODO: list more
|
|
17
17
|
*
|
|
18
|
+
* General rule:
|
|
19
|
+
* If h() is a function with null or an HTMLElement as its first argument create a Node.
|
|
20
|
+
* Otherwise create a template
|
|
21
|
+
*
|
|
18
22
|
* Currently supported:
|
|
19
|
-
* 1. h(el, options)`<b>${'Hi'}</b>` // Create template and render its nodes to el.
|
|
20
|
-
* 2. h(el, template, ?options) // Render the Template created by #1 to element.
|
|
21
23
|
*
|
|
22
|
-
*
|
|
24
|
+
* Create Tempataes
|
|
25
|
+
* 1. h`<b>Hello</b> ${'World'}!` // Create Template that can later be used to create nodes.
|
|
26
|
+
* 2. h('<b>Hello</b><u>Goodbye</u>'); // Create Template from string, that can later be used to create nodes.
|
|
23
27
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* 7. h()`Hello<b>${'World'}!</b>` // Same as 4-6, but evaluates the string as a Solarite template, which
|
|
28
|
-
* // includes properly handling nested components and r`` sub-expressions.
|
|
29
|
-
* 8. h(template) // Render Template created by #1.
|
|
28
|
+
* Add children to an element.
|
|
29
|
+
* 3. h(el, h`<b>${'Hi'}</b>`, ?options)
|
|
30
|
+
* 4. h(el, ?options)`<b>${'Hi'}</b>` // typical path used in render(). Create template and render its nodes to el.
|
|
30
31
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
32
|
+
* Create top-level element
|
|
33
|
+
* 5. h()`Hello<b>${'World'}!</b>`
|
|
34
|
+
*
|
|
35
|
+
* 6. h(string, object, ...) // Used for JSX
|
|
33
36
|
* @param htmlStrings {?HTMLElement|string|string[]|function():Template|{render:function()}}
|
|
34
37
|
* @param exprs {*[]|string|Template|Object}
|
|
35
|
-
* @return {Node|HTMLElement|Template} */
|
|
38
|
+
* @return {Node|HTMLElement|Template|Function} */
|
|
36
39
|
export default function h(htmlStrings=undefined, ...exprs) {
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (htmlStrings instanceof Node) {
|
|
43
|
-
let parent = htmlStrings, template = exprs[0];
|
|
41
|
+
// 1. Tagged template: h`<div>...</div>`
|
|
42
|
+
if (Array.isArray(arguments[0])) {
|
|
43
|
+
return new Template(arguments[0], exprs);
|
|
44
|
+
}
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
parent.innerHTML = ''; // Remove shadowroot. TODO: This could mess up paths?
|
|
46
|
+
// 2. String to template, or JSX factory form h(tag, props, ...children)
|
|
47
|
+
else if (typeof arguments[0] === 'string' || arguments[0] instanceof String) {
|
|
48
|
+
let tagOrHtml = arguments[0];
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
// 2a. JSX: h("tag", {props}, ...children)
|
|
51
|
+
if (exprs.length && (typeof exprs[0] === 'object' || exprs[0] === null)) {
|
|
52
|
+
let tag = tagOrHtml + '';
|
|
53
|
+
let props = exprs[0] || {};
|
|
54
|
+
let children = exprs.slice(1);
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
let taggedTemplate = (htmlStrings, ...exprs) => {
|
|
54
|
-
Globals.rendered.add(parent)
|
|
55
|
-
let template = new Template(htmlStrings, exprs);
|
|
56
|
-
return template.render(parent, options);
|
|
57
|
-
}
|
|
58
|
-
return taggedTemplate;
|
|
56
|
+
return Template.fromJsx(tag, props, children);
|
|
59
57
|
}
|
|
60
58
|
|
|
61
|
-
//
|
|
62
|
-
else {
|
|
63
|
-
let
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// TODO: Is this ever executed?
|
|
69
|
-
debugger;
|
|
70
|
-
parent.append(this.rootNg.getParentNode());
|
|
71
|
-
}
|
|
59
|
+
// 2b. Plain html string => template: h('<div>...</div>')
|
|
60
|
+
else {
|
|
61
|
+
let html = tagOrHtml;
|
|
62
|
+
// If it starts with whitespace and then a tag, trim it.
|
|
63
|
+
if (html.match(/^\s^</))
|
|
64
|
+
html = html.trim();
|
|
65
|
+
return new Template([html], []);
|
|
72
66
|
}
|
|
73
67
|
}
|
|
74
68
|
|
|
75
|
-
|
|
76
|
-
else if (Array.isArray(htmlStrings)) {
|
|
77
|
-
return new Template(htmlStrings, exprs);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
else if (typeof htmlStrings === 'string' || htmlStrings instanceof String) {
|
|
81
|
-
// 10. JSX
|
|
82
|
-
if (typeof exprs[0] === 'object') {
|
|
83
|
-
let tag = htmlStrings;
|
|
84
|
-
let props = exprs[0] || {};
|
|
85
|
-
let children = exprs.slice(1);
|
|
86
|
-
|
|
87
|
-
let templateHtmlStrings = [];
|
|
88
|
-
let templateExprs = [];
|
|
69
|
+
else if (arguments[0] instanceof HTMLElement || arguments[0] instanceof DocumentFragment) {
|
|
89
70
|
|
|
90
|
-
|
|
91
|
-
|
|
71
|
+
// 3. Render template to element: h(el, template)
|
|
72
|
+
if (arguments[1] instanceof Template) {
|
|
92
73
|
|
|
93
|
-
|
|
94
|
-
|
|
74
|
+
/** @type Template */
|
|
75
|
+
let template = arguments[1];
|
|
76
|
+
let parent = arguments[0];
|
|
77
|
+
let options = arguments[2];
|
|
78
|
+
template.render(parent, options);
|
|
95
79
|
}
|
|
96
80
|
|
|
81
|
+
// 4. Render tagged template to element: h(el)`<div>...</div>`
|
|
82
|
+
else {
|
|
83
|
+
let parent = arguments[0], options = arguments[1];
|
|
97
84
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
htmlStrings = htmlStrings.trim();
|
|
102
|
-
|
|
103
|
-
// We create a new one each time because otherwise
|
|
104
|
-
// the returned fragment will have its content replaced by a subsequent call.
|
|
105
|
-
let templateEl = document.createElement('template');
|
|
106
|
-
templateEl.innerHTML = htmlStrings;
|
|
107
|
-
|
|
108
|
-
// 4+5. Return Node if there's one child.
|
|
109
|
-
let relevantNodes = Util.trimEmptyNodes(templateEl.content.childNodes);
|
|
110
|
-
if (relevantNodes.length === 1)
|
|
111
|
-
return relevantNodes[0];
|
|
85
|
+
// Remove shadowroot if present. TODO: This could mess up paths?
|
|
86
|
+
if (parent.shadowRoot)
|
|
87
|
+
parent.innerHTML = '';
|
|
112
88
|
|
|
113
|
-
|
|
114
|
-
|
|
89
|
+
// Return a tagged template function that applies the tagged template to parent.
|
|
90
|
+
let renderTemplate = (htmlStrings, ...exprs) => {
|
|
91
|
+
Globals.rendered.add(parent)
|
|
92
|
+
let template = new Template(htmlStrings, exprs);
|
|
93
|
+
return template.render(parent, options);
|
|
94
|
+
}
|
|
95
|
+
return renderTemplate;
|
|
96
|
+
}
|
|
115
97
|
}
|
|
116
98
|
|
|
117
|
-
//
|
|
118
|
-
else if (
|
|
99
|
+
// 5. Create a static element: h()`<div></div>`
|
|
100
|
+
else if (!arguments.length) {
|
|
119
101
|
return (htmlStrings, ...exprs) => {
|
|
120
|
-
//Globals.rendered.add(parent)
|
|
121
102
|
let template = h(htmlStrings, ...exprs);
|
|
122
|
-
return template
|
|
103
|
+
return toEl(template);
|
|
123
104
|
}
|
|
124
105
|
}
|
|
125
106
|
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
return htmlStrings.render();
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// 9. Create dynamic element with render() function.
|
|
107
|
+
// 6. Help toEl() with objects: h(this)`<div>...</div>` inside an object's render()
|
|
108
|
+
// Intercepts the main h(this)`...` function call inside render().
|
|
133
109
|
// TODO: This path doesn't handle embeds like data-id="..."
|
|
134
|
-
else if (typeof
|
|
135
|
-
let obj =
|
|
110
|
+
else if (typeof arguments[0] === 'object' && Globals.objToEl.has(arguments[0])) {
|
|
111
|
+
let obj = arguments[0];
|
|
136
112
|
|
|
137
|
-
if (obj.constructor.name !== 'Object')
|
|
113
|
+
if (obj.constructor.name !== 'Object')
|
|
138
114
|
throw new Error(`Solarate Web Component class ${obj.constructor?.name} must extend HTMLElement.`);
|
|
139
115
|
|
|
116
|
+
// Jsx with h(this, <jsx>)
|
|
117
|
+
if (arguments[1] instanceof Template) {
|
|
118
|
+
let template = arguments[1];
|
|
119
|
+
let el = template.render();
|
|
120
|
+
Globals.objToEl.set(obj, el);
|
|
121
|
+
}
|
|
140
122
|
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
if (Globals.objToEl.has(obj)) {
|
|
123
|
+
// h(this)`<div>...</div>`
|
|
124
|
+
else
|
|
144
125
|
return function(...args) {
|
|
145
|
-
|
|
146
|
-
|
|
126
|
+
let template = h(...args);
|
|
127
|
+
let el = template.render();
|
|
147
128
|
Globals.objToEl.set(obj, el);
|
|
148
129
|
}.bind(obj);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Normal path
|
|
152
|
-
else {
|
|
153
|
-
Globals.objToEl.set(obj, null);
|
|
154
|
-
obj[renderF](); // Calls the Special rebound render path above, when the render function calls r(this)
|
|
155
|
-
let el = Globals.objToEl.get(obj);
|
|
156
|
-
Globals.objToEl.delete(obj);
|
|
157
|
-
|
|
158
|
-
for (let name in obj)
|
|
159
|
-
if (typeof obj[name] === 'function')
|
|
160
|
-
el[name] = obj[name].bind(el); // Make the "this" of functions be el.
|
|
161
|
-
// TODO: But this doesn't work for passing an object with functions as a constructor arg via an attribute:
|
|
162
|
-
// <my-element arg=${{myFunc() { return this }}}
|
|
163
|
-
else
|
|
164
|
-
el[name] = obj[name];
|
|
165
|
-
|
|
166
|
-
// Bind id's
|
|
167
|
-
// This doesn't work for id's referenced by attributes.
|
|
168
|
-
// for (let idEl of el.querySelectorAll('[id],[data-id]')) {
|
|
169
|
-
// Util.bindId(el, idEl);
|
|
170
|
-
// Util.bindId(obj, idEl);
|
|
171
|
-
// }
|
|
172
|
-
// TODO: Bind styles
|
|
173
|
-
|
|
174
|
-
return el;
|
|
175
|
-
}
|
|
176
130
|
}
|
|
131
|
+
// TODO: Handle other primitive types?
|
|
132
|
+
else if (Util.isFalsy(arguments[0]))
|
|
133
|
+
return new Template();
|
|
177
134
|
|
|
178
135
|
else
|
|
179
|
-
throw new Error('
|
|
136
|
+
throw new Error('h() does not support argument of type: ' + (arguments[0] ? typeof arguments[0] : arguments[0]))
|
|
180
137
|
}
|
|
181
138
|
|
|
182
|
-
// Trick to prevent minifier from renaming this function.
|
|
183
|
-
let renderF = 'render';
|
package/src/hash.js
CHANGED
|
@@ -9,8 +9,8 @@ export function getObjectId(obj) {
|
|
|
9
9
|
// return obj.toString(); // This fails to detect when a function's bound variables changes.
|
|
10
10
|
|
|
11
11
|
let result = objectIds.get(obj);
|
|
12
|
-
if (
|
|
13
|
-
result = '
|
|
12
|
+
if (result===undefined) { // convert to string, store in result, then add 1 to lastObjectId.
|
|
13
|
+
result = '~@' + (lastObjectId++); // We use a unique, 2-byte prefix to ensure it doesn't collide w/ strings not from getObjectId()
|
|
14
14
|
objectIds.set(obj, result)
|
|
15
15
|
}
|
|
16
16
|
return result;
|
|
@@ -20,7 +20,8 @@ export function getObjectId(obj) {
|
|
|
20
20
|
* Control how JSON.stringify() handles Nodes and Functions.
|
|
21
21
|
* Normally, we'd pass a replacer() function argument to JSON.stringify() to handle Nodes and Functions.
|
|
22
22
|
* But that makes JSON.stringify() take twice as long to run.
|
|
23
|
-
* Adding a toJSON method globally on these object prototypes doesn't incur that performance penalty.
|
|
23
|
+
* Adding a toJSON method globally on these object prototypes doesn't incur that performance penalty.
|
|
24
|
+
* TODO: This needs to be benchmarked again after the json rewrite in Chrome 138. */
|
|
24
25
|
let isHashing = true;
|
|
25
26
|
function toJSON() {
|
|
26
27
|
return isHashing ? getObjectId(this) : this
|
|
@@ -48,26 +49,27 @@ export function getObjectHash(obj) {
|
|
|
48
49
|
// Sometimes these get unassigned by Chrome and Brave 119, as well as Firefox, seemingly randomly!
|
|
49
50
|
// The same tests sometimes pass, sometimes fail, even after browser and OS restarts.
|
|
50
51
|
// So we check the assignments on every run of getObjectHash()
|
|
52
|
+
// TODO: Cache references to Node.prototype and Function.prototype:
|
|
51
53
|
if (Node.prototype.toJSON !== toJSON) {
|
|
52
54
|
Node.prototype.toJSON = toJSON;
|
|
53
55
|
if (Function.prototype.toJSON !== toJSON) // Will it only unmap one but not the other?
|
|
54
56
|
Function.prototype.toJSON = toJSON;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
let result;
|
|
58
59
|
isHashing = true;
|
|
59
60
|
try {
|
|
60
|
-
|
|
61
|
+
return JSON.stringify(obj);
|
|
61
62
|
}
|
|
62
63
|
catch(e) {
|
|
63
|
-
|
|
64
|
+
return getObjectHashCircular(obj);
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
isHashing = false;
|
|
64
68
|
}
|
|
65
|
-
isHashing = false;
|
|
66
|
-
return result;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
/**
|
|
70
|
-
* Slower hashing method that supports.
|
|
72
|
+
* Slower hashing method that supports circular references.
|
|
71
73
|
* @param obj
|
|
72
74
|
* @returns {string} */
|
|
73
75
|
function getObjectHashCircular(obj) {
|
package/src/toEl.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import Globals from "./Globals.js";
|
|
2
|
+
import Template from "./Template.js";
|
|
3
|
+
import Util from "./Util.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Convert a template, string, or object into a DOM Node or Element
|
|
7
|
+
*
|
|
8
|
+
* 1. toEl('Hello'); // Create single text node.
|
|
9
|
+
* 2. toEl('<b>Hello</b>'); // Create single HTMLElement
|
|
10
|
+
* 3. toEl('<b>Hello</b><u>Goodbye</u>'); // Create document fragment because there's more than one node.
|
|
11
|
+
* 4. toEl(template) // Render Template created by h`<html>` or h();
|
|
12
|
+
* 5. toEl({render(){...}}) // Pass an object with a render method, and optionally other props/methods.
|
|
13
|
+
* @param arg {string|Template|{render:()=>void}}
|
|
14
|
+
* @returns {Node|DocumentFragment|HTMLElement} */
|
|
15
|
+
export default function toEl(arg) {
|
|
16
|
+
|
|
17
|
+
if (typeof arg === 'string') {
|
|
18
|
+
let html = arg;
|
|
19
|
+
|
|
20
|
+
// If it's an element with whitespace before or after it, trim both ends.
|
|
21
|
+
if (html.match(/^\s^<\S+/) || html.match(/\S+>\s+$/))
|
|
22
|
+
html = html.trim();
|
|
23
|
+
|
|
24
|
+
// We create a new one each time because otherwise
|
|
25
|
+
// the returned fragment will have its content replaced by a subsequent call.
|
|
26
|
+
let templateEl = Globals.doc.createElement('template');
|
|
27
|
+
templateEl.innerHTML = html;
|
|
28
|
+
|
|
29
|
+
// 1+2. Return Node if there's one child.
|
|
30
|
+
let relevantNodes = Util.trimEmptyNodes(templateEl.content.childNodes);
|
|
31
|
+
if (relevantNodes.length === 1)
|
|
32
|
+
return relevantNodes[0];
|
|
33
|
+
|
|
34
|
+
// 3. Otherwise return DocumentFragment.
|
|
35
|
+
return templateEl.content;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 4.
|
|
39
|
+
if (arg instanceof Template) {
|
|
40
|
+
return arg.render();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 5. Create dynamic element from an object with a render() function.
|
|
44
|
+
// TODO: This path doesn't handle embeds like data-id="..."
|
|
45
|
+
else if (arg && typeof arg === 'object') {
|
|
46
|
+
let obj = arg;
|
|
47
|
+
|
|
48
|
+
if (obj.constructor.name !== 'Object')
|
|
49
|
+
throw new Error(`Solarate Web Component class ${obj.constructor?.name} must extend HTMLElement.`);
|
|
50
|
+
|
|
51
|
+
// Normal path
|
|
52
|
+
if (!Globals.objToEl.has(obj)) {
|
|
53
|
+
Globals.objToEl.set(obj, null);
|
|
54
|
+
obj[renderF](); // Calls the Special rebound render path above, when the render function calls h(this)
|
|
55
|
+
let el = Globals.objToEl.get(obj);
|
|
56
|
+
Globals.objToEl.delete(obj);
|
|
57
|
+
|
|
58
|
+
for (let name in obj)
|
|
59
|
+
if (typeof obj[name] === 'function')
|
|
60
|
+
el[name] = obj[name].bind(el); // Make the "this" of functions be el.
|
|
61
|
+
// TODO: But this doesn't work for passing an object with functions as a constructor arg via an attribute:
|
|
62
|
+
// <my-element arg=${{myFunc() { return this }}}
|
|
63
|
+
else
|
|
64
|
+
el[name] = obj[name];
|
|
65
|
+
|
|
66
|
+
// Bind id's
|
|
67
|
+
// This doesn't work for id's referenced by attributes.
|
|
68
|
+
// for (let idEl of el.querySelectorAll('[id],[data-id]')) {
|
|
69
|
+
// Util.bindId(el, idEl);
|
|
70
|
+
// Util.bindId(obj, idEl);
|
|
71
|
+
// }
|
|
72
|
+
// TODO: Bind styles
|
|
73
|
+
|
|
74
|
+
return el;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
throw new Error('toEl() does not support argument of type: ' + (arg ? typeof arg : arg));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
// Trick to prevent minifier from renaming this function.
|
|
83
|
+
let renderF = 'render';
|
package/src/udomdiff.js
CHANGED
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import NodeGroup from "./NodeGroup.js";
|
|
20
|
-
|
|
21
19
|
/**
|
|
22
20
|
* @param {Node} parentNode The container where children live
|
|
23
21
|
* @param {Node[]} a The list of current/live children
|
|
@@ -28,11 +26,6 @@ import NodeGroup from "./NodeGroup.js";
|
|
|
28
26
|
* @returns {Node[]} The same list of future children.
|
|
29
27
|
*/
|
|
30
28
|
const udomdiff = (parentNode, a, b, before) => {
|
|
31
|
-
//#IFDEV
|
|
32
|
-
// if (parentNode instanceof ExprPath)
|
|
33
|
-
// parentNode.verify();
|
|
34
|
-
//#ENDIF
|
|
35
|
-
|
|
36
29
|
const bLength = b.length;
|
|
37
30
|
let aEnd = a.length;
|
|
38
31
|
let bEnd = bLength;
|
|
@@ -54,13 +47,6 @@ const udomdiff = (parentNode, a, b, before) => {
|
|
|
54
47
|
while (bStart < bEnd) {
|
|
55
48
|
let bNode = b[bStart++];
|
|
56
49
|
parentNode.insertBefore(bNode, node);
|
|
57
|
-
|
|
58
|
-
//#IFDEV
|
|
59
|
-
if (bNode instanceof NodeGroup)
|
|
60
|
-
bNode.verify();
|
|
61
|
-
// if (parentNode instanceof ExprPath)
|
|
62
|
-
// parentNode.verify();
|
|
63
|
-
//#ENDIF
|
|
64
50
|
}
|
|
65
51
|
}
|
|
66
52
|
// remove head or tail: fast path
|
|
@@ -70,13 +56,6 @@ const udomdiff = (parentNode, a, b, before) => {
|
|
|
70
56
|
let aNode = a[aStart];
|
|
71
57
|
if (!map || !map.has(aNode)) {
|
|
72
58
|
parentNode.removeChild(aNode);
|
|
73
|
-
|
|
74
|
-
//#IFDEV
|
|
75
|
-
if (aNode instanceof NodeGroup)
|
|
76
|
-
aNode.verify();
|
|
77
|
-
// if (parentNode instanceof ExprPath)
|
|
78
|
-
// parentNode.verify();
|
|
79
|
-
//#ENDIF
|
|
80
59
|
}
|
|
81
60
|
aStart++;
|
|
82
61
|
}
|
|
@@ -113,24 +92,10 @@ const udomdiff = (parentNode, a, b, before) => {
|
|
|
113
92
|
a2,
|
|
114
93
|
b2.nextSibling
|
|
115
94
|
);
|
|
116
|
-
//#IFDEV
|
|
117
|
-
if (a2 instanceof NodeGroup)
|
|
118
|
-
a2.verify();
|
|
119
|
-
// if (parentNode instanceof ExprPath)
|
|
120
|
-
// parentNode.verify();
|
|
121
|
-
//#ENDIF
|
|
122
95
|
|
|
123
96
|
let bNode = b[--bEnd];
|
|
124
97
|
parentNode.insertBefore(bNode, node);
|
|
125
98
|
|
|
126
|
-
//#IFDEV
|
|
127
|
-
if (bNode instanceof NodeGroup)
|
|
128
|
-
bNode.verify();
|
|
129
|
-
// if (parentNode instanceof ExprPath)
|
|
130
|
-
// parentNode.verify();
|
|
131
|
-
|
|
132
|
-
//#ENDIF
|
|
133
|
-
|
|
134
99
|
// mark the future index as identical (yeah, it's dirty, but cheap 👍)
|
|
135
100
|
// The main reason to do this, is that when a[aEnd] will be reached,
|
|
136
101
|
// the loop will likely be on the fast path, as identical to b[bEnd].
|
|
@@ -178,14 +143,6 @@ const udomdiff = (parentNode, a, b, before) => {
|
|
|
178
143
|
while (bStart < index) {
|
|
179
144
|
let bNode = b[bStart++];
|
|
180
145
|
parentNode.insertBefore(bNode, node);
|
|
181
|
-
|
|
182
|
-
//#IFDEV
|
|
183
|
-
if (bNode instanceof NodeGroup)
|
|
184
|
-
bNode.verify();
|
|
185
|
-
// if (parentNode instanceof ExprPath)
|
|
186
|
-
// parentNode.verify();
|
|
187
|
-
|
|
188
|
-
//#ENDIF
|
|
189
146
|
}
|
|
190
147
|
}
|
|
191
148
|
// if the effort wasn't good enough, fallback to a replace,
|
|
@@ -198,13 +155,6 @@ const udomdiff = (parentNode, a, b, before) => {
|
|
|
198
155
|
bNode,
|
|
199
156
|
aNode
|
|
200
157
|
);
|
|
201
|
-
|
|
202
|
-
//#IFDEV
|
|
203
|
-
if (aNode instanceof NodeGroup)
|
|
204
|
-
aNode.verify();
|
|
205
|
-
// if (parentNode instanceof ExprPath)
|
|
206
|
-
// parentNode.verify();
|
|
207
|
-
//#ENDIF
|
|
208
158
|
}
|
|
209
159
|
}
|
|
210
160
|
// otherwise move the source forward, 'cause there's nothing to do
|
|
@@ -217,13 +167,6 @@ const udomdiff = (parentNode, a, b, before) => {
|
|
|
217
167
|
else {
|
|
218
168
|
let aNode = a[aStart++];
|
|
219
169
|
parentNode.removeChild(aNode);
|
|
220
|
-
|
|
221
|
-
//#IFDEV
|
|
222
|
-
if (aNode instanceof NodeGroup)
|
|
223
|
-
aNode.verify();
|
|
224
|
-
// if (parentNode instanceof ExprPath)
|
|
225
|
-
// parentNode.verify();
|
|
226
|
-
//#ENDIF
|
|
227
170
|
}
|
|
228
171
|
}
|
|
229
172
|
}
|