@ -54,6 +54,8 @@ export let current_effect = null;
/** @type {null | import('./types.js').Signal[]} */
/** @type {null | import('./types.js').Signal[]} */
let current _dependencies = null ;
let current _dependencies = null ;
let current _dependencies _index = 0 ;
let current _dependencies _index = 0 ;
/** @type {null | import('./types.js').Signal[]} */
let current _untracked _writes = null ;
// Handling capturing of signals from object property getters
// Handling capturing of signals from object property getters
let current _should _capture _signal = false ;
let current _should _capture _signal = false ;
/** If `true`, `get`ting the signal should not register it as a dependency */
/** If `true`, `get`ting the signal should not register it as a dependency */
@ -282,6 +284,7 @@ function execute_signal_fn(signal) {
const init = signal . i ;
const init = signal . i ;
const previous _dependencies = current _dependencies ;
const previous _dependencies = current _dependencies ;
const previous _dependencies _index = current _dependencies _index ;
const previous _dependencies _index = current _dependencies _index ;
const previous _untracked _writes = current _untracked _writes ;
const previous _consumer = current _consumer ;
const previous _consumer = current _consumer ;
const previous _block = current _block ;
const previous _block = current _block ;
const previous _component _context = current _component _context ;
const previous _component _context = current _component _context ;
@ -290,6 +293,7 @@ function execute_signal_fn(signal) {
const previous _untracking = current _untracking ;
const previous _untracking = current _untracking ;
current _dependencies = /** @type {null | import('./types.js').Signal[]} */ ( null ) ;
current _dependencies = /** @type {null | import('./types.js').Signal[]} */ ( null ) ;
current _dependencies _index = 0 ;
current _dependencies _index = 0 ;
current _untracked _writes = null ;
current _consumer = signal ;
current _consumer = signal ;
current _block = signal . b ;
current _block = signal . b ;
current _component _context = signal . x ;
current _component _context = signal . x ;
@ -347,6 +351,7 @@ function execute_signal_fn(signal) {
} finally {
} finally {
current _dependencies = previous _dependencies ;
current _dependencies = previous _dependencies ;
current _dependencies _index = previous _dependencies _index ;
current _dependencies _index = previous _dependencies _index ;
current _untracked _writes = previous _untracked _writes ;
current _consumer = previous _consumer ;
current _consumer = previous _consumer ;
current _block = previous _block ;
current _block = previous _block ;
current _component _context = previous _component _context ;
current _component _context = previous _component _context ;
@ -469,6 +474,19 @@ export function execute_effect(signal) {
}
}
}
}
function infinite _loop _guard ( ) {
if ( flush _count > 100 ) {
throw new Error (
'ERR_SVELTE_TOO_MANY_UPDATES' +
( DEV
? ': Maximum update depth exceeded. This can happen when a reactive block or effect ' +
'repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops.'
: '' )
) ;
}
flush _count ++ ;
}
/ * *
/ * *
* @ param { Array < import ( './types.js' ) . EffectSignal > } effects
* @ param { Array < import ( './types.js' ) . EffectSignal > } effects
* @ returns { void }
* @ returns { void }
@ -476,16 +494,7 @@ export function execute_effect(signal) {
function flush _queued _effects ( effects ) {
function flush _queued _effects ( effects ) {
const length = effects . length ;
const length = effects . length ;
if ( length > 0 ) {
if ( length > 0 ) {
if ( flush _count > 100 ) {
infinite _loop _guard ( ) ;
throw new Error (
'ERR_SVELTE_TOO_MANY_UPDATES' +
( DEV
? ': Maximum update depth exceeded. This can happen when a reactive block or effect ' +
'repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops.'
: '' )
) ;
}
flush _count ++ ;
let i ;
let i ;
for ( i = 0 ; i < length ; i ++ ) {
for ( i = 0 ; i < length ; i ++ ) {
const signal = effects [ i ] ;
const signal = effects [ i ] ;
@ -606,13 +615,13 @@ export function flushSync(fn) {
const previous _queued _pre _and _render _effects = current _queued _pre _and _render _effects ;
const previous _queued _pre _and _render _effects = current _queued _pre _and _render _effects ;
const previous _queued _effects = current _queued _effects ;
const previous _queued _effects = current _queued _effects ;
try {
try {
infinite _loop _guard ( ) ;
/** @type {import('./types.js').EffectSignal[]} */
/** @type {import('./types.js').EffectSignal[]} */
const pre _and _render _effects = [ ] ;
const pre _and _render _effects = [ ] ;
/** @type {import('./types.js').EffectSignal[]} */
/** @type {import('./types.js').EffectSignal[]} */
const effects = [ ] ;
const effects = [ ] ;
current _scheduler _mode = FLUSH _SYNC ;
current _scheduler _mode = FLUSH _SYNC ;
flush _count = 0 ;
current _queued _pre _and _render _effects = pre _and _render _effects ;
current _queued _pre _and _render _effects = pre _and _render _effects ;
current _queued _effects = effects ;
current _queued _effects = effects ;
flush _queued _effects ( previous _queued _pre _and _render _effects ) ;
flush _queued _effects ( previous _queued _pre _and _render _effects ) ;
@ -626,6 +635,7 @@ export function flushSync(fn) {
if ( is _task _queued ) {
if ( is _task _queued ) {
process _task ( ) ;
process _task ( ) ;
}
}
flush _count = 0 ;
} finally {
} finally {
current _scheduler _mode = previous _scheduler _mode ;
current _scheduler _mode = previous _scheduler _mode ;
current _queued _pre _and _render _effects = previous _queued _pre _and _render _effects ;
current _queued _pre _and _render _effects = previous _queued _pre _and _render _effects ;
@ -814,6 +824,15 @@ export function get(signal) {
} else if ( signal !== current _dependencies [ current _dependencies . length - 1 ] ) {
} else if ( signal !== current _dependencies [ current _dependencies . length - 1 ] ) {
current _dependencies . push ( signal ) ;
current _dependencies . push ( signal ) ;
}
}
if (
current _untracked _writes !== null &&
current _effect !== null &&
( current _effect . f & CLEAN ) !== 0 &&
current _untracked _writes . includes ( signal )
) {
set _signal _status ( current _effect , DIRTY ) ;
schedule _effect ( current _effect , false ) ;
}
}
}
if ( ( flags & DERIVED ) !== 0 && is _signal _dirty ( signal ) ) {
if ( ( flags & DERIVED ) !== 0 && is _signal _dirty ( signal ) ) {
@ -1024,12 +1043,18 @@ export function set_signal_value(signal, value) {
is _runes ( component _context ) &&
is _runes ( component _context ) &&
current _effect !== null &&
current _effect !== null &&
current _effect . c === null &&
current _effect . c === null &&
( current _effect . f & CLEAN ) !== 0 &&
( current _effect . f & CLEAN ) !== 0
current _dependencies !== null &&
current _dependencies . includes ( signal )
) {
) {
set _signal _status ( current _effect , DIRTY ) ;
if ( current _dependencies !== null && current _dependencies . includes ( signal ) ) {
schedule _effect ( current _effect , false ) ;
set _signal _status ( current _effect , DIRTY ) ;
schedule _effect ( current _effect , false ) ;
} else {
if ( current _untracked _writes === null ) {
current _untracked _writes = [ signal ] ;
} else {
current _untracked _writes . push ( signal ) ;
}
}
}
}
mark _signal _consumers ( signal , DIRTY , true ) ;
mark _signal _consumers ( signal , DIRTY , true ) ;
// If we have afterUpdates locally on the component, but we're within a render effect
// If we have afterUpdates locally on the component, but we're within a render effect