Skip to content

Commit 1032b31

Browse files
committed
fix WAS_MARKED logic
1 parent c96eb44 commit 1032b31

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,10 @@ function mark_reactions(signal, status) {
335335

336336
if ((flags & DERIVED) !== 0) {
337337
if ((flags & WAS_MARKED) === 0) {
338-
reaction.f |= WAS_MARKED;
338+
// Only connected deriveds can be reliably unmarked right away
339+
if (flags & CONNECTED) {
340+
reaction.f |= WAS_MARKED;
341+
}
339342
mark_reactions(/** @type {Derived} */ (reaction), MAYBE_DIRTY);
340343
}
341344
} else if (not_dirty) {

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

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,13 @@ export function is_dirty(reaction) {
154154
return true;
155155
}
156156

157+
if (flags & DERIVED) {
158+
reaction.f &= ~WAS_MARKED;
159+
}
160+
157161
if ((flags & MAYBE_DIRTY) !== 0) {
158162
var dependencies = reaction.deps;
159163

160-
if (flags & DERIVED) {
161-
reaction.f &= ~WAS_MARKED;
162-
}
163-
164164
if (dependencies !== null) {
165165
var i;
166166
var dependency;
@@ -365,9 +365,10 @@ function remove_reaction(signal, dependency) {
365365
) {
366366
set_signal_status(dependency, MAYBE_DIRTY);
367367
// If we are working with a derived that is owned by an effect, then mark it as being
368-
// disconnected.
368+
// disconnected and remove the mark flag, as it cannot be reliably removed otherwise
369369
if ((dependency.f & CONNECTED) !== 0) {
370370
dependency.f ^= CONNECTED;
371+
dependency.f &= ~WAS_MARKED;
371372
}
372373
// Disconnect any reactions owned by this reaction
373374
destroy_derived_effects(/** @type {Derived} **/ (dependency));
@@ -613,6 +614,10 @@ export function get(signal) {
613614
var should_reconnect = is_updating_effect && effect_tracking() && (derived.f & CONNECTED) === 0;
614615

615616
if (batch_values?.has(derived)) {
617+
// This happens as part of is_dirty normally, but we return early
618+
// here so we need to do it separately
619+
remove_marked_flag(derived);
620+
616621
if (should_reconnect) {
617622
reconnect(derived);
618623
}
@@ -657,6 +662,20 @@ function reconnect(derived) {
657662
}
658663
}
659664

665+
/**
666+
* Removes the WAS_MARKED flag from the derived and its dependencies
667+
* @param {Derived} derived
668+
*/
669+
function remove_marked_flag(derived) {
670+
if ((derived.f & WAS_MARKED) === 0) return;
671+
derived.f ^= WAS_MARKED;
672+
673+
// Only deriveds with dependencies can be marked
674+
for (const dep of /** @type {Value[]} */ (derived.deps)) {
675+
remove_marked_flag(/** @type {Derived} */ (dep));
676+
}
677+
}
678+
660679
/** @param {Derived} derived */
661680
function depends_on_old_values(derived) {
662681
if (derived.v === UNINITIALIZED) return true; // we don't know, so assume the worst

0 commit comments

Comments
 (0)