ripple 0.4.2 → 0.4.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/CHANGELOG.md +107 -0
- package/package.json +9 -3
- package/src/jsx-runtime.d.ts +2 -1
- package/src/runtime/array.js +15 -9
- package/src/runtime/index-client.js +25 -7
- package/src/runtime/index-server.js +1 -0
- package/src/runtime/internal/client/attributes.js +313 -0
- package/src/runtime/internal/client/blocks.js +4 -14
- package/src/runtime/internal/client/component.js +2 -5
- package/src/runtime/internal/client/composite.js +14 -6
- package/src/runtime/internal/client/constants.js +6 -6
- package/src/runtime/internal/client/context.js +3 -2
- package/src/runtime/internal/client/css.js +11 -26
- package/src/runtime/internal/client/errors.js +188 -0
- package/src/runtime/internal/client/events.js +79 -34
- package/src/runtime/internal/client/expression.js +21 -116
- package/src/runtime/internal/client/for.js +108 -232
- package/src/runtime/internal/client/head.js +4 -3
- package/src/runtime/internal/client/html.js +5 -3
- package/src/runtime/internal/client/hydrate.js +484 -0
- package/src/runtime/internal/client/hydration-enabled.js +7 -0
- package/src/runtime/internal/client/hydration.js +16 -81
- package/src/runtime/internal/client/if.js +13 -9
- package/src/runtime/internal/client/index.js +14 -6
- package/src/runtime/internal/client/operations.js +11 -7
- package/src/runtime/internal/client/portal.js +3 -2
- package/src/runtime/internal/client/render.js +42 -325
- package/src/runtime/internal/client/root-boundary-enabled.js +7 -0
- package/src/runtime/internal/client/runtime.js +87 -363
- package/src/runtime/internal/client/template-ns.js +47 -0
- package/src/runtime/internal/client/template.js +63 -140
- package/src/runtime/internal/client/track-async.js +356 -0
- package/src/runtime/internal/client/try.js +133 -319
- package/src/runtime/internal/client/types.d.ts +48 -24
- package/src/runtime/internal/server/index.js +31 -29
- package/src/runtime/internal/server/prerender.js +27 -0
- package/src/server/index.js +1 -0
- package/src/utils/class-name.js +28 -0
- package/tests/client/basic/basic.errors.test.tsrx +3 -3
- package/tests/client/compiler/__snapshots__/compiler.typescript.test.tsrx.snap +0 -2
- package/tests/client/compiler/compiler.basic.test.tsrx +2 -2
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +3 -3
- package/tests/client/composite/composite.props.test.tsrx +10 -10
- package/tests/client/derived-release.test.tsrx +3 -3
- package/tests/client/for-item.test.tsrx +39 -0
- package/tests/client/for-selector.test.tsrx +95 -0
- package/tests/hydration/compiled/client/basic.js +87 -87
- package/tests/hydration/compiled/client/composite.js +5 -5
- package/tests/hydration/compiled/client/events.js +40 -48
- package/tests/hydration/compiled/client/for.js +162 -181
- package/tests/hydration/compiled/client/fragment-cursor.js +521 -289
- package/tests/hydration/compiled/client/head.js +22 -22
- package/tests/hydration/compiled/client/hmr.js +4 -4
- package/tests/hydration/compiled/client/html-in-template.js +5 -5
- package/tests/hydration/compiled/client/html.js +152 -162
- package/tests/hydration/compiled/client/if-children.js +58 -53
- package/tests/hydration/compiled/client/if-fragment-controlflow.js +39 -39
- package/tests/hydration/compiled/client/if.js +26 -26
- package/tests/hydration/compiled/client/mixed-control-flow.js +56 -68
- package/tests/hydration/compiled/client/nested-control-flow.js +139 -271
- package/tests/hydration/compiled/client/portal.js +10 -10
- package/tests/hydration/compiled/client/reactivity.js +29 -29
- package/tests/hydration/compiled/client/return.js +2 -2
- package/tests/hydration/compiled/client/streaming.js +33 -35
- package/tests/hydration/compiled/client/switch.js +25 -25
- package/tests/hydration/compiled/client/track-async-serialization.js +41 -41
- package/tests/hydration/compiled/client/try.js +15 -15
- package/tests/hydration/compiled/client/typed-text.js +7 -7
- package/tests/hydration/compiled/server/basic.js +6 -6
- package/tests/hydration/compiled/server/events.js +8 -8
- package/tests/hydration/compiled/server/for.js +22 -22
- package/tests/hydration/compiled/server/fragment-cursor.js +188 -52
- package/tests/hydration/compiled/server/head.js +6 -6
- package/tests/hydration/compiled/server/hmr.js +1 -1
- package/tests/hydration/compiled/server/html.js +1 -1
- package/tests/hydration/compiled/server/if-children.js +9 -9
- package/tests/hydration/compiled/server/if.js +5 -5
- package/tests/hydration/compiled/server/mixed-control-flow.js +4 -4
- package/tests/hydration/compiled/server/portal.js +1 -1
- package/tests/hydration/compiled/server/reactivity.js +9 -9
- package/tests/hydration/compiled/server/streaming.js +9 -9
- package/tests/hydration/compiled/server/switch.js +4 -4
- package/tests/hydration/compiled/server/track-async-serialization.js +16 -16
- package/tests/hydration/compiled/server/try.js +4 -4
- package/tests/hydration/compiled/server/typed-text.js +1 -1
- package/tests/hydration/components/fragment-cursor.tsrx +60 -0
- package/tests/hydration/components/track-async-serialization.tsrx +2 -2
- package/tests/hydration/fragment-cursor.test.js +34 -1
- package/tests/hydration/track-async-serialization.test.js +1 -1
- package/tests/server/basic.components.test.tsrx +3 -3
- package/tests/server/track-async-serialization.test.tsrx +6 -6
- package/tests/utils/tracked-types.test.js +3 -3
- package/types/index.d.ts +8 -8
- package/types/server.d.ts +17 -0
|
@@ -25,31 +25,36 @@ import { get_last_child, next_sibling, resolve_anchor } from './operations.js';
|
|
|
25
25
|
import { append } from './template.js';
|
|
26
26
|
import { active_block, run_block, run_branch, set, set_tracking, tracked } from './runtime.js';
|
|
27
27
|
import { array_from, is_array } from '@tsrx/core/runtime/language-helpers';
|
|
28
|
+
import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* @template V
|
|
31
32
|
* @param {Node | AppendIntoAnchor} anchor
|
|
32
33
|
* @param {V} value
|
|
33
34
|
* @param {number} index
|
|
34
|
-
* @param {
|
|
35
|
-
* @param {
|
|
36
|
-
* @param {boolean} is_keyed
|
|
37
|
-
* @param {((item: V) => any) | undefined} [map_item] a keyed loop's destructuring of the item (see `for_block_keyed`)
|
|
35
|
+
* @param {any} key the key the item was matched by (keyed lists)
|
|
36
|
+
* @param {ListState} state the list's state: how items render
|
|
38
37
|
* @returns {Block}
|
|
39
38
|
*/
|
|
40
|
-
function create_item(anchor, value, index,
|
|
39
|
+
function create_item(anchor, value, index, key, state) {
|
|
41
40
|
var block = /** @type {Block} */ (active_block);
|
|
42
|
-
var
|
|
43
|
-
var
|
|
41
|
+
var render_fn = state.r;
|
|
42
|
+
var map_item = state.m;
|
|
43
|
+
var tracked_index = state.x ? tracked(index, block) : undefined;
|
|
44
|
+
var tracked_value = state.y
|
|
44
45
|
? tracked(map_item === undefined ? value : map_item(value), block)
|
|
45
46
|
: value;
|
|
46
|
-
var
|
|
47
|
+
var item_state = {
|
|
47
48
|
start: null,
|
|
48
49
|
end: null,
|
|
49
50
|
i: tracked_index,
|
|
50
51
|
v: tracked_value,
|
|
51
52
|
// The item as the collection holds it; a keyed diff compares against it.
|
|
52
53
|
r: value,
|
|
54
|
+
// The key the item was matched by: fixed for the block's whole life, so
|
|
55
|
+
// the body reads it as a plain value (a compiled `@if (outer === item.key)`
|
|
56
|
+
// depends on the selector alone, not on the item).
|
|
57
|
+
k: key,
|
|
53
58
|
// The render state of a body that carries its render block on the item
|
|
54
59
|
// block itself (see `item`), or null.
|
|
55
60
|
p: null,
|
|
@@ -59,8 +64,8 @@ function create_item(anchor, value, index, render_fn, is_indexed, is_keyed, map_
|
|
|
59
64
|
// renders in place: allocated, linked and run through `run_branch`, with
|
|
60
65
|
// none of the first-run bookkeeping a block that may re-run needs.
|
|
61
66
|
if (tracked_value === value && tracked_index === undefined) {
|
|
62
|
-
var lean = allocate_block(BRANCH_BLOCK, run_item,
|
|
63
|
-
run_branch(lean, render_fn, anchor, value);
|
|
67
|
+
var lean = allocate_block(BRANCH_BLOCK, run_item, item_state);
|
|
68
|
+
run_branch(lean, render_fn, anchor, value, key);
|
|
64
69
|
lean.f ^= BLOCK_HAS_RUN;
|
|
65
70
|
return lean;
|
|
66
71
|
}
|
|
@@ -69,18 +74,35 @@ function create_item(anchor, value, index, render_fn, is_indexed, is_keyed, map_
|
|
|
69
74
|
// reads them before rendering, so nested loops cannot observe a stale pair.
|
|
70
75
|
item_anchor = anchor;
|
|
71
76
|
item_render_fn = render_fn;
|
|
72
|
-
var b = create_block(BRANCH_BLOCK, run_item,
|
|
77
|
+
var b = create_block(BRANCH_BLOCK, run_item, item_state);
|
|
73
78
|
|
|
74
79
|
// The item's tracked value and index are owned by the item block itself.
|
|
75
|
-
if (
|
|
80
|
+
if (tracked_value !== value) {
|
|
76
81
|
/** @type {Tracked} */ (tracked_value).b = b;
|
|
77
82
|
}
|
|
78
|
-
if (
|
|
83
|
+
if (tracked_index !== undefined) {
|
|
79
84
|
/** @type {Tracked} */ (tracked_index).b = b;
|
|
80
85
|
}
|
|
81
86
|
return b;
|
|
82
87
|
}
|
|
83
88
|
|
|
89
|
+
/**
|
|
90
|
+
* A matched item at its new index: its tracked index and, for a computed key,
|
|
91
|
+
* its tracked value follow the collection.
|
|
92
|
+
* @param {ListState} state
|
|
93
|
+
* @param {Block} block
|
|
94
|
+
* @param {any} value
|
|
95
|
+
* @param {number} index
|
|
96
|
+
*/
|
|
97
|
+
function patch_item(state, block, value, index) {
|
|
98
|
+
if (state.x) {
|
|
99
|
+
update_index(block, index);
|
|
100
|
+
}
|
|
101
|
+
if (state.k !== undefined) {
|
|
102
|
+
update_value(block, value, state.m, state.l);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
84
106
|
/**
|
|
85
107
|
* The insertion point of a list: a node the items go before, or, for a
|
|
86
108
|
* controlled list (the sole content of its parent), an append-into sentinel so
|
|
@@ -93,16 +115,16 @@ function create_item(anchor, value, index, render_fn, is_indexed, is_keyed, map_
|
|
|
93
115
|
* @returns {AppendIntoAnchor}
|
|
94
116
|
*/
|
|
95
117
|
function controlled_anchor(parent) {
|
|
96
|
-
return { parent, into: true };
|
|
118
|
+
return { parent, into: true, tail: false };
|
|
97
119
|
}
|
|
98
120
|
|
|
99
121
|
/** @type {Node | AppendIntoAnchor | null} */
|
|
100
122
|
var item_anchor = null;
|
|
101
|
-
/** @type {((anchor: Node, value: any, index?: any) => Block) | null} */
|
|
123
|
+
/** @type {((anchor: Node, value: any, index?: any, key?: any) => Block) | null} */
|
|
102
124
|
var item_render_fn = null;
|
|
103
125
|
|
|
104
126
|
/**
|
|
105
|
-
* @param {{ i: Tracked | undefined, v: any, p: any }} state
|
|
127
|
+
* @param {{ i: Tracked | undefined, v: any, k: any, p: any }} state
|
|
106
128
|
*/
|
|
107
129
|
function run_item(state) {
|
|
108
130
|
var p = state.p;
|
|
@@ -115,11 +137,13 @@ function run_item(state) {
|
|
|
115
137
|
)(p);
|
|
116
138
|
return;
|
|
117
139
|
}
|
|
118
|
-
var render_fn = /** @type {(anchor: Node, value: any, index?: any) => Block} */ (
|
|
140
|
+
var render_fn = /** @type {(anchor: Node, value: any, index?: any, key?: any) => Block} */ (
|
|
141
|
+
item_render_fn
|
|
142
|
+
);
|
|
119
143
|
var anchor = /** @type {Node} */ (item_anchor);
|
|
120
144
|
item_render_fn = null;
|
|
121
145
|
item_anchor = null;
|
|
122
|
-
render_fn(anchor, state.v, state.i);
|
|
146
|
+
render_fn(anchor, state.v, state.i, state.k);
|
|
123
147
|
}
|
|
124
148
|
|
|
125
149
|
/**
|
|
@@ -292,6 +316,7 @@ class ListState {
|
|
|
292
316
|
* @param {((prev: any) => void) | undefined} update_fn the update function
|
|
293
317
|
* of an item body that carries its render block (see `item`)
|
|
294
318
|
* @param {boolean} is_local items are held as they are (`LOCAL_ITEMS`)
|
|
319
|
+
* @param {boolean} is_keyed each item holds a tracked of its value
|
|
295
320
|
*/
|
|
296
321
|
constructor(
|
|
297
322
|
anchor,
|
|
@@ -304,6 +329,7 @@ class ListState {
|
|
|
304
329
|
map_item,
|
|
305
330
|
update_fn,
|
|
306
331
|
is_local,
|
|
332
|
+
is_keyed,
|
|
307
333
|
) {
|
|
308
334
|
this.a = anchor;
|
|
309
335
|
this.g = get_collection;
|
|
@@ -315,6 +341,7 @@ class ListState {
|
|
|
315
341
|
this.m = map_item;
|
|
316
342
|
this.u = update_fn;
|
|
317
343
|
this.l = is_local;
|
|
344
|
+
this.y = is_keyed;
|
|
318
345
|
}
|
|
319
346
|
}
|
|
320
347
|
|
|
@@ -327,13 +354,13 @@ function run_for(state) {
|
|
|
327
354
|
|
|
328
355
|
// Items render untracked, as in a branch; the list tracks only its collection.
|
|
329
356
|
set_tracking(false);
|
|
330
|
-
reconcile_by_ref(state.a, block, array
|
|
357
|
+
reconcile_by_ref(state.a, block, array);
|
|
331
358
|
set_tracking(true);
|
|
332
359
|
|
|
333
360
|
// Re-anchor a hydrated list: the hydrated anchor is the block's start
|
|
334
361
|
// marker; later inserts and end moves must go before the cursor, which now
|
|
335
362
|
// sits after the hydrated items.
|
|
336
|
-
if (hydrating) {
|
|
363
|
+
if (HYDRATION && hydrating) {
|
|
337
364
|
state.a = /** @type {Element | Text} */ (hydrate_node);
|
|
338
365
|
}
|
|
339
366
|
}
|
|
@@ -346,21 +373,10 @@ function run_for_keyed(state) {
|
|
|
346
373
|
var array = collection_to_array(state.g());
|
|
347
374
|
|
|
348
375
|
set_tracking(false);
|
|
349
|
-
reconcile_by_key(
|
|
350
|
-
state.a,
|
|
351
|
-
block,
|
|
352
|
-
array,
|
|
353
|
-
state.r,
|
|
354
|
-
state.c,
|
|
355
|
-
state.x,
|
|
356
|
-
state.k,
|
|
357
|
-
state.e,
|
|
358
|
-
state.m,
|
|
359
|
-
state.l,
|
|
360
|
-
);
|
|
376
|
+
reconcile_by_key(state.a, block, array);
|
|
361
377
|
set_tracking(true);
|
|
362
378
|
|
|
363
|
-
if (hydrating) {
|
|
379
|
+
if (HYDRATION && hydrating) {
|
|
364
380
|
state.a = /** @type {Element | Text} */ (hydrate_node);
|
|
365
381
|
}
|
|
366
382
|
}
|
|
@@ -387,7 +403,7 @@ export function for_block(node, get_collection, render_fn, flags, render_empty,
|
|
|
387
403
|
var boundary;
|
|
388
404
|
|
|
389
405
|
if (is_controlled) {
|
|
390
|
-
if (hydrating) {
|
|
406
|
+
if (HYDRATION && hydrating) {
|
|
391
407
|
// The cursor sits on the list's element; the items are its children.
|
|
392
408
|
hydrate_first_child();
|
|
393
409
|
} else {
|
|
@@ -395,7 +411,7 @@ export function for_block(node, get_collection, render_fn, flags, render_empty,
|
|
|
395
411
|
}
|
|
396
412
|
}
|
|
397
413
|
|
|
398
|
-
if (hydrating) {
|
|
414
|
+
if (HYDRATION && hydrating) {
|
|
399
415
|
if (root_controlled) {
|
|
400
416
|
boundary = /** @type {Node} */ (hydrate_node);
|
|
401
417
|
}
|
|
@@ -415,13 +431,14 @@ export function for_block(node, get_collection, render_fn, flags, render_empty,
|
|
|
415
431
|
undefined,
|
|
416
432
|
update_fn,
|
|
417
433
|
false,
|
|
434
|
+
false,
|
|
418
435
|
),
|
|
419
436
|
FOR_BLOCK,
|
|
420
437
|
);
|
|
421
438
|
|
|
422
439
|
if (!is_controlled) own_anchor(node, /** @type {Node} */ (anchor));
|
|
423
440
|
|
|
424
|
-
if (hydrating && root_controlled) {
|
|
441
|
+
if (HYDRATION && hydrating && root_controlled) {
|
|
425
442
|
// The original `node`: for a sentinel, `hydrate_append` performs the
|
|
426
443
|
// cursor advance that stands in for the eliminated sibling navigation.
|
|
427
444
|
append(/** @type {ChildNode} */ (node), /** @type {Node} */ (boundary));
|
|
@@ -464,7 +481,7 @@ export function for_block_keyed(
|
|
|
464
481
|
if (is_controlled) {
|
|
465
482
|
var parent_node = /** @type {Element} */ (node);
|
|
466
483
|
|
|
467
|
-
if (hydrating) {
|
|
484
|
+
if (HYDRATION && hydrating) {
|
|
468
485
|
hydrate_first_child();
|
|
469
486
|
anchor = /** @type {Element | Text} */ (get_last_child(parent_node));
|
|
470
487
|
} else {
|
|
@@ -472,7 +489,7 @@ export function for_block_keyed(
|
|
|
472
489
|
}
|
|
473
490
|
}
|
|
474
491
|
|
|
475
|
-
if (hydrating) {
|
|
492
|
+
if (HYDRATION && hydrating) {
|
|
476
493
|
if (root_controlled) {
|
|
477
494
|
boundary = /** @type {Node} */ (hydrate_node);
|
|
478
495
|
}
|
|
@@ -492,13 +509,14 @@ export function for_block_keyed(
|
|
|
492
509
|
map_item,
|
|
493
510
|
update_fn,
|
|
494
511
|
(flags & LOCAL_ITEMS) !== 0,
|
|
512
|
+
(flags & LOCAL_ITEMS) === 0,
|
|
495
513
|
),
|
|
496
514
|
FOR_BLOCK,
|
|
497
515
|
);
|
|
498
516
|
|
|
499
517
|
if (!is_controlled) own_anchor(node, /** @type {Node} */ (anchor));
|
|
500
518
|
|
|
501
|
-
if (hydrating && root_controlled) {
|
|
519
|
+
if (HYDRATION && hydrating && root_controlled) {
|
|
502
520
|
// The original `node`: for a sentinel, `hydrate_append` performs the
|
|
503
521
|
// cursor advance that stands in for the eliminated sibling navigation.
|
|
504
522
|
append(/** @type {ChildNode} */ (node), /** @type {Node} */ (boundary));
|
|
@@ -561,36 +579,18 @@ function update_value(block, value, map_item, is_local) {
|
|
|
561
579
|
|
|
562
580
|
/**
|
|
563
581
|
* @template V
|
|
564
|
-
* @template K
|
|
565
582
|
* @param {ListAnchor} anchor
|
|
566
583
|
* @param {Block} block
|
|
567
584
|
* @param {V[]} b
|
|
568
|
-
* @param {(anchor: Node, value: V | Tracked, index?: any) => Block} render_fn
|
|
569
|
-
* @param {boolean} is_controlled
|
|
570
|
-
* @param {boolean} is_indexed
|
|
571
|
-
* @param {((item: V) => K) | undefined} get_key identity keys when omitted
|
|
572
|
-
* @param {((anchor: Node) => void) | undefined} render_empty
|
|
573
|
-
* @param {((item: V) => any) | undefined} map_item
|
|
574
|
-
* @param {boolean} is_local items are held as they are (`LOCAL_ITEMS`)
|
|
575
585
|
* @returns {void}
|
|
576
586
|
*
|
|
577
587
|
* The first run only creates items, so it lives in this small function and
|
|
578
588
|
* the diff below is compiled only once a list actually changes.
|
|
579
589
|
*/
|
|
580
|
-
function reconcile_by_key(
|
|
581
|
-
anchor,
|
|
582
|
-
block,
|
|
583
|
-
b,
|
|
584
|
-
render_fn,
|
|
585
|
-
is_controlled,
|
|
586
|
-
is_indexed,
|
|
587
|
-
get_key,
|
|
588
|
-
render_empty,
|
|
589
|
-
map_item,
|
|
590
|
-
is_local,
|
|
591
|
-
) {
|
|
590
|
+
function reconcile_by_key(anchor, block, b) {
|
|
592
591
|
var b_length = b.length;
|
|
593
592
|
var state = /** @type {ListState} */ (block.s);
|
|
593
|
+
var get_key = state.k;
|
|
594
594
|
|
|
595
595
|
if (state.keys === null && b_length > 0) {
|
|
596
596
|
var b_blocks = Array(b_length);
|
|
@@ -604,7 +604,7 @@ function reconcile_by_key(
|
|
|
604
604
|
if (get_key !== undefined) {
|
|
605
605
|
b_keys[j] = get_key(value);
|
|
606
606
|
}
|
|
607
|
-
b_blocks[j] = create_item(anchor, value, j,
|
|
607
|
+
b_blocks[j] = create_item(anchor, value, j, b_keys[j], state);
|
|
608
608
|
}
|
|
609
609
|
|
|
610
610
|
state.array = b;
|
|
@@ -613,50 +613,24 @@ function reconcile_by_key(
|
|
|
613
613
|
return;
|
|
614
614
|
}
|
|
615
615
|
|
|
616
|
-
reconcile_by_key_diff(
|
|
617
|
-
anchor,
|
|
618
|
-
block,
|
|
619
|
-
b,
|
|
620
|
-
render_fn,
|
|
621
|
-
is_controlled,
|
|
622
|
-
is_indexed,
|
|
623
|
-
get_key,
|
|
624
|
-
render_empty,
|
|
625
|
-
map_item,
|
|
626
|
-
is_local,
|
|
627
|
-
);
|
|
616
|
+
reconcile_by_key_diff(anchor, block, b);
|
|
628
617
|
}
|
|
629
618
|
|
|
630
619
|
/**
|
|
631
620
|
* Keyed diff for every run after the first (or a first run with an empty
|
|
632
621
|
* list). See {@link reconcile_by_key}.
|
|
633
|
-
* @template V
|
|
622
|
+
* @template V
|
|
634
623
|
* @param {ListAnchor} anchor
|
|
635
624
|
* @param {Block} block
|
|
636
625
|
* @param {V[]} b
|
|
637
|
-
* @param {(anchor: Node, value: V | Tracked, index?: any) => Block} render_fn
|
|
638
|
-
* @param {boolean} is_controlled
|
|
639
|
-
* @param {boolean} is_indexed
|
|
640
|
-
* @param {((item: V) => K) | undefined} get_key
|
|
641
|
-
* @param {((anchor: Node) => void) | undefined} render_empty
|
|
642
|
-
* @param {((item: V) => any) | undefined} map_item
|
|
643
|
-
* @param {boolean} is_local items are held as they are (`LOCAL_ITEMS`)
|
|
644
626
|
* @returns {void}
|
|
645
627
|
*/
|
|
646
|
-
function reconcile_by_key_diff(
|
|
647
|
-
anchor,
|
|
648
|
-
block,
|
|
649
|
-
b,
|
|
650
|
-
render_fn,
|
|
651
|
-
is_controlled,
|
|
652
|
-
is_indexed,
|
|
653
|
-
get_key,
|
|
654
|
-
render_empty,
|
|
655
|
-
map_item,
|
|
656
|
-
is_local,
|
|
657
|
-
) {
|
|
658
|
-
var is_keyed = !is_local;
|
|
628
|
+
function reconcile_by_key_diff(anchor, block, b) {
|
|
659
629
|
var state = /** @type {ListState} */ (block.s);
|
|
630
|
+
var is_controlled = state.c;
|
|
631
|
+
var is_indexed = state.x;
|
|
632
|
+
var get_key = state.k;
|
|
633
|
+
var render_empty = state.e;
|
|
660
634
|
|
|
661
635
|
// Variables used in conditional branches - declare with initial values
|
|
662
636
|
/** @type {number} */
|
|
@@ -723,7 +697,7 @@ function reconcile_by_key_diff(
|
|
|
723
697
|
// Fast-path for create
|
|
724
698
|
if (a_length === 0) {
|
|
725
699
|
for (; j < b_length; j++) {
|
|
726
|
-
b_blocks[j] = create_item(anchor, b[j], j,
|
|
700
|
+
b_blocks[j] = create_item(anchor, b[j], j, b_keys[j], state);
|
|
727
701
|
}
|
|
728
702
|
state.array = b;
|
|
729
703
|
state.blocks = b_blocks;
|
|
@@ -765,27 +739,15 @@ function reconcile_by_key_diff(
|
|
|
765
739
|
// moves; only what is left afterwards needs the map and LIS below.
|
|
766
740
|
while (a_start <= a_end && b_start <= b_end) {
|
|
767
741
|
if (a_keys[a_start] === b_keys[b_start]) {
|
|
768
|
-
b_val = b[b_start];
|
|
769
742
|
b_block = b_blocks[b_start] = a_blocks[a_start];
|
|
770
|
-
|
|
771
|
-
update_index(b_block, b_start);
|
|
772
|
-
}
|
|
773
|
-
if (get_key !== undefined) {
|
|
774
|
-
update_value(b_block, b_val, map_item, is_local);
|
|
775
|
-
}
|
|
743
|
+
patch_item(state, b_block, b[b_start], b_start);
|
|
776
744
|
a_start++;
|
|
777
745
|
b_start++;
|
|
778
746
|
continue;
|
|
779
747
|
}
|
|
780
748
|
if (a_keys[a_end] === b_keys[b_end]) {
|
|
781
|
-
b_val = b[b_end];
|
|
782
749
|
b_block = b_blocks[b_end] = a_blocks[a_end];
|
|
783
|
-
|
|
784
|
-
update_index(b_block, b_end);
|
|
785
|
-
}
|
|
786
|
-
if (get_key !== undefined) {
|
|
787
|
-
update_value(b_block, b_val, map_item, is_local);
|
|
788
|
-
}
|
|
750
|
+
patch_item(state, b_block, b[b_end], b_end);
|
|
789
751
|
a_end--;
|
|
790
752
|
b_end--;
|
|
791
753
|
continue;
|
|
@@ -800,14 +762,8 @@ function reconcile_by_key_diff(
|
|
|
800
762
|
}
|
|
801
763
|
if (a_keys[a_end] === b_keys[b_start]) {
|
|
802
764
|
// Last old item is the next new one: move it in front of the old run.
|
|
803
|
-
b_val = b[b_start];
|
|
804
765
|
b_block = b_blocks[b_start] = a_blocks[a_end];
|
|
805
|
-
|
|
806
|
-
update_index(b_block, b_start);
|
|
807
|
-
}
|
|
808
|
-
if (get_key !== undefined) {
|
|
809
|
-
update_value(b_block, b_val, map_item, is_local);
|
|
810
|
-
}
|
|
766
|
+
patch_item(state, b_block, b[b_start], b_start);
|
|
811
767
|
move(b_block, /** @type {ChildNode} */ (a_blocks[a_start].s.start));
|
|
812
768
|
a_end--;
|
|
813
769
|
b_start++;
|
|
@@ -815,14 +771,8 @@ function reconcile_by_key_diff(
|
|
|
815
771
|
}
|
|
816
772
|
if (a_keys[a_start] === b_keys[b_end]) {
|
|
817
773
|
// First old item is the last new one: move it behind the old run.
|
|
818
|
-
b_val = b[b_end];
|
|
819
774
|
b_block = b_blocks[b_end] = a_blocks[a_start];
|
|
820
|
-
|
|
821
|
-
update_index(b_block, b_end);
|
|
822
|
-
}
|
|
823
|
-
if (get_key !== undefined) {
|
|
824
|
-
update_value(b_block, b_val, map_item, is_local);
|
|
825
|
-
}
|
|
775
|
+
patch_item(state, b_block, b[b_end], b_end);
|
|
826
776
|
move(b_block, block_start(b_blocks, b_end + 1, b_length, anchor));
|
|
827
777
|
a_start++;
|
|
828
778
|
b_end--;
|
|
@@ -837,15 +787,7 @@ function reconcile_by_key_diff(
|
|
|
837
787
|
if (b_start <= b_end) {
|
|
838
788
|
var target_node = block_start(b_blocks, b_end + 1, b_length, anchor);
|
|
839
789
|
while (b_start <= b_end) {
|
|
840
|
-
b_blocks[b_start] = create_item(
|
|
841
|
-
target_node,
|
|
842
|
-
b[b_start],
|
|
843
|
-
b_start,
|
|
844
|
-
render_fn,
|
|
845
|
-
is_indexed,
|
|
846
|
-
is_keyed,
|
|
847
|
-
map_item,
|
|
848
|
-
);
|
|
790
|
+
b_blocks[b_start] = create_item(target_node, b[b_start], b_start, b_keys[b_start], state);
|
|
849
791
|
b_start++;
|
|
850
792
|
}
|
|
851
793
|
}
|
|
@@ -886,14 +828,8 @@ function reconcile_by_key_diff(
|
|
|
886
828
|
} else {
|
|
887
829
|
pos = j;
|
|
888
830
|
}
|
|
889
|
-
b_val = b[j];
|
|
890
831
|
b_block = b_blocks[j] = a_blocks[i];
|
|
891
|
-
|
|
892
|
-
update_index(b_block, j);
|
|
893
|
-
}
|
|
894
|
-
if (get_key !== undefined) {
|
|
895
|
-
update_value(b_block, b_val, map_item, is_local);
|
|
896
|
-
}
|
|
832
|
+
patch_item(state, b_block, b[j], j);
|
|
897
833
|
++patched;
|
|
898
834
|
break;
|
|
899
835
|
}
|
|
@@ -929,14 +865,8 @@ function reconcile_by_key_diff(
|
|
|
929
865
|
} else {
|
|
930
866
|
pos = j;
|
|
931
867
|
}
|
|
932
|
-
b_val = b[j];
|
|
933
868
|
b_block = b_blocks[j] = a_blocks[i];
|
|
934
|
-
|
|
935
|
-
update_index(b_block, j);
|
|
936
|
-
}
|
|
937
|
-
if (get_key !== undefined) {
|
|
938
|
-
update_value(b_block, b_val, map_item, is_local);
|
|
939
|
-
}
|
|
869
|
+
patch_item(state, b_block, b[j], j);
|
|
940
870
|
++patched;
|
|
941
871
|
} else if (!fast_path_removal) {
|
|
942
872
|
destroy_block(a_blocks[i]);
|
|
@@ -950,18 +880,7 @@ function reconcile_by_key_diff(
|
|
|
950
880
|
|
|
951
881
|
if (fast_path_removal) {
|
|
952
882
|
reconcile_fast_clear(anchor, block, []);
|
|
953
|
-
reconcile_by_key(
|
|
954
|
-
anchor,
|
|
955
|
-
block,
|
|
956
|
-
b,
|
|
957
|
-
render_fn,
|
|
958
|
-
is_controlled,
|
|
959
|
-
is_indexed,
|
|
960
|
-
get_key,
|
|
961
|
-
render_empty,
|
|
962
|
-
map_item,
|
|
963
|
-
is_local,
|
|
964
|
-
);
|
|
883
|
+
reconcile_by_key(anchor, block, b);
|
|
965
884
|
return;
|
|
966
885
|
} else if (moved) {
|
|
967
886
|
var next_pos = 0;
|
|
@@ -971,21 +890,7 @@ function reconcile_by_key_diff(
|
|
|
971
890
|
// When most surviving items have to move anyway, re-lay the whole range
|
|
972
891
|
// in order (see `relay`).
|
|
973
892
|
if ((patched - seq.length) * 3 > b_left * 2) {
|
|
974
|
-
relay(
|
|
975
|
-
anchor,
|
|
976
|
-
a_blocks,
|
|
977
|
-
a_start,
|
|
978
|
-
a_end,
|
|
979
|
-
b,
|
|
980
|
-
b_blocks,
|
|
981
|
-
b_start,
|
|
982
|
-
b_end,
|
|
983
|
-
sources,
|
|
984
|
-
render_fn,
|
|
985
|
-
is_indexed,
|
|
986
|
-
is_keyed,
|
|
987
|
-
map_item,
|
|
988
|
-
);
|
|
893
|
+
relay(anchor, a_blocks, a_start, a_end, b, b_blocks, b_start, b_end, sources, b_keys, state);
|
|
989
894
|
state.array = b;
|
|
990
895
|
state.blocks = b_blocks;
|
|
991
896
|
state.keys = b_keys;
|
|
@@ -999,7 +904,7 @@ function reconcile_by_key_diff(
|
|
|
999
904
|
next_pos = pos + 1;
|
|
1000
905
|
|
|
1001
906
|
var target = block_start(b_blocks, next_pos, b_length, anchor);
|
|
1002
|
-
b_blocks[pos] = create_item(target, b_val, pos,
|
|
907
|
+
b_blocks[pos] = create_item(target, b_val, pos, b_keys[pos], state);
|
|
1003
908
|
} else if (j < 0 || i !== seq[j]) {
|
|
1004
909
|
pos = i + b_start;
|
|
1005
910
|
next_pos = pos + 1;
|
|
@@ -1018,7 +923,7 @@ function reconcile_by_key_diff(
|
|
|
1018
923
|
next_pos = pos + 1;
|
|
1019
924
|
|
|
1020
925
|
var target = block_start(b_blocks, next_pos, b_length, anchor);
|
|
1021
|
-
b_blocks[pos] = create_item(target, b_val, pos,
|
|
926
|
+
b_blocks[pos] = create_item(target, b_val, pos, b_keys[pos], state);
|
|
1022
927
|
}
|
|
1023
928
|
}
|
|
1024
929
|
}
|
|
@@ -1047,10 +952,8 @@ function reconcile_by_key_diff(
|
|
|
1047
952
|
* @param {number} b_start
|
|
1048
953
|
* @param {number} b_end
|
|
1049
954
|
* @param {Int32Array} sources zero at the index of a new item
|
|
1050
|
-
* @param {
|
|
1051
|
-
* @param {
|
|
1052
|
-
* @param {boolean} is_keyed
|
|
1053
|
-
* @param {((item: V) => any) | undefined} map_item
|
|
955
|
+
* @param {any[] | undefined} b_keys the new items' keys (a keyed list)
|
|
956
|
+
* @param {ListState} state
|
|
1054
957
|
*/
|
|
1055
958
|
function relay(
|
|
1056
959
|
anchor,
|
|
@@ -1062,10 +965,8 @@ function relay(
|
|
|
1062
965
|
b_start,
|
|
1063
966
|
b_end,
|
|
1064
967
|
sources,
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
is_keyed,
|
|
1068
|
-
map_item,
|
|
968
|
+
b_keys,
|
|
969
|
+
state,
|
|
1069
970
|
) {
|
|
1070
971
|
var b_length = b.length;
|
|
1071
972
|
var end_target = block_start(b_blocks, b_end + 1, b_length, anchor);
|
|
@@ -1085,7 +986,13 @@ function relay(
|
|
|
1085
986
|
|
|
1086
987
|
for (var pos = b_start; pos <= b_end; pos++) {
|
|
1087
988
|
if (sources[pos - b_start] === 0) {
|
|
1088
|
-
b_blocks[pos] = create_item(
|
|
989
|
+
b_blocks[pos] = create_item(
|
|
990
|
+
cursor,
|
|
991
|
+
b[pos],
|
|
992
|
+
pos,
|
|
993
|
+
b_keys === undefined ? undefined : b_keys[pos],
|
|
994
|
+
state,
|
|
995
|
+
);
|
|
1089
996
|
continue;
|
|
1090
997
|
}
|
|
1091
998
|
var block = b_blocks[pos];
|
|
@@ -1108,14 +1015,12 @@ function relay(
|
|
|
1108
1015
|
* @param {ListAnchor} anchor
|
|
1109
1016
|
* @param {Block} block
|
|
1110
1017
|
* @param {V[]} b
|
|
1111
|
-
* @param {(anchor: Node, value: V | Tracked, index?: any) => Block} render_fn
|
|
1112
|
-
* @param {boolean} is_controlled
|
|
1113
|
-
* @param {boolean} is_indexed
|
|
1114
|
-
* @param {(anchor: Node) => void} [render_empty]
|
|
1115
1018
|
* @returns {void}
|
|
1116
1019
|
*/
|
|
1117
|
-
function reconcile_by_ref(anchor, block, b
|
|
1020
|
+
function reconcile_by_ref(anchor, block, b) {
|
|
1118
1021
|
var state = /** @type {ListState} */ (block.s);
|
|
1022
|
+
var is_controlled = state.c;
|
|
1023
|
+
var render_empty = state.e;
|
|
1119
1024
|
var a_length = state.array.length;
|
|
1120
1025
|
var b_length = b.length;
|
|
1121
1026
|
var j = 0;
|
|
@@ -1155,14 +1060,14 @@ function reconcile_by_ref(anchor, block, b, render_fn, is_controlled, is_indexed
|
|
|
1155
1060
|
// Fast-path for create
|
|
1156
1061
|
if (a_length === 0) {
|
|
1157
1062
|
for (; j < b_length; j++) {
|
|
1158
|
-
b_blocks[j] = create_item(anchor, b[j], j,
|
|
1063
|
+
b_blocks[j] = create_item(anchor, b[j], j, undefined, state);
|
|
1159
1064
|
}
|
|
1160
1065
|
state.array = b;
|
|
1161
1066
|
state.blocks = b_blocks;
|
|
1162
1067
|
return;
|
|
1163
1068
|
}
|
|
1164
1069
|
|
|
1165
|
-
reconcile_by_ref_diff(anchor, block, b, b_blocks
|
|
1070
|
+
reconcile_by_ref_diff(anchor, block, b, b_blocks);
|
|
1166
1071
|
}
|
|
1167
1072
|
|
|
1168
1073
|
/**
|
|
@@ -1173,13 +1078,11 @@ function reconcile_by_ref(anchor, block, b, render_fn, is_controlled, is_indexed
|
|
|
1173
1078
|
* @param {Block} block
|
|
1174
1079
|
* @param {V[]} b
|
|
1175
1080
|
* @param {Block[]} b_blocks
|
|
1176
|
-
* @param {(anchor: Node, value: V | Tracked, index?: any) => Block} render_fn
|
|
1177
|
-
* @param {boolean} is_controlled
|
|
1178
|
-
* @param {boolean} is_indexed
|
|
1179
1081
|
* @returns {void}
|
|
1180
1082
|
*/
|
|
1181
|
-
function reconcile_by_ref_diff(anchor, block, b, b_blocks
|
|
1083
|
+
function reconcile_by_ref_diff(anchor, block, b, b_blocks) {
|
|
1182
1084
|
var state = /** @type {ListState} */ (block.s);
|
|
1085
|
+
var is_controlled = state.c;
|
|
1183
1086
|
|
|
1184
1087
|
// Variables used in conditional branches - declare with initial values
|
|
1185
1088
|
/** @type {number} */
|
|
@@ -1215,21 +1118,15 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1215
1118
|
// moves; only what is left afterwards needs the map and LIS below.
|
|
1216
1119
|
while (a_start <= a_end && b_start <= b_end) {
|
|
1217
1120
|
if (a[a_start] === b[b_start]) {
|
|
1218
|
-
b_val = b[b_start];
|
|
1219
1121
|
b_block = b_blocks[b_start] = a_blocks[a_start];
|
|
1220
|
-
|
|
1221
|
-
update_index(b_block, b_start);
|
|
1222
|
-
}
|
|
1122
|
+
patch_item(state, b_block, b[b_start], b_start);
|
|
1223
1123
|
a_start++;
|
|
1224
1124
|
b_start++;
|
|
1225
1125
|
continue;
|
|
1226
1126
|
}
|
|
1227
1127
|
if (a[a_end] === b[b_end]) {
|
|
1228
|
-
b_val = b[b_end];
|
|
1229
1128
|
b_block = b_blocks[b_end] = a_blocks[a_end];
|
|
1230
|
-
|
|
1231
|
-
update_index(b_block, b_end);
|
|
1232
|
-
}
|
|
1129
|
+
patch_item(state, b_block, b[b_end], b_end);
|
|
1233
1130
|
a_end--;
|
|
1234
1131
|
b_end--;
|
|
1235
1132
|
continue;
|
|
@@ -1239,11 +1136,8 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1239
1136
|
}
|
|
1240
1137
|
if (a[a_end] === b[b_start]) {
|
|
1241
1138
|
// Last old item is the next new one: move it in front of the old run.
|
|
1242
|
-
b_val = b[b_start];
|
|
1243
1139
|
b_block = b_blocks[b_start] = a_blocks[a_end];
|
|
1244
|
-
|
|
1245
|
-
update_index(b_block, b_start);
|
|
1246
|
-
}
|
|
1140
|
+
patch_item(state, b_block, b[b_start], b_start);
|
|
1247
1141
|
move(b_block, /** @type {ChildNode} */ (a_blocks[a_start].s.start));
|
|
1248
1142
|
a_end--;
|
|
1249
1143
|
b_start++;
|
|
@@ -1251,11 +1145,8 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1251
1145
|
}
|
|
1252
1146
|
if (a[a_start] === b[b_end]) {
|
|
1253
1147
|
// First old item is the last new one: move it behind the old run.
|
|
1254
|
-
b_val = b[b_end];
|
|
1255
1148
|
b_block = b_blocks[b_end] = a_blocks[a_start];
|
|
1256
|
-
|
|
1257
|
-
update_index(b_block, b_end);
|
|
1258
|
-
}
|
|
1149
|
+
patch_item(state, b_block, b[b_end], b_end);
|
|
1259
1150
|
move(b_block, block_start(b_blocks, b_end + 1, b_length, anchor));
|
|
1260
1151
|
a_start++;
|
|
1261
1152
|
b_end--;
|
|
@@ -1270,14 +1161,7 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1270
1161
|
if (b_start <= b_end) {
|
|
1271
1162
|
var target_node = block_start(b_blocks, b_end + 1, b_length, anchor);
|
|
1272
1163
|
while (b_start <= b_end) {
|
|
1273
|
-
b_blocks[b_start] = create_item(
|
|
1274
|
-
target_node,
|
|
1275
|
-
b[b_start],
|
|
1276
|
-
b_start,
|
|
1277
|
-
render_fn,
|
|
1278
|
-
is_indexed,
|
|
1279
|
-
false,
|
|
1280
|
-
);
|
|
1164
|
+
b_blocks[b_start] = create_item(target_node, b[b_start], b_start, undefined, state);
|
|
1281
1165
|
b_start++;
|
|
1282
1166
|
}
|
|
1283
1167
|
}
|
|
@@ -1314,11 +1198,8 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1314
1198
|
} else {
|
|
1315
1199
|
pos = j;
|
|
1316
1200
|
}
|
|
1317
|
-
b_val = b[j];
|
|
1318
1201
|
b_block = b_blocks[j] = a_blocks[i];
|
|
1319
|
-
|
|
1320
|
-
update_index(b_block, j);
|
|
1321
|
-
}
|
|
1202
|
+
patch_item(state, b_block, b[j], j);
|
|
1322
1203
|
++patched;
|
|
1323
1204
|
break;
|
|
1324
1205
|
}
|
|
@@ -1354,11 +1235,8 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1354
1235
|
} else {
|
|
1355
1236
|
pos = j;
|
|
1356
1237
|
}
|
|
1357
|
-
b_val = b[j];
|
|
1358
1238
|
b_block = b_blocks[j] = a_blocks[i];
|
|
1359
|
-
|
|
1360
|
-
update_index(b_block, j);
|
|
1361
|
-
}
|
|
1239
|
+
patch_item(state, b_block, b[j], j);
|
|
1362
1240
|
++patched;
|
|
1363
1241
|
} else if (!fast_path_removal) {
|
|
1364
1242
|
destroy_block(a_blocks[i]);
|
|
@@ -1372,7 +1250,7 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1372
1250
|
|
|
1373
1251
|
if (fast_path_removal) {
|
|
1374
1252
|
reconcile_fast_clear(anchor, block, []);
|
|
1375
|
-
reconcile_by_ref(anchor, block, b
|
|
1253
|
+
reconcile_by_ref(anchor, block, b);
|
|
1376
1254
|
return;
|
|
1377
1255
|
} else if (moved) {
|
|
1378
1256
|
var next_pos = 0;
|
|
@@ -1392,10 +1270,8 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1392
1270
|
b_start,
|
|
1393
1271
|
b_end,
|
|
1394
1272
|
sources,
|
|
1395
|
-
render_fn,
|
|
1396
|
-
is_indexed,
|
|
1397
|
-
false,
|
|
1398
1273
|
undefined,
|
|
1274
|
+
state,
|
|
1399
1275
|
);
|
|
1400
1276
|
state.array = b;
|
|
1401
1277
|
state.blocks = b_blocks;
|
|
@@ -1409,7 +1285,7 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1409
1285
|
next_pos = pos + 1;
|
|
1410
1286
|
|
|
1411
1287
|
var target = block_start(b_blocks, next_pos, b_length, anchor);
|
|
1412
|
-
b_blocks[pos] = create_item(target, b_val, pos,
|
|
1288
|
+
b_blocks[pos] = create_item(target, b_val, pos, undefined, state);
|
|
1413
1289
|
} else if (j < 0 || i !== seq[j]) {
|
|
1414
1290
|
pos = i + b_start;
|
|
1415
1291
|
next_pos = pos + 1;
|
|
@@ -1428,7 +1304,7 @@ function reconcile_by_ref_diff(anchor, block, b, b_blocks, render_fn, is_control
|
|
|
1428
1304
|
next_pos = pos + 1;
|
|
1429
1305
|
|
|
1430
1306
|
var target = block_start(b_blocks, next_pos, b_length, anchor);
|
|
1431
|
-
b_blocks[pos] = create_item(target, b_val, pos,
|
|
1307
|
+
b_blocks[pos] = create_item(target, b_val, pos, undefined, state);
|
|
1432
1308
|
}
|
|
1433
1309
|
}
|
|
1434
1310
|
}
|