svelte 5.40.2 → 5.41.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/compiler/index.js +1 -1
- package/package.json +1 -1
- package/src/compiler/errors.js +11 -2
- package/src/compiler/phases/2-analyze/visitors/CallExpression.js +7 -0
- package/src/compiler/phases/2-analyze/visitors/EachBlock.js +5 -0
- package/src/compiler/phases/3-transform/client/transform-client.js +4 -1
- package/src/compiler/phases/3-transform/client/visitors/CallExpression.js +6 -0
- package/src/compiler/phases/3-transform/client/visitors/Fragment.js +7 -2
- package/src/compiler/phases/3-transform/client/visitors/LetDirective.js +21 -17
- package/src/compiler/phases/3-transform/client/visitors/RegularElement.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/SlotElement.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/SvelteFragment.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/shared/component.js +2 -2
- package/src/compiler/phases/3-transform/server/visitors/CallExpression.js +4 -0
- package/src/internal/client/dom/blocks/await.js +71 -137
- package/src/internal/client/dom/blocks/boundary.js +7 -19
- package/src/internal/client/dom/blocks/branches.js +185 -0
- package/src/internal/client/dom/blocks/if.js +28 -107
- package/src/internal/client/dom/blocks/key.js +12 -58
- package/src/internal/client/dom/blocks/snippet.js +6 -22
- package/src/internal/client/dom/blocks/svelte-component.js +7 -63
- package/src/internal/client/dom/blocks/svelte-element.js +34 -45
- package/src/internal/client/dom/elements/bindings/select.js +21 -0
- package/src/internal/client/index.js +1 -1
- package/src/internal/client/reactivity/async.js +24 -8
- package/src/internal/client/reactivity/batch.js +66 -24
- package/src/internal/client/reactivity/effects.js +20 -2
- package/src/utils.js +1 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +12 -0
- package/types/index.d.ts.map +1 -1
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/** @import { Effect, TemplateNode } from '#client' */
|
|
2
|
+
import { is_runes } from '../../context.js';
|
|
3
|
+
import { Batch, current_batch } from '../../reactivity/batch.js';
|
|
4
|
+
import {
|
|
5
|
+
branch,
|
|
6
|
+
destroy_effect,
|
|
7
|
+
move_effect,
|
|
8
|
+
pause_effect,
|
|
9
|
+
resume_effect
|
|
10
|
+
} from '../../reactivity/effects.js';
|
|
11
|
+
import { set_should_intro, should_intro } from '../../render.js';
|
|
12
|
+
import { hydrate_node, hydrating } from '../hydration.js';
|
|
13
|
+
import { create_text, should_defer_append } from '../operations.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {{ effect: Effect, fragment: DocumentFragment }} Branch
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @template Key
|
|
21
|
+
*/
|
|
22
|
+
export class BranchManager {
|
|
23
|
+
/** @type {TemplateNode} */
|
|
24
|
+
anchor;
|
|
25
|
+
|
|
26
|
+
/** @type {Map<Batch, Key>} */
|
|
27
|
+
#batches = new Map();
|
|
28
|
+
|
|
29
|
+
/** @type {Map<Key, Effect>} */
|
|
30
|
+
#onscreen = new Map();
|
|
31
|
+
|
|
32
|
+
/** @type {Map<Key, Branch>} */
|
|
33
|
+
#offscreen = new Map();
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Whether to pause (i.e. outro) on change, or destroy immediately.
|
|
37
|
+
* This is necessary for `<svelte:element>`
|
|
38
|
+
*/
|
|
39
|
+
#transition = true;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {TemplateNode} anchor
|
|
43
|
+
* @param {boolean} transition
|
|
44
|
+
*/
|
|
45
|
+
constructor(anchor, transition = true) {
|
|
46
|
+
this.anchor = anchor;
|
|
47
|
+
this.#transition = transition;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#commit = () => {
|
|
51
|
+
var batch = /** @type {Batch} */ (current_batch);
|
|
52
|
+
|
|
53
|
+
// if this batch was made obsolete, bail
|
|
54
|
+
if (!this.#batches.has(batch)) return;
|
|
55
|
+
|
|
56
|
+
var key = /** @type {Key} */ (this.#batches.get(batch));
|
|
57
|
+
|
|
58
|
+
var onscreen = this.#onscreen.get(key);
|
|
59
|
+
|
|
60
|
+
if (onscreen) {
|
|
61
|
+
// effect is already in the DOM — abort any current outro
|
|
62
|
+
resume_effect(onscreen);
|
|
63
|
+
} else {
|
|
64
|
+
// effect is currently offscreen. put it in the DOM
|
|
65
|
+
var offscreen = this.#offscreen.get(key);
|
|
66
|
+
|
|
67
|
+
if (offscreen) {
|
|
68
|
+
this.#onscreen.set(key, offscreen.effect);
|
|
69
|
+
this.#offscreen.delete(key);
|
|
70
|
+
|
|
71
|
+
// remove the anchor...
|
|
72
|
+
/** @type {TemplateNode} */ (offscreen.fragment.lastChild).remove();
|
|
73
|
+
|
|
74
|
+
// ...and append the fragment
|
|
75
|
+
this.anchor.before(offscreen.fragment);
|
|
76
|
+
onscreen = offscreen.effect;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
for (const [b, k] of this.#batches) {
|
|
81
|
+
this.#batches.delete(b);
|
|
82
|
+
|
|
83
|
+
if (b === batch) {
|
|
84
|
+
// keep values for newer batches
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const offscreen = this.#offscreen.get(k);
|
|
89
|
+
|
|
90
|
+
if (offscreen) {
|
|
91
|
+
// for older batches, destroy offscreen effects
|
|
92
|
+
// as they will never be committed
|
|
93
|
+
destroy_effect(offscreen.effect);
|
|
94
|
+
this.#offscreen.delete(k);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// outro/destroy all onscreen effects...
|
|
99
|
+
for (const [k, effect] of this.#onscreen) {
|
|
100
|
+
// ...except the one that was just committed
|
|
101
|
+
if (k === key) continue;
|
|
102
|
+
|
|
103
|
+
const on_destroy = () => {
|
|
104
|
+
const keys = Array.from(this.#batches.values());
|
|
105
|
+
|
|
106
|
+
if (keys.includes(k)) {
|
|
107
|
+
// keep the effect offscreen, as another batch will need it
|
|
108
|
+
var fragment = document.createDocumentFragment();
|
|
109
|
+
move_effect(effect, fragment);
|
|
110
|
+
|
|
111
|
+
fragment.append(create_text()); // TODO can we avoid this?
|
|
112
|
+
|
|
113
|
+
this.#offscreen.set(k, { effect, fragment });
|
|
114
|
+
} else {
|
|
115
|
+
destroy_effect(effect);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.#onscreen.delete(k);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
if (this.#transition || !onscreen) {
|
|
122
|
+
pause_effect(effect, on_destroy, false);
|
|
123
|
+
} else {
|
|
124
|
+
on_destroy();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
*
|
|
131
|
+
* @param {any} key
|
|
132
|
+
* @param {null | ((target: TemplateNode) => void)} fn
|
|
133
|
+
*/
|
|
134
|
+
ensure(key, fn) {
|
|
135
|
+
var batch = /** @type {Batch} */ (current_batch);
|
|
136
|
+
var defer = should_defer_append();
|
|
137
|
+
|
|
138
|
+
if (fn && !this.#onscreen.has(key) && !this.#offscreen.has(key)) {
|
|
139
|
+
if (defer) {
|
|
140
|
+
var fragment = document.createDocumentFragment();
|
|
141
|
+
var target = create_text();
|
|
142
|
+
|
|
143
|
+
fragment.append(target);
|
|
144
|
+
|
|
145
|
+
this.#offscreen.set(key, {
|
|
146
|
+
effect: branch(() => fn(target)),
|
|
147
|
+
fragment
|
|
148
|
+
});
|
|
149
|
+
} else {
|
|
150
|
+
this.#onscreen.set(
|
|
151
|
+
key,
|
|
152
|
+
branch(() => fn(this.anchor))
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.#batches.set(batch, key);
|
|
158
|
+
|
|
159
|
+
if (defer) {
|
|
160
|
+
for (const [k, effect] of this.#onscreen) {
|
|
161
|
+
if (k === key) {
|
|
162
|
+
batch.skipped_effects.delete(effect);
|
|
163
|
+
} else {
|
|
164
|
+
batch.skipped_effects.add(effect);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
for (const [k, branch] of this.#offscreen) {
|
|
169
|
+
if (k === key) {
|
|
170
|
+
batch.skipped_effects.delete(branch.effect);
|
|
171
|
+
} else {
|
|
172
|
+
batch.skipped_effects.add(branch.effect);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
batch.add_callback(this.#commit);
|
|
177
|
+
} else {
|
|
178
|
+
if (hydrating) {
|
|
179
|
+
this.anchor = hydrate_node;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
this.#commit();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
/** @import {
|
|
2
|
-
/** @import { Batch } from '../../reactivity/batch.js'; */
|
|
1
|
+
/** @import { TemplateNode } from '#client' */
|
|
3
2
|
import { EFFECT_TRANSPARENT } from '#client/constants';
|
|
4
3
|
import {
|
|
5
4
|
hydrate_next,
|
|
6
|
-
hydrate_node,
|
|
7
5
|
hydrating,
|
|
8
6
|
read_hydration_instruction,
|
|
9
7
|
skip_nodes,
|
|
10
8
|
set_hydrate_node,
|
|
11
9
|
set_hydrating
|
|
12
10
|
} from '../hydration.js';
|
|
13
|
-
import { block
|
|
14
|
-
import { HYDRATION_START_ELSE
|
|
15
|
-
import {
|
|
16
|
-
import { current_batch } from '../../reactivity/batch.js';
|
|
11
|
+
import { block } from '../../reactivity/effects.js';
|
|
12
|
+
import { HYDRATION_START_ELSE } from '../../../../constants.js';
|
|
13
|
+
import { BranchManager } from './branches.js';
|
|
17
14
|
|
|
18
15
|
// TODO reinstate https://github.com/sveltejs/svelte/pull/15250
|
|
19
16
|
|
|
@@ -28,122 +25,46 @@ export function if_block(node, fn, elseif = false) {
|
|
|
28
25
|
hydrate_next();
|
|
29
26
|
}
|
|
30
27
|
|
|
31
|
-
var
|
|
32
|
-
|
|
33
|
-
/** @type {Effect | null} */
|
|
34
|
-
var consequent_effect = null;
|
|
35
|
-
|
|
36
|
-
/** @type {Effect | null} */
|
|
37
|
-
var alternate_effect = null;
|
|
38
|
-
|
|
39
|
-
/** @type {typeof UNINITIALIZED | boolean | null} */
|
|
40
|
-
var condition = UNINITIALIZED;
|
|
41
|
-
|
|
28
|
+
var branches = new BranchManager(node);
|
|
42
29
|
var flags = elseif ? EFFECT_TRANSPARENT : 0;
|
|
43
30
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/** @type {DocumentFragment | null} */
|
|
52
|
-
var offscreen_fragment = null;
|
|
53
|
-
|
|
54
|
-
function commit() {
|
|
55
|
-
if (offscreen_fragment !== null) {
|
|
56
|
-
// remove the anchor
|
|
57
|
-
/** @type {Text} */ (offscreen_fragment.lastChild).remove();
|
|
58
|
-
|
|
59
|
-
anchor.before(offscreen_fragment);
|
|
60
|
-
offscreen_fragment = null;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
var active = condition ? consequent_effect : alternate_effect;
|
|
64
|
-
var inactive = condition ? alternate_effect : consequent_effect;
|
|
65
|
-
|
|
66
|
-
if (active) {
|
|
67
|
-
resume_effect(active);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (inactive) {
|
|
71
|
-
pause_effect(inactive, () => {
|
|
72
|
-
if (condition) {
|
|
73
|
-
alternate_effect = null;
|
|
74
|
-
} else {
|
|
75
|
-
consequent_effect = null;
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const update_branch = (
|
|
82
|
-
/** @type {boolean | null} */ new_condition,
|
|
83
|
-
/** @type {null | ((anchor: Node) => void)} */ fn
|
|
84
|
-
) => {
|
|
85
|
-
if (condition === (condition = new_condition)) return;
|
|
86
|
-
|
|
87
|
-
/** Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
|
|
88
|
-
let mismatch = false;
|
|
89
|
-
|
|
31
|
+
/**
|
|
32
|
+
* @param {boolean} condition,
|
|
33
|
+
* @param {null | ((anchor: Node) => void)} fn
|
|
34
|
+
*/
|
|
35
|
+
function update_branch(condition, fn) {
|
|
90
36
|
if (hydrating) {
|
|
91
|
-
const is_else = read_hydration_instruction(
|
|
37
|
+
const is_else = read_hydration_instruction(node) === HYDRATION_START_ELSE;
|
|
92
38
|
|
|
93
|
-
if (
|
|
39
|
+
if (condition === is_else) {
|
|
94
40
|
// Hydration mismatch: remove everything inside the anchor and start fresh.
|
|
95
41
|
// This could happen with `{#if browser}...{/if}`, for example
|
|
96
|
-
anchor = skip_nodes();
|
|
42
|
+
var anchor = skip_nodes();
|
|
97
43
|
|
|
98
44
|
set_hydrate_node(anchor);
|
|
99
|
-
|
|
100
|
-
mismatch = true;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
45
|
+
branches.anchor = anchor;
|
|
103
46
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (defer) {
|
|
108
|
-
offscreen_fragment = document.createDocumentFragment();
|
|
109
|
-
offscreen_fragment.append((target = create_text()));
|
|
110
|
-
}
|
|
47
|
+
set_hydrating(false);
|
|
48
|
+
branches.ensure(condition, fn);
|
|
49
|
+
set_hydrating(true);
|
|
111
50
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
} else {
|
|
115
|
-
alternate_effect ??= fn && branch(() => fn(target));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
116
53
|
}
|
|
117
54
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
var active = condition ? consequent_effect : alternate_effect;
|
|
122
|
-
var inactive = condition ? alternate_effect : consequent_effect;
|
|
123
|
-
|
|
124
|
-
if (active) batch.skipped_effects.delete(active);
|
|
125
|
-
if (inactive) batch.skipped_effects.add(inactive);
|
|
55
|
+
branches.ensure(condition, fn);
|
|
56
|
+
}
|
|
126
57
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
commit();
|
|
130
|
-
}
|
|
58
|
+
block(() => {
|
|
59
|
+
var has_branch = false;
|
|
131
60
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
};
|
|
61
|
+
fn((fn, flag = true) => {
|
|
62
|
+
has_branch = true;
|
|
63
|
+
update_branch(flag, fn);
|
|
64
|
+
});
|
|
137
65
|
|
|
138
|
-
block(() => {
|
|
139
|
-
has_branch = false;
|
|
140
|
-
fn(set_branch);
|
|
141
66
|
if (!has_branch) {
|
|
142
|
-
update_branch(
|
|
67
|
+
update_branch(false, null);
|
|
143
68
|
}
|
|
144
69
|
}, flags);
|
|
145
|
-
|
|
146
|
-
if (hydrating) {
|
|
147
|
-
anchor = hydrate_node;
|
|
148
|
-
}
|
|
149
70
|
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
/** @import {
|
|
2
|
-
/** @import { Batch } from '../../reactivity/batch.js'; */
|
|
3
|
-
import { UNINITIALIZED } from '../../../../constants.js';
|
|
4
|
-
import { block, branch, pause_effect } from '../../reactivity/effects.js';
|
|
5
|
-
import { not_equal, safe_not_equal } from '../../reactivity/equality.js';
|
|
1
|
+
/** @import { TemplateNode } from '#client' */
|
|
6
2
|
import { is_runes } from '../../context.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
3
|
+
import { block } from '../../reactivity/effects.js';
|
|
4
|
+
import { hydrate_next, hydrating } from '../hydration.js';
|
|
5
|
+
import { BranchManager } from './branches.js';
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* @template V
|
|
@@ -20,60 +16,18 @@ export function key(node, get_key, render_fn) {
|
|
|
20
16
|
hydrate_next();
|
|
21
17
|
}
|
|
22
18
|
|
|
23
|
-
var
|
|
19
|
+
var branches = new BranchManager(node);
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
var key = UNINITIALIZED;
|
|
27
|
-
|
|
28
|
-
/** @type {Effect} */
|
|
29
|
-
var effect;
|
|
30
|
-
|
|
31
|
-
/** @type {Effect} */
|
|
32
|
-
var pending_effect;
|
|
33
|
-
|
|
34
|
-
/** @type {DocumentFragment | null} */
|
|
35
|
-
var offscreen_fragment = null;
|
|
36
|
-
|
|
37
|
-
var changed = is_runes() ? not_equal : safe_not_equal;
|
|
38
|
-
|
|
39
|
-
function commit() {
|
|
40
|
-
if (effect) {
|
|
41
|
-
pause_effect(effect);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (offscreen_fragment !== null) {
|
|
45
|
-
// remove the anchor
|
|
46
|
-
/** @type {Text} */ (offscreen_fragment.lastChild).remove();
|
|
47
|
-
|
|
48
|
-
anchor.before(offscreen_fragment);
|
|
49
|
-
offscreen_fragment = null;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
effect = pending_effect;
|
|
53
|
-
}
|
|
21
|
+
var legacy = !is_runes();
|
|
54
22
|
|
|
55
23
|
block(() => {
|
|
56
|
-
|
|
57
|
-
var target = anchor;
|
|
58
|
-
|
|
59
|
-
var defer = should_defer_append();
|
|
60
|
-
|
|
61
|
-
if (defer) {
|
|
62
|
-
offscreen_fragment = document.createDocumentFragment();
|
|
63
|
-
offscreen_fragment.append((target = create_text()));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
pending_effect = branch(() => render_fn(target));
|
|
24
|
+
var key = get_key();
|
|
67
25
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
commit();
|
|
72
|
-
}
|
|
26
|
+
// key blocks in Svelte <5 had stupid semantics
|
|
27
|
+
if (legacy && key !== null && typeof key === 'object') {
|
|
28
|
+
key = /** @type {V} */ ({});
|
|
73
29
|
}
|
|
74
|
-
});
|
|
75
30
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
31
|
+
branches.ensure(key, render_fn);
|
|
32
|
+
});
|
|
79
33
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** @import { Snippet } from 'svelte' */
|
|
2
|
-
/** @import {
|
|
2
|
+
/** @import { TemplateNode } from '#client' */
|
|
3
3
|
/** @import { Getters } from '#shared' */
|
|
4
4
|
import { EFFECT_TRANSPARENT, ELEMENT_NODE } from '#client/constants';
|
|
5
|
-
import {
|
|
5
|
+
import { block, teardown } from '../../reactivity/effects.js';
|
|
6
6
|
import {
|
|
7
7
|
dev_current_component_function,
|
|
8
8
|
set_dev_current_component_function
|
|
@@ -14,8 +14,8 @@ import * as w from '../../warnings.js';
|
|
|
14
14
|
import * as e from '../../errors.js';
|
|
15
15
|
import { DEV } from 'esm-env';
|
|
16
16
|
import { get_first_child, get_next_sibling } from '../operations.js';
|
|
17
|
-
import { noop } from '../../../shared/utils.js';
|
|
18
17
|
import { prevent_snippet_stringification } from '../../../shared/validate.js';
|
|
18
|
+
import { BranchManager } from './branches.js';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* @template {(node: TemplateNode, ...args: any[]) => void} SnippetFn
|
|
@@ -25,33 +25,17 @@ import { prevent_snippet_stringification } from '../../../shared/validate.js';
|
|
|
25
25
|
* @returns {void}
|
|
26
26
|
*/
|
|
27
27
|
export function snippet(node, get_snippet, ...args) {
|
|
28
|
-
var
|
|
29
|
-
|
|
30
|
-
/** @type {SnippetFn | null | undefined} */
|
|
31
|
-
// @ts-ignore
|
|
32
|
-
var snippet = noop;
|
|
33
|
-
|
|
34
|
-
/** @type {Effect | null} */
|
|
35
|
-
var snippet_effect;
|
|
28
|
+
var branches = new BranchManager(node);
|
|
36
29
|
|
|
37
30
|
block(() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (snippet_effect) {
|
|
41
|
-
destroy_effect(snippet_effect);
|
|
42
|
-
snippet_effect = null;
|
|
43
|
-
}
|
|
31
|
+
const snippet = get_snippet() ?? null;
|
|
44
32
|
|
|
45
33
|
if (DEV && snippet == null) {
|
|
46
34
|
e.invalid_snippet();
|
|
47
35
|
}
|
|
48
36
|
|
|
49
|
-
|
|
37
|
+
branches.ensure(snippet, snippet && ((anchor) => snippet(anchor, ...args)));
|
|
50
38
|
}, EFFECT_TRANSPARENT);
|
|
51
|
-
|
|
52
|
-
if (hydrating) {
|
|
53
|
-
anchor = hydrate_node;
|
|
54
|
-
}
|
|
55
39
|
}
|
|
56
40
|
|
|
57
41
|
/**
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
/** @import { TemplateNode, Dom
|
|
2
|
-
/** @import { Batch } from '../../reactivity/batch.js'; */
|
|
1
|
+
/** @import { TemplateNode, Dom } from '#client' */
|
|
3
2
|
import { EFFECT_TRANSPARENT } from '#client/constants';
|
|
4
|
-
import { block
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { create_text, should_defer_append } from '../operations.js';
|
|
3
|
+
import { block } from '../../reactivity/effects.js';
|
|
4
|
+
import { hydrate_next, hydrating } from '../hydration.js';
|
|
5
|
+
import { BranchManager } from './branches.js';
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* @template P
|
|
@@ -19,64 +17,10 @@ export function component(node, get_component, render_fn) {
|
|
|
19
17
|
hydrate_next();
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
/** @type {C} */
|
|
25
|
-
var component;
|
|
26
|
-
|
|
27
|
-
/** @type {Effect | null} */
|
|
28
|
-
var effect;
|
|
29
|
-
|
|
30
|
-
/** @type {DocumentFragment | null} */
|
|
31
|
-
var offscreen_fragment = null;
|
|
32
|
-
|
|
33
|
-
/** @type {Effect | null} */
|
|
34
|
-
var pending_effect = null;
|
|
35
|
-
|
|
36
|
-
function commit() {
|
|
37
|
-
if (effect) {
|
|
38
|
-
pause_effect(effect);
|
|
39
|
-
effect = null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (offscreen_fragment) {
|
|
43
|
-
// remove the anchor
|
|
44
|
-
/** @type {Text} */ (offscreen_fragment.lastChild).remove();
|
|
45
|
-
|
|
46
|
-
anchor.before(offscreen_fragment);
|
|
47
|
-
offscreen_fragment = null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
effect = pending_effect;
|
|
51
|
-
pending_effect = null;
|
|
52
|
-
}
|
|
20
|
+
var branches = new BranchManager(node);
|
|
53
21
|
|
|
54
22
|
block(() => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
var defer = should_defer_append();
|
|
58
|
-
|
|
59
|
-
if (component) {
|
|
60
|
-
var target = anchor;
|
|
61
|
-
|
|
62
|
-
if (defer) {
|
|
63
|
-
offscreen_fragment = document.createDocumentFragment();
|
|
64
|
-
offscreen_fragment.append((target = create_text()));
|
|
65
|
-
if (effect) {
|
|
66
|
-
/** @type {Batch} */ (current_batch).skipped_effects.add(effect);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
pending_effect = branch(() => render_fn(target, component));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (defer) {
|
|
73
|
-
/** @type {Batch} */ (current_batch).add_callback(commit);
|
|
74
|
-
} else {
|
|
75
|
-
commit();
|
|
76
|
-
}
|
|
23
|
+
var component = get_component() ?? null;
|
|
24
|
+
branches.ensure(component, component && ((target) => render_fn(target, component)));
|
|
77
25
|
}, EFFECT_TRANSPARENT);
|
|
78
|
-
|
|
79
|
-
if (hydrating) {
|
|
80
|
-
anchor = hydrate_node;
|
|
81
|
-
}
|
|
82
26
|
}
|