@lvce-editor/virtual-dom-worker 1.7.0 → 1.9.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/index.d.ts +7 -0
- package/dist/index.js +208 -0
- package/package.json +1 -1
- package/src/parts/AddPatch/AddPatch.ts +6 -0
- package/src/parts/ApplyPendingPatches/ApplyPendingPatches.ts +22 -0
- package/src/parts/AttributePatch/AttributePatch.ts +0 -1
- package/src/parts/GetKeys/GetKeys.ts +10 -0
- package/src/parts/GetTotalChildCount/GetTotalChildCount.ts +16 -0
- package/src/parts/Main/Main.ts +1 -0
- package/src/parts/NavigateChildPatch/NavigateChildPatch.ts +4 -0
- package/src/parts/NavigateParentPatch/NavigateParentPatch.ts +3 -0
- package/src/parts/NavigateSiblingPatch/NavigateSiblingPatch.ts +4 -0
- package/src/parts/Patch/Patch.ts +13 -1
- package/src/parts/PatchType/PatchType.ts +6 -0
- package/src/parts/RemoveAttributePatch/RemoveAttributePatch.ts +0 -1
- package/src/parts/RemoveChildPatch/RemoveChildPatch.ts +4 -0
- package/src/parts/RemovePatch/RemovePatch.ts +4 -0
- package/src/parts/TextPatch/TextPatch.ts +0 -1
- package/src/parts/VirtualDomDiff/VirtualDomDiff.ts +140 -48
package/dist/index.d.ts
CHANGED
|
@@ -6,3 +6,10 @@ export interface VirtualDomNode {
|
|
|
6
6
|
export const text: (data: string) => VirtualDomNode
|
|
7
7
|
|
|
8
8
|
export const mergeClassNames: (...classNames: readonly string[]) => string
|
|
9
|
+
|
|
10
|
+
export interface Patch {}
|
|
11
|
+
|
|
12
|
+
export const diff: (
|
|
13
|
+
oldNodes: readonly VirtualDomNode[],
|
|
14
|
+
newNodes: readonly VirtualDomNode[],
|
|
15
|
+
) => readonly Patch[]
|
package/dist/index.js
CHANGED
|
@@ -130,8 +130,216 @@ var text = (data) => {
|
|
|
130
130
|
childCount: 0
|
|
131
131
|
};
|
|
132
132
|
};
|
|
133
|
+
|
|
134
|
+
// src/parts/PatchType/PatchType.ts
|
|
135
|
+
var SetText = 1;
|
|
136
|
+
var SetAttribute = 3;
|
|
137
|
+
var RemoveAttribute = 4;
|
|
138
|
+
var Add = 6;
|
|
139
|
+
var NavigateChild = 7;
|
|
140
|
+
var NavigateParent = 8;
|
|
141
|
+
var RemoveChild = 9;
|
|
142
|
+
var NavigateSibling = 10;
|
|
143
|
+
|
|
144
|
+
// src/parts/ApplyPendingPatches/ApplyPendingPatches.ts
|
|
145
|
+
var applyPendingPatches = (patches, pendingPatches, skip) => {
|
|
146
|
+
for (let k = 0; k < pendingPatches.length - skip; k += 2) {
|
|
147
|
+
const type = pendingPatches[k];
|
|
148
|
+
const index = pendingPatches[k + 1];
|
|
149
|
+
if (type === NavigateParent) {
|
|
150
|
+
patches.push({ type });
|
|
151
|
+
} else {
|
|
152
|
+
patches.push({
|
|
153
|
+
type,
|
|
154
|
+
index
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
pendingPatches.length = 0;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// src/parts/GetKeys/GetKeys.ts
|
|
162
|
+
var isKey = (key) => {
|
|
163
|
+
return key !== "type" && key !== "childCount";
|
|
164
|
+
};
|
|
165
|
+
var getKeys = (node) => {
|
|
166
|
+
const keys = Object.keys(node).filter(isKey);
|
|
167
|
+
return keys;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// src/parts/GetTotalChildCount/GetTotalChildCount.ts
|
|
171
|
+
var getTotalChildCount = (nodes, index) => {
|
|
172
|
+
let i = index;
|
|
173
|
+
let pending = 1;
|
|
174
|
+
while (pending) {
|
|
175
|
+
const node = nodes[i];
|
|
176
|
+
pending += node.childCount;
|
|
177
|
+
pending--;
|
|
178
|
+
i++;
|
|
179
|
+
}
|
|
180
|
+
return i - index;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// src/parts/VirtualDomDiff/VirtualDomDiff.ts
|
|
184
|
+
var diff = (oldNodes, newNodes) => {
|
|
185
|
+
const patches = [];
|
|
186
|
+
const pendingPatches = [];
|
|
187
|
+
let i = 0;
|
|
188
|
+
let j = 0;
|
|
189
|
+
let siblingOffset = 0;
|
|
190
|
+
let maxSiblingOffset = 1;
|
|
191
|
+
const indexStack = [0, 1];
|
|
192
|
+
while (i < oldNodes.length && j < newNodes.length) {
|
|
193
|
+
const oldNode = oldNodes[i];
|
|
194
|
+
const newNode = newNodes[j];
|
|
195
|
+
if (siblingOffset > 0) {
|
|
196
|
+
}
|
|
197
|
+
if (siblingOffset === maxSiblingOffset) {
|
|
198
|
+
pendingPatches.push(NavigateParent, 0);
|
|
199
|
+
maxSiblingOffset = indexStack.pop();
|
|
200
|
+
siblingOffset = indexStack.pop() + 1;
|
|
201
|
+
}
|
|
202
|
+
if (oldNode.type !== newNode.type) {
|
|
203
|
+
let skip = 0;
|
|
204
|
+
if (pendingPatches.length > 0 && pendingPatches.at(-2) === NavigateChild) {
|
|
205
|
+
skip = 2;
|
|
206
|
+
}
|
|
207
|
+
applyPendingPatches(patches, pendingPatches, skip);
|
|
208
|
+
const oldTotal = getTotalChildCount(oldNodes, i);
|
|
209
|
+
const newTotal = getTotalChildCount(newNodes, j);
|
|
210
|
+
patches.push({
|
|
211
|
+
type: RemoveChild,
|
|
212
|
+
index: siblingOffset
|
|
213
|
+
});
|
|
214
|
+
patches.push({
|
|
215
|
+
type: Add,
|
|
216
|
+
nodes: newNodes.slice(j, j + newTotal)
|
|
217
|
+
});
|
|
218
|
+
siblingOffset++;
|
|
219
|
+
i += oldTotal;
|
|
220
|
+
j += newTotal;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (oldNode.type === Text && newNode.type === Text) {
|
|
224
|
+
if (oldNode.text !== newNode.text) {
|
|
225
|
+
if (siblingOffset !== 0) {
|
|
226
|
+
pendingPatches.push(NavigateSibling, siblingOffset);
|
|
227
|
+
}
|
|
228
|
+
applyPendingPatches(patches, pendingPatches, 0);
|
|
229
|
+
patches.push({
|
|
230
|
+
type: SetText,
|
|
231
|
+
value: newNode.text
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
i++;
|
|
235
|
+
j++;
|
|
236
|
+
siblingOffset++;
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const oldKeys = getKeys(oldNode);
|
|
240
|
+
const newKeys = getKeys(newNode);
|
|
241
|
+
let hasAttributeChanges = false;
|
|
242
|
+
for (const key of newKeys) {
|
|
243
|
+
if (oldNode[key] !== newNode[key]) {
|
|
244
|
+
hasAttributeChanges = true;
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
for (const key of oldKeys) {
|
|
249
|
+
if (!(key in newNode)) {
|
|
250
|
+
hasAttributeChanges = true;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (hasAttributeChanges) {
|
|
255
|
+
applyPendingPatches(patches, pendingPatches, 0);
|
|
256
|
+
for (const key of newKeys) {
|
|
257
|
+
if (oldNode[key] !== newNode[key]) {
|
|
258
|
+
patches.push({
|
|
259
|
+
type: SetAttribute,
|
|
260
|
+
key,
|
|
261
|
+
value: newNode[key]
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
for (const key of oldKeys) {
|
|
266
|
+
if (!(key in newNode)) {
|
|
267
|
+
patches.push({
|
|
268
|
+
type: RemoveAttribute,
|
|
269
|
+
key
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (oldNode.childCount && newNode.childCount) {
|
|
275
|
+
maxSiblingOffset = oldNode.childCount;
|
|
276
|
+
indexStack.push(0, maxSiblingOffset);
|
|
277
|
+
pendingPatches.push(NavigateChild, 0);
|
|
278
|
+
i++;
|
|
279
|
+
j++;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (oldNode.childCount) {
|
|
283
|
+
applyPendingPatches(patches, pendingPatches, 0);
|
|
284
|
+
for (let k = 0; k < oldNode.childCount; k++) {
|
|
285
|
+
patches.push({
|
|
286
|
+
type: RemoveChild,
|
|
287
|
+
index: 0
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
i += getTotalChildCount(oldNodes, i);
|
|
291
|
+
j++;
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
if (newNode.childCount) {
|
|
295
|
+
applyPendingPatches(patches, pendingPatches, 0);
|
|
296
|
+
const total = getTotalChildCount(newNodes, j);
|
|
297
|
+
patches.push({
|
|
298
|
+
type: Add,
|
|
299
|
+
nodes: newNodes.slice(j + 1, j + total)
|
|
300
|
+
});
|
|
301
|
+
i++;
|
|
302
|
+
j += total;
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
i++;
|
|
306
|
+
j++;
|
|
307
|
+
siblingOffset++;
|
|
308
|
+
}
|
|
309
|
+
while (i < oldNodes.length) {
|
|
310
|
+
if (indexStack.length !== 2) {
|
|
311
|
+
patches.push({
|
|
312
|
+
type: NavigateParent
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
patches.push({
|
|
316
|
+
type: RemoveChild,
|
|
317
|
+
index: siblingOffset
|
|
318
|
+
});
|
|
319
|
+
i += getTotalChildCount(oldNodes, i);
|
|
320
|
+
indexStack.pop();
|
|
321
|
+
indexStack.pop();
|
|
322
|
+
}
|
|
323
|
+
while (j < newNodes.length) {
|
|
324
|
+
if (siblingOffset > 0) {
|
|
325
|
+
patches.push({
|
|
326
|
+
type: NavigateSibling,
|
|
327
|
+
index: siblingOffset
|
|
328
|
+
});
|
|
329
|
+
siblingOffset = 0;
|
|
330
|
+
}
|
|
331
|
+
const count = getTotalChildCount(newNodes, j);
|
|
332
|
+
patches.push({
|
|
333
|
+
type: Add,
|
|
334
|
+
nodes: newNodes.slice(j, j + count)
|
|
335
|
+
});
|
|
336
|
+
j += count;
|
|
337
|
+
}
|
|
338
|
+
return patches;
|
|
339
|
+
};
|
|
133
340
|
export {
|
|
134
341
|
VirtualDomElements_exports as VirtualDomElements,
|
|
342
|
+
diff,
|
|
135
343
|
mergeClassNames,
|
|
136
344
|
text
|
|
137
345
|
};
|
package/package.json
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Patch } from '../Patch/Patch.ts'
|
|
2
|
+
import * as PatchType from '../PatchType/PatchType.ts'
|
|
3
|
+
|
|
4
|
+
export const applyPendingPatches = (
|
|
5
|
+
patches: Patch[],
|
|
6
|
+
pendingPatches: number[],
|
|
7
|
+
skip: number,
|
|
8
|
+
): void => {
|
|
9
|
+
for (let k = 0; k < pendingPatches.length - skip; k += 2) {
|
|
10
|
+
const type = pendingPatches[k]
|
|
11
|
+
const index = pendingPatches[k + 1]
|
|
12
|
+
if (type === PatchType.NavigateParent) {
|
|
13
|
+
patches.push({ type })
|
|
14
|
+
} else {
|
|
15
|
+
patches.push({
|
|
16
|
+
type,
|
|
17
|
+
index,
|
|
18
|
+
} as Patch)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
pendingPatches.length = 0
|
|
22
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { VirtualDomNode } from '../VirtualDomNode/VirtualDomNode.ts'
|
|
2
|
+
|
|
3
|
+
const isKey = (key: string): boolean => {
|
|
4
|
+
return key !== 'type' && key !== 'childCount'
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const getKeys = (node: VirtualDomNode): readonly string[] => {
|
|
8
|
+
const keys = Object.keys(node).filter(isKey)
|
|
9
|
+
return keys
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { VirtualDomNode } from '../VirtualDomNode/VirtualDomNode.ts'
|
|
2
|
+
|
|
3
|
+
export const getTotalChildCount = (
|
|
4
|
+
nodes: readonly VirtualDomNode[],
|
|
5
|
+
index: number,
|
|
6
|
+
): number => {
|
|
7
|
+
let i = index
|
|
8
|
+
let pending = 1
|
|
9
|
+
while (pending) {
|
|
10
|
+
const node = nodes[i]
|
|
11
|
+
pending += node.childCount
|
|
12
|
+
pending--
|
|
13
|
+
i++
|
|
14
|
+
}
|
|
15
|
+
return i - index
|
|
16
|
+
}
|
package/src/parts/Main/Main.ts
CHANGED
package/src/parts/Patch/Patch.ts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
|
+
import type { AddPatch } from '../AddPatch/AddPatch.ts'
|
|
1
2
|
import type { AttributePatch } from '../AttributePatch/AttributePatch.ts'
|
|
3
|
+
import type { NavigateChildPatch } from '../NavigateChildPatch/NavigateChildPatch.ts'
|
|
4
|
+
import type { NavigateParentPatch } from '../NavigateParentPatch/NavigateParentPatch.ts'
|
|
5
|
+
import type { NavigateSiblingPatch } from '../NavigateSiblingPatch/NavigateSiblingPatch.ts'
|
|
6
|
+
import type { RemoveAttributePatch } from '../RemoveAttributePatch/RemoveAttributePatch.ts'
|
|
7
|
+
import type { RemoveChildPatch } from '../RemoveChildPatch/RemoveChildPatch.ts'
|
|
8
|
+
import type { RemovePatch } from '../RemovePatch/RemovePatch.ts'
|
|
2
9
|
import type { ReplacePatch } from '../ReplacePatch/ReplacePatch.ts'
|
|
3
10
|
import type { TextPatch } from '../TextPatch/TextPatch.ts'
|
|
4
|
-
import type { RemoveAttributePatch } from '../RemoveAttributePatch/RemoveAttributePatch.ts'
|
|
5
11
|
|
|
6
12
|
export type Patch =
|
|
7
13
|
| TextPatch
|
|
8
14
|
| AttributePatch
|
|
9
15
|
| ReplacePatch
|
|
10
16
|
| RemoveAttributePatch
|
|
17
|
+
| RemovePatch
|
|
18
|
+
| AddPatch
|
|
19
|
+
| NavigateChildPatch
|
|
20
|
+
| NavigateParentPatch
|
|
21
|
+
| RemoveChildPatch
|
|
22
|
+
| NavigateSiblingPatch
|
|
@@ -2,3 +2,9 @@ export const SetText = 1
|
|
|
2
2
|
export const Replace = 2
|
|
3
3
|
export const SetAttribute = 3
|
|
4
4
|
export const RemoveAttribute = 4
|
|
5
|
+
export const Remove = 5
|
|
6
|
+
export const Add = 6
|
|
7
|
+
export const NavigateChild = 7
|
|
8
|
+
export const NavigateParent = 8
|
|
9
|
+
export const RemoveChild = 9
|
|
10
|
+
export const NavigateSibling = 10
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Patch } from '../Patch/Patch.ts'
|
|
2
2
|
import type { VirtualDomNode } from '../VirtualDomNode/VirtualDomNode.ts'
|
|
3
|
+
import * as ApplyPendingPatches from '../ApplyPendingPatches/ApplyPendingPatches.ts'
|
|
4
|
+
import * as GetKeys from '../GetKeys/GetKeys.ts'
|
|
5
|
+
import * as GetTotalChildCount from '../GetTotalChildCount/GetTotalChildCount.ts'
|
|
3
6
|
import * as PatchType from '../PatchType/PatchType.ts'
|
|
4
7
|
import * as VirtualDomElements from '../VirtualDomElements/VirtualDomElements.ts'
|
|
5
8
|
|
|
@@ -8,88 +11,177 @@ export const diff = (
|
|
|
8
11
|
newNodes: readonly VirtualDomNode[],
|
|
9
12
|
): readonly Patch[] => {
|
|
10
13
|
const patches: Patch[] = []
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
const pendingPatches: number[] = []
|
|
15
|
+
let i = 0
|
|
16
|
+
let j = 0
|
|
17
|
+
let siblingOffset = 0
|
|
18
|
+
let maxSiblingOffset = 1
|
|
19
|
+
const indexStack: number[] = [0, 1]
|
|
20
|
+
while (i < oldNodes.length && j < newNodes.length) {
|
|
14
21
|
const oldNode = oldNodes[i]
|
|
15
|
-
const newNode = newNodes[
|
|
22
|
+
const newNode = newNodes[j]
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
patches.push({
|
|
20
|
-
type: PatchType.Replace,
|
|
21
|
-
index: i,
|
|
22
|
-
// @ts-ignore
|
|
23
|
-
node: undefined,
|
|
24
|
-
})
|
|
25
|
-
continue
|
|
24
|
+
if (siblingOffset > 0) {
|
|
25
|
+
// pendingPatches.push(PatchType.NavigateSibling, siblingOffset)
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
type: PatchType.Replace,
|
|
32
|
-
index: i,
|
|
33
|
-
node: newNode,
|
|
34
|
-
})
|
|
35
|
-
continue
|
|
27
|
+
if (siblingOffset === maxSiblingOffset) {
|
|
28
|
+
pendingPatches.push(PatchType.NavigateParent, 0)
|
|
29
|
+
maxSiblingOffset = indexStack.pop() as number
|
|
30
|
+
siblingOffset = (indexStack.pop() as number) + 1
|
|
36
31
|
}
|
|
37
32
|
|
|
38
|
-
// Different node types - complete replacement
|
|
39
33
|
if (oldNode.type !== newNode.type) {
|
|
34
|
+
let skip = 0
|
|
35
|
+
if (
|
|
36
|
+
pendingPatches.length > 0 &&
|
|
37
|
+
pendingPatches.at(-2) === PatchType.NavigateChild
|
|
38
|
+
) {
|
|
39
|
+
skip = 2
|
|
40
|
+
}
|
|
41
|
+
ApplyPendingPatches.applyPendingPatches(patches, pendingPatches, skip)
|
|
42
|
+
const oldTotal = GetTotalChildCount.getTotalChildCount(oldNodes, i)
|
|
43
|
+
const newTotal = GetTotalChildCount.getTotalChildCount(newNodes, j)
|
|
44
|
+
|
|
45
|
+
patches.push({
|
|
46
|
+
type: PatchType.RemoveChild,
|
|
47
|
+
index: siblingOffset,
|
|
48
|
+
})
|
|
40
49
|
patches.push({
|
|
41
|
-
type: PatchType.
|
|
42
|
-
|
|
43
|
-
node: newNode,
|
|
50
|
+
type: PatchType.Add,
|
|
51
|
+
nodes: newNodes.slice(j, j + newTotal),
|
|
44
52
|
})
|
|
53
|
+
siblingOffset++
|
|
54
|
+
i += oldTotal
|
|
55
|
+
j += newTotal
|
|
45
56
|
continue
|
|
46
57
|
}
|
|
47
58
|
|
|
48
|
-
// Text node changes
|
|
49
59
|
if (
|
|
50
60
|
oldNode.type === VirtualDomElements.Text &&
|
|
51
61
|
newNode.type === VirtualDomElements.Text
|
|
52
62
|
) {
|
|
53
63
|
if (oldNode.text !== newNode.text) {
|
|
64
|
+
if (siblingOffset !== 0) {
|
|
65
|
+
pendingPatches.push(PatchType.NavigateSibling, siblingOffset)
|
|
66
|
+
}
|
|
67
|
+
ApplyPendingPatches.applyPendingPatches(patches, pendingPatches, 0)
|
|
54
68
|
patches.push({
|
|
55
69
|
type: PatchType.SetText,
|
|
56
|
-
index: i,
|
|
57
70
|
value: newNode.text,
|
|
58
71
|
})
|
|
59
72
|
}
|
|
73
|
+
i++
|
|
74
|
+
j++
|
|
75
|
+
siblingOffset++
|
|
60
76
|
continue
|
|
61
77
|
}
|
|
62
78
|
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
)
|
|
67
|
-
const newKeys = Object.keys(newNode).filter(
|
|
68
|
-
(key) => key !== 'type' && key !== 'childCount',
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
// Check for changed or added attributes
|
|
79
|
+
const oldKeys = GetKeys.getKeys(oldNode)
|
|
80
|
+
const newKeys = GetKeys.getKeys(newNode)
|
|
81
|
+
let hasAttributeChanges = false
|
|
72
82
|
for (const key of newKeys) {
|
|
73
83
|
if (oldNode[key] !== newNode[key]) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
index: i,
|
|
77
|
-
key,
|
|
78
|
-
value: newNode[key],
|
|
79
|
-
})
|
|
84
|
+
hasAttributeChanges = true
|
|
85
|
+
break
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
|
-
|
|
83
|
-
// Check for removed attributes
|
|
84
88
|
for (const key of oldKeys) {
|
|
85
89
|
if (!(key in newNode)) {
|
|
90
|
+
hasAttributeChanges = true
|
|
91
|
+
break
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (hasAttributeChanges) {
|
|
96
|
+
ApplyPendingPatches.applyPendingPatches(patches, pendingPatches, 0)
|
|
97
|
+
|
|
98
|
+
for (const key of newKeys) {
|
|
99
|
+
if (oldNode[key] !== newNode[key]) {
|
|
100
|
+
patches.push({
|
|
101
|
+
type: PatchType.SetAttribute,
|
|
102
|
+
key,
|
|
103
|
+
value: newNode[key],
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const key of oldKeys) {
|
|
108
|
+
if (!(key in newNode)) {
|
|
109
|
+
patches.push({
|
|
110
|
+
type: PatchType.RemoveAttribute,
|
|
111
|
+
key,
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (oldNode.childCount && newNode.childCount) {
|
|
118
|
+
maxSiblingOffset = oldNode.childCount
|
|
119
|
+
indexStack.push(0, maxSiblingOffset)
|
|
120
|
+
pendingPatches.push(PatchType.NavigateChild, 0)
|
|
121
|
+
i++
|
|
122
|
+
j++
|
|
123
|
+
continue
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (oldNode.childCount) {
|
|
127
|
+
ApplyPendingPatches.applyPendingPatches(patches, pendingPatches, 0)
|
|
128
|
+
for (let k = 0; k < oldNode.childCount; k++) {
|
|
86
129
|
patches.push({
|
|
87
|
-
type: PatchType.
|
|
88
|
-
index:
|
|
89
|
-
key,
|
|
130
|
+
type: PatchType.RemoveChild,
|
|
131
|
+
index: 0,
|
|
90
132
|
})
|
|
91
133
|
}
|
|
134
|
+
i += GetTotalChildCount.getTotalChildCount(oldNodes, i)
|
|
135
|
+
j++
|
|
136
|
+
continue
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (newNode.childCount) {
|
|
140
|
+
ApplyPendingPatches.applyPendingPatches(patches, pendingPatches, 0)
|
|
141
|
+
const total = GetTotalChildCount.getTotalChildCount(newNodes, j)
|
|
142
|
+
patches.push({
|
|
143
|
+
type: PatchType.Add,
|
|
144
|
+
nodes: newNodes.slice(j + 1, j + total),
|
|
145
|
+
})
|
|
146
|
+
i++
|
|
147
|
+
j += total
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
i++
|
|
152
|
+
j++
|
|
153
|
+
siblingOffset++
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
while (i < oldNodes.length) {
|
|
157
|
+
if (indexStack.length !== 2) {
|
|
158
|
+
patches.push({
|
|
159
|
+
type: PatchType.NavigateParent,
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
patches.push({
|
|
163
|
+
type: PatchType.RemoveChild,
|
|
164
|
+
index: siblingOffset,
|
|
165
|
+
})
|
|
166
|
+
i += GetTotalChildCount.getTotalChildCount(oldNodes, i)
|
|
167
|
+
indexStack.pop()
|
|
168
|
+
indexStack.pop()
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
while (j < newNodes.length) {
|
|
172
|
+
if (siblingOffset > 0) {
|
|
173
|
+
patches.push({
|
|
174
|
+
type: PatchType.NavigateSibling,
|
|
175
|
+
index: siblingOffset,
|
|
176
|
+
})
|
|
177
|
+
siblingOffset = 0
|
|
92
178
|
}
|
|
179
|
+
const count = GetTotalChildCount.getTotalChildCount(newNodes, j)
|
|
180
|
+
patches.push({
|
|
181
|
+
type: PatchType.Add,
|
|
182
|
+
nodes: newNodes.slice(j, j + count),
|
|
183
|
+
})
|
|
184
|
+
j += count
|
|
93
185
|
}
|
|
94
186
|
|
|
95
187
|
return patches
|