consistency better fix

fix-untrack-expose-unsafe
Dominic Gannaway 5 days ago
parent 8bf08ff422
commit 3221d652fd

@ -19,7 +19,9 @@ import {
check_dirtiness, check_dirtiness,
set_is_flushing_effect, set_is_flushing_effect,
is_flushing_effect, is_flushing_effect,
unsafe_mutations unsafe_mutating,
unsafe_sources,
set_unsafe_sources
} from '../runtime.js'; } from '../runtime.js';
import { equals, safe_equals } from './equality.js'; import { equals, safe_equals } from './equality.js';
import { import {
@ -148,7 +150,7 @@ export function mutate(source, value) {
export function set(source, value) { export function set(source, value) {
if ( if (
active_reaction !== null && active_reaction !== null &&
!unsafe_mutations && !unsafe_mutating &&
is_runes() && is_runes() &&
(active_reaction.f & (DERIVED | BLOCK_EFFECT)) !== 0 && (active_reaction.f & (DERIVED | BLOCK_EFFECT)) !== 0 &&
// If the source was created locally within the current derived, then // If the source was created locally within the current derived, then
@ -172,6 +174,14 @@ export function internal_set(source, value) {
source.v = value; source.v = value;
source.version = increment_version(); source.version = increment_version();
if (unsafe_mutating) {
if (unsafe_sources === null) {
set_unsafe_sources([source]);
} else {
unsafe_sources.push(source);
}
}
if (DEV && tracing_mode_flag) { if (DEV && tracing_mode_flag) {
source.updated = get_stack('UpdatedAt'); source.updated = get_stack('UpdatedAt');
} }
@ -231,7 +241,7 @@ export function internal_set(source, value) {
* @param {number} status should be DIRTY or MAYBE_DIRTY * @param {number} status should be DIRTY or MAYBE_DIRTY
* @returns {void} * @returns {void}
*/ */
function mark_reactions(signal, status) { export function mark_reactions(signal, status) {
var reactions = signal.reactions; var reactions = signal.reactions;
if (reactions === null) return; if (reactions === null) return;

@ -29,7 +29,7 @@ import {
} from './constants.js'; } from './constants.js';
import { flush_tasks } from './dom/task.js'; import { flush_tasks } from './dom/task.js';
import { add_owner } from './dev/ownership.js'; import { add_owner } from './dev/ownership.js';
import { internal_set, set, source } from './reactivity/sources.js'; import { internal_set, mark_reactions, set, source } from './reactivity/sources.js';
import { destroy_derived, execute_derived, update_derived } from './reactivity/deriveds.js'; import { destroy_derived, execute_derived, update_derived } from './reactivity/deriveds.js';
import * as e from './errors.js'; import * as e from './errors.js';
import { lifecycle_outside_component } from '../shared/errors.js'; import { lifecycle_outside_component } from '../shared/errors.js';
@ -80,9 +80,15 @@ export let active_reaction = null;
export let untracking = false; export let untracking = false;
export let unsafe_mutations = false; export let unsafe_mutating = false;
export let unsafe_mutation_inside_effect = false; /** @type {null | Source[]} */
export let unsafe_sources = null;
/** @param {Source[] | null} value */
export function set_unsafe_sources(value) {
unsafe_sources = value;
}
/** @param {null | Reaction} reaction */ /** @param {null | Reaction} reaction */
export function set_active_reaction(reaction) { export function set_active_reaction(reaction) {
@ -394,7 +400,7 @@ export function update_reaction(reaction) {
var prev_derived_sources = derived_sources; var prev_derived_sources = derived_sources;
var previous_component_context = component_context; var previous_component_context = component_context;
var previous_untracking = untracking; var previous_untracking = untracking;
var previous_unsafe_mutations = unsafe_mutations; var previous_unsafe_mutating = unsafe_mutating;
var flags = reaction.f; var flags = reaction.f;
new_deps = /** @type {null | Value[]} */ (null); new_deps = /** @type {null | Value[]} */ (null);
@ -405,7 +411,7 @@ export function update_reaction(reaction) {
derived_sources = null; derived_sources = null;
component_context = reaction.ctx; component_context = reaction.ctx;
untracking = false; untracking = false;
unsafe_mutations = false; unsafe_mutating = false;
try { try {
var result = /** @type {Function} */ (0, reaction.fn)(); var result = /** @type {Function} */ (0, reaction.fn)();
@ -445,7 +451,7 @@ export function update_reaction(reaction) {
derived_sources = prev_derived_sources; derived_sources = prev_derived_sources;
component_context = previous_component_context; component_context = previous_component_context;
untracking = previous_untracking; untracking = previous_untracking;
unsafe_mutations = previous_unsafe_mutations; unsafe_mutating = previous_unsafe_mutating;
} }
} }
@ -519,10 +525,10 @@ export function update_effect(effect) {
var previous_effect = active_effect; var previous_effect = active_effect;
var previous_component_context = component_context; var previous_component_context = component_context;
var previous_unsafe_mutation_inside_effect = unsafe_mutation_inside_effect; var previous_unsafe_sources = unsafe_sources;
active_effect = effect; active_effect = effect;
unsafe_mutation_inside_effect = false; unsafe_sources = null;
if (DEV) { if (DEV) {
var previous_component_fn = dev_current_component_function; var previous_component_fn = dev_current_component_function;
@ -539,17 +545,14 @@ export function update_effect(effect) {
execute_effect_teardown(effect); execute_effect_teardown(effect);
var teardown = update_reaction(effect); var teardown = update_reaction(effect);
var is_init = effect.version === 0;
effect.teardown = typeof teardown === 'function' ? teardown : null; effect.teardown = typeof teardown === 'function' ? teardown : null;
// If unsafe() has been used within the effect on the first time // If unsafe() has been used within the effect then we will need
// it's run, then we might need to schedule the effect to run again // to re-invalidate any unsafe sources that were already invalidated
// if it has a dependency that has been invalidated // to ensure consistency of the graph
if (unsafe_mutation_inside_effect && is_init && (effect.f & CLEAN) !== 0) { if (unsafe_sources !== null && (effect.f & CLEAN) !== 0) {
set_signal_status(effect, MAYBE_DIRTY); for (let i = 0; i < /** @type {Source[]} */ (unsafe_sources).length; i++) {
if (check_dirtiness(effect)) { mark_reactions(unsafe_sources[i], DIRTY);
set_signal_status(effect, DIRTY);
schedule_effect(effect);
} }
} }
@ -562,7 +565,7 @@ export function update_effect(effect) {
handle_error(error, effect, previous_effect, previous_component_context || effect.ctx); handle_error(error, effect, previous_effect, previous_component_context || effect.ctx);
} finally { } finally {
active_effect = previous_effect; active_effect = previous_effect;
unsafe_mutation_inside_effect = previous_unsafe_mutation_inside_effect; unsafe_sources = previous_unsafe_sources;
if (DEV) { if (DEV) {
dev_current_component_function = previous_component_fn; dev_current_component_function = previous_component_fn;
@ -1062,18 +1065,12 @@ export function untrack(fn) {
* @returns {T} * @returns {T}
*/ */
export function unsafe(fn) { export function unsafe(fn) {
var previous_unsafe_mutations = unsafe_mutations; var previous_unsafe_mutating = unsafe_mutating;
try { try {
unsafe_mutations = true; unsafe_mutating = true;
var val = fn(); return fn();
if (is_flushing_effect) {
unsafe_mutation_inside_effect = true;
}
return val;
} finally { } finally {
unsafe_mutations = previous_unsafe_mutations; unsafe_mutating = previous_unsafe_mutating;
} }
} }

Loading…
Cancel
Save