Skip to content

Commit 3221d65

Browse files
committed
consistency better fix
1 parent 8bf08ff commit 3221d65

File tree

2 files changed

+38
-31
lines changed

2 files changed

+38
-31
lines changed

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import {
1919
check_dirtiness,
2020
set_is_flushing_effect,
2121
is_flushing_effect,
22-
unsafe_mutations
22+
unsafe_mutating,
23+
unsafe_sources,
24+
set_unsafe_sources
2325
} from '../runtime.js';
2426
import { equals, safe_equals } from './equality.js';
2527
import {
@@ -148,7 +150,7 @@ export function mutate(source, value) {
148150
export function set(source, value) {
149151
if (
150152
active_reaction !== null &&
151-
!unsafe_mutations &&
153+
!unsafe_mutating &&
152154
is_runes() &&
153155
(active_reaction.f & (DERIVED | BLOCK_EFFECT)) !== 0 &&
154156
// If the source was created locally within the current derived, then
@@ -172,6 +174,14 @@ export function internal_set(source, value) {
172174
source.v = value;
173175
source.version = increment_version();
174176

177+
if (unsafe_mutating) {
178+
if (unsafe_sources === null) {
179+
set_unsafe_sources([source]);
180+
} else {
181+
unsafe_sources.push(source);
182+
}
183+
}
184+
175185
if (DEV && tracing_mode_flag) {
176186
source.updated = get_stack('UpdatedAt');
177187
}
@@ -231,7 +241,7 @@ export function internal_set(source, value) {
231241
* @param {number} status should be DIRTY or MAYBE_DIRTY
232242
* @returns {void}
233243
*/
234-
function mark_reactions(signal, status) {
244+
export function mark_reactions(signal, status) {
235245
var reactions = signal.reactions;
236246
if (reactions === null) return;
237247

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

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
} from './constants.js';
3030
import { flush_tasks } from './dom/task.js';
3131
import { add_owner } from './dev/ownership.js';
32-
import { internal_set, set, source } from './reactivity/sources.js';
32+
import { internal_set, mark_reactions, set, source } from './reactivity/sources.js';
3333
import { destroy_derived, execute_derived, update_derived } from './reactivity/deriveds.js';
3434
import * as e from './errors.js';
3535
import { lifecycle_outside_component } from '../shared/errors.js';
@@ -80,9 +80,15 @@ export let active_reaction = null;
8080

8181
export let untracking = false;
8282

83-
export let unsafe_mutations = false;
83+
export let unsafe_mutating = false;
8484

85-
export let unsafe_mutation_inside_effect = false;
85+
/** @type {null | Source[]} */
86+
export let unsafe_sources = null;
87+
88+
/** @param {Source[] | null} value */
89+
export function set_unsafe_sources(value) {
90+
unsafe_sources = value;
91+
}
8692

8793
/** @param {null | Reaction} reaction */
8894
export function set_active_reaction(reaction) {
@@ -394,7 +400,7 @@ export function update_reaction(reaction) {
394400
var prev_derived_sources = derived_sources;
395401
var previous_component_context = component_context;
396402
var previous_untracking = untracking;
397-
var previous_unsafe_mutations = unsafe_mutations;
403+
var previous_unsafe_mutating = unsafe_mutating;
398404
var flags = reaction.f;
399405

400406
new_deps = /** @type {null | Value[]} */ (null);
@@ -405,7 +411,7 @@ export function update_reaction(reaction) {
405411
derived_sources = null;
406412
component_context = reaction.ctx;
407413
untracking = false;
408-
unsafe_mutations = false;
414+
unsafe_mutating = false;
409415

410416
try {
411417
var result = /** @type {Function} */ (0, reaction.fn)();
@@ -445,7 +451,7 @@ export function update_reaction(reaction) {
445451
derived_sources = prev_derived_sources;
446452
component_context = previous_component_context;
447453
untracking = previous_untracking;
448-
unsafe_mutations = previous_unsafe_mutations;
454+
unsafe_mutating = previous_unsafe_mutating;
449455
}
450456
}
451457

@@ -519,10 +525,10 @@ export function update_effect(effect) {
519525

520526
var previous_effect = active_effect;
521527
var previous_component_context = component_context;
522-
var previous_unsafe_mutation_inside_effect = unsafe_mutation_inside_effect;
528+
var previous_unsafe_sources = unsafe_sources;
523529

524530
active_effect = effect;
525-
unsafe_mutation_inside_effect = false;
531+
unsafe_sources = null;
526532

527533
if (DEV) {
528534
var previous_component_fn = dev_current_component_function;
@@ -539,17 +545,14 @@ export function update_effect(effect) {
539545

540546
execute_effect_teardown(effect);
541547
var teardown = update_reaction(effect);
542-
var is_init = effect.version === 0;
543548
effect.teardown = typeof teardown === 'function' ? teardown : null;
544549

545-
// If unsafe() has been used within the effect on the first time
546-
// it's run, then we might need to schedule the effect to run again
547-
// if it has a dependency that has been invalidated
548-
if (unsafe_mutation_inside_effect && is_init && (effect.f & CLEAN) !== 0) {
549-
set_signal_status(effect, MAYBE_DIRTY);
550-
if (check_dirtiness(effect)) {
551-
set_signal_status(effect, DIRTY);
552-
schedule_effect(effect);
550+
// If unsafe() has been used within the effect then we will need
551+
// to re-invalidate any unsafe sources that were already invalidated
552+
// to ensure consistency of the graph
553+
if (unsafe_sources !== null && (effect.f & CLEAN) !== 0) {
554+
for (let i = 0; i < /** @type {Source[]} */ (unsafe_sources).length; i++) {
555+
mark_reactions(unsafe_sources[i], DIRTY);
553556
}
554557
}
555558

@@ -562,7 +565,7 @@ export function update_effect(effect) {
562565
handle_error(error, effect, previous_effect, previous_component_context || effect.ctx);
563566
} finally {
564567
active_effect = previous_effect;
565-
unsafe_mutation_inside_effect = previous_unsafe_mutation_inside_effect;
568+
unsafe_sources = previous_unsafe_sources;
566569

567570
if (DEV) {
568571
dev_current_component_function = previous_component_fn;
@@ -1062,18 +1065,12 @@ export function untrack(fn) {
10621065
* @returns {T}
10631066
*/
10641067
export function unsafe(fn) {
1065-
var previous_unsafe_mutations = unsafe_mutations;
1068+
var previous_unsafe_mutating = unsafe_mutating;
10661069
try {
1067-
unsafe_mutations = true;
1068-
var val = fn();
1069-
1070-
if (is_flushing_effect) {
1071-
unsafe_mutation_inside_effect = true;
1072-
}
1073-
1074-
return val;
1070+
unsafe_mutating = true;
1071+
return fn();
10751072
} finally {
1076-
unsafe_mutations = previous_unsafe_mutations;
1073+
unsafe_mutating = previous_unsafe_mutating;
10771074
}
10781075
}
10791076

0 commit comments

Comments
 (0)