Skip to content

Commit 84b6ad7

Browse files
committed
wip
1 parent 044475d commit 84b6ad7

File tree

4 files changed

+100
-50
lines changed

4 files changed

+100
-50
lines changed

packages/svelte/src/internal/client/dom/blocks/boundary.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import {
1818
set_active_effect,
1919
set_active_reaction,
2020
reset_is_throwing_error,
21-
schedule_effect
21+
schedule_effect,
22+
increment_write_version
2223
} from '../../runtime.js';
2324
import {
2425
hydrate_next,
@@ -170,11 +171,8 @@ export function boundary(node, props, children) {
170171
for (var [signal, entry] of forks) {
171172
if (signal.v !== entry.v) {
172173
if ((signal.f & DERIVED) === 0) {
173-
var val = signal.v;
174-
signal.v = entry.v;
175-
internal_set(signal, val);
176-
} else {
177-
mark_reactions(signal, DIRTY);
174+
mark_reactions(signal, DIRTY, undefined, true);
175+
signal.wv = increment_write_version();
178176
}
179177
}
180178
}

packages/svelte/src/internal/client/reactivity/sources.js

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@ import {
2828
UNOWNED,
2929
MAYBE_DIRTY,
3030
BLOCK_EFFECT,
31-
ROOT_EFFECT
31+
ROOT_EFFECT,
32+
ASYNC_DERIVED
3233
} from '../constants.js';
3334
import * as e from '../errors.js';
3435
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
3536
import { get_stack } from '../dev/tracing.js';
3637
import { component_context, is_runes } from '../context.js';
38+
import { get_boundary } from '../dom/blocks/boundary.js';
3739

3840
export let inspect_effects = new Set();
3941

@@ -169,6 +171,7 @@ export function set(source, value) {
169171
*/
170172
export function internal_set(source, value) {
171173
if (!source.equals(value)) {
174+
possibly_fork(source);
172175

173176
mark_reactions(source, DIRTY);
174177

@@ -258,9 +261,10 @@ export function update_pre(source, d = 1) {
258261
/**
259262
* @param {Value} signal
260263
* @param {number} status should be DIRTY or MAYBE_DIRTY
264+
* @param {Value} [parent]
261265
* @returns {void}
262266
*/
263-
export function mark_reactions(signal, status) {
267+
export function mark_reactions(signal, status, parent, only_boundary = false) {
264268
var reactions = signal.reactions;
265269
if (reactions === null) return;
266270

@@ -277,6 +281,24 @@ export function mark_reactions(signal, status) {
277281
// In legacy mode, skip the current effect to prevent infinite loops
278282
if (!runes && reaction === active_effect) continue;
279283

284+
if (only_boundary) {
285+
if ((flags & (DERIVED)) === 0) {
286+
var boundary = get_boundary(/** @type {Effect} */ (reaction));
287+
if (!boundary) {
288+
continue;
289+
}
290+
}
291+
} else if ((flags & (DERIVED | ASYNC_DERIVED)) === 0) {
292+
boundary = get_boundary(/** @type {Effect} */ (reaction));
293+
if (boundary) {
294+
// @ts-ignore
295+
var forks = boundary.fn.forks;
296+
if (forks.has(signal) || forks.has(parent)) {
297+
continue;
298+
}
299+
}
300+
}
301+
280302
// Inspect effects need to run immediately, so that the stack trace makes sense
281303
if (DEV && (flags & INSPECT_EFFECT) !== 0) {
282304
inspect_effects.add(reaction);
@@ -288,10 +310,76 @@ export function mark_reactions(signal, status) {
288310
// If the signal a) was previously clean or b) is an unowned derived, then mark it
289311
if ((flags & (CLEAN | UNOWNED)) !== 0) {
290312
if ((flags & DERIVED) !== 0) {
291-
mark_reactions(/** @type {Derived} */ (reaction), MAYBE_DIRTY);
313+
mark_reactions(/** @type {Derived} */ (reaction), MAYBE_DIRTY, signal, only_boundary);
292314
} else {
293315
schedule_effect(/** @type {Effect} */ (reaction));
294316
}
295317
}
296318
}
297319
}
320+
321+
/**
322+
* @param {Source | Derived} signal
323+
* @param {any} forks
324+
*/
325+
function fork_dependencies(signal, forks) {
326+
var entry = forks.get(signal);
327+
if (entry === undefined) {
328+
entry = { v: signal.v };
329+
forks.set(signal, entry);
330+
if ((signal.f & DERIVED) !== 0) {
331+
var deps = /** @type {Derived} */ (signal).deps;
332+
if (deps !== null) {
333+
for (var i = 0; i < deps.length; i++) {
334+
fork_dependencies(deps[i], forks);
335+
}
336+
}
337+
}
338+
}
339+
}
340+
341+
/**
342+
* @param {Value} signal
343+
* @returns {void}
344+
*/
345+
function possibly_fork(signal) {
346+
var reactions = signal.reactions;
347+
if (reactions === null) return;
348+
349+
var runes = is_runes();
350+
var length = reactions.length;
351+
352+
for (var i = 0; i < length; i++) {
353+
var reaction = reactions[i];
354+
var flags = reaction.f;
355+
356+
// Skip any effects that are already dirty
357+
if ((flags & DIRTY) !== 0) continue;
358+
359+
// In legacy mode, skip the current effect to prevent infinite loops
360+
if (!runes && reaction === active_effect) continue;
361+
362+
// If the signal a) was previously clean or b) is an unowned derived, then mark it
363+
if ((flags & (CLEAN | UNOWNED)) !== 0) {
364+
if ((flags & DERIVED) !== 0) {
365+
possibly_fork(/** @type {Derived} */ (reaction));
366+
} else {
367+
if ((reaction.f & ASYNC_DERIVED) !== 0) {
368+
// if (active_effect === signal) {
369+
// set_signal_status(signal, MAYBE_DIRTY);
370+
// return;
371+
// }
372+
var boundary = get_boundary(/** @type {Effect} */ (reaction));
373+
// @ts-ignore
374+
var forks = boundary.fn.forks;
375+
var deps = reaction.deps;
376+
if (deps !== null) {
377+
for (var s = 0; s < deps.length; s++) {
378+
fork_dependencies(deps[s], forks);
379+
}
380+
}
381+
}
382+
}
383+
}
384+
}
385+
}

packages/svelte/src/internal/client/runtime.js

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -783,47 +783,11 @@ function flush_deferred() {
783783
}
784784
}
785785

786-
/**
787-
* @param {Source | Derived} signal
788-
* @param {any} forks
789-
*/
790-
function fork_dependencies(signal, forks) {
791-
var entry = forks.get(signal);
792-
if (entry === undefined) {
793-
entry = { v: signal.v };
794-
forks.set(signal, entry);
795-
if ((signal.f & DERIVED) !== 0) {
796-
var deps = /** @type {Derived} */ (signal).deps;
797-
if (deps !== null) {
798-
for (var i = 0; i < deps.length; i++) {
799-
fork_dependencies(deps[i], forks);
800-
}
801-
}
802-
}
803-
}
804-
}
805-
806786
/**
807787
* @param {Effect} signal
808788
* @returns {void}
809789
*/
810790
export function schedule_effect(signal) {
811-
if ((signal.f & ASYNC_DERIVED) !== 0) {
812-
if (active_effect === signal) {
813-
set_signal_status(signal, MAYBE_DIRTY);
814-
return;
815-
}
816-
var boundary = get_boundary(signal);
817-
// @ts-ignore
818-
var forks = boundary.fn.forks;
819-
var deps = signal.deps;
820-
if (deps !== null) {
821-
for (var i = 0; i < deps.length; i++) {
822-
fork_dependencies(deps[i], forks);
823-
}
824-
}
825-
}
826-
827791
if (scheduler_mode === FLUSH_MICROTASK) {
828792
if (!is_micro_task_queued) {
829793
is_micro_task_queued = true;
@@ -1067,7 +1031,11 @@ export function get(signal) {
10671031

10681032
var target_effect = event_boundary_effect ?? active_effect;
10691033

1070-
if (target_effect !== null && !is_flushing_async_derived) {
1034+
if (
1035+
target_effect !== null &&
1036+
!is_flushing_async_derived &&
1037+
(target_effect.f & ASYNC_DERIVED) === 0
1038+
) {
10711039
var boundary = get_boundary(target_effect);
10721040
if (boundary !== null) {
10731041
// @ts-ignore

packages/svelte/tests/runtime-runes/samples/async-derived/_config.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,7 @@ export default test({
3232
await Promise.resolve();
3333
await Promise.resolve();
3434
await Promise.resolve();
35-
await Promise.resolve();
36-
await Promise.resolve();
37-
await Promise.resolve();
3835
await tick();
39-
flushSync();
4036
assert.htmlEqual(target.innerHTML, '<p>84</p>');
4137

4238
d = deferred();

0 commit comments

Comments
 (0)