@ -9,7 +9,6 @@ import {
} from './reactivity/effects.js' ;
import {
EFFECT ,
RENDER _EFFECT ,
DIRTY ,
MAYBE _DIRTY ,
CLEAN ,
@ -41,28 +40,19 @@ import {
} from './context.js' ;
import { is _firefox } from './dom/operations.js' ;
const FLUSH _MICROTASK = 0 ;
const FLUSH _SYNC = 1 ;
// Used for DEV time error handling
/** @param {WeakSet<Error>} value */
const handled _errors = new WeakSet ( ) ;
let is _throwing _error = false ;
// Used for controlling the flush of effects.
let scheduler _mode = FLUSH _MICROTASK ;
// Used for handling scheduling
let is _micro _task _queued = false ;
let is _flushing = false ;
/** @type {Effect | null} */
let last _scheduled _effect = null ;
export let is _flushing _effect = false ;
export let is _destroying _effect = false ;
let is _updating _effect = false ;
/** @param {boolean} value */
export function set _is _flushing _effect ( value ) {
is _flushing _effect = value ;
}
export let is _destroying _effect = false ;
/** @param {boolean} value */
export function set _is _destroying _effect ( value ) {
@ -74,7 +64,6 @@ export function set_is_destroying_effect(value) {
/** @type {Effect[]} */
let queued _root _effects = [ ] ;
let flush _count = 0 ;
/** @type {Effect[]} Stack of effects, dev only */
let dev _effect _stack = [ ] ;
// Handle signal reactivity tree dependencies and reactions
@ -410,10 +399,9 @@ export function update_reaction(reaction) {
new _deps = /** @type {null | Value[]} */ ( null ) ;
skipped _deps = 0 ;
untracked _writes = null ;
active _reaction = ( flags & ( BRANCH _EFFECT | ROOT _EFFECT ) ) === 0 ? reaction : null ;
skip _reaction =
( flags & UNOWNED ) !== 0 &&
( ! is _flushing _effect || previous _reaction === null || previous _untracking ) ;
( flags & UNOWNED ) !== 0 && ( untracking || ! is _updating _effect || active _reaction === null ) ;
active _reaction = ( flags & ( BRANCH _EFFECT | ROOT _EFFECT ) ) === 0 ? reaction : null ;
derived _sources = null ;
set _component _context ( reaction . ctx ) ;
@ -559,8 +547,10 @@ export function update_effect(effect) {
var previous _effect = active _effect ;
var previous _component _context = component _context ;
var was _updating _effect = is _updating _effect ;
active _effect = effect ;
is _updating _effect = true ;
if ( DEV ) {
var previous _component _fn = dev _current _component _function ;
@ -602,6 +592,7 @@ export function update_effect(effect) {
} catch ( error ) {
handle _error ( error , effect , previous _effect , previous _component _context || effect . ctx ) ;
} finally {
is _updating _effect = was _updating _effect ;
active _effect = previous _effect ;
if ( DEV ) {
@ -620,69 +611,70 @@ function log_effect_stack() {
}
function infinite _loop _guard ( ) {
if ( flush _count > 1000 ) {
flush _count = 0 ;
try {
e . effect _update _depth _exceeded ( ) ;
} catch ( error ) {
try {
e . effect _update _depth _exceeded ( ) ;
} catch ( error ) {
if ( DEV ) {
// stack is garbage, ignore. Instead add a console.error message.
define _property ( error , 'stack' , {
value : ''
} ) ;
}
// Try and handle the error so it can be caught at a boundary, that's
// if there's an effect available from when it was last scheduled
if ( last _scheduled _effect !== null ) {
if ( DEV ) {
// stack is garbage, ignore. Instead add a console.error message.
define _property ( error , 'stack' , {
value : ''
} ) ;
}
// Try and handle the error so it can be caught at a boundary, that's
// if there's an effect available from when it was last scheduled
if ( last _scheduled _effect !== null ) {
if ( DEV ) {
try {
handle _error ( error , last _scheduled _effect , null , null ) ;
} catch ( e ) {
// Only log the effect stack if the error is re-thrown
log _effect _stack ( ) ;
throw e ;
}
} else {
try {
handle _error ( error , last _scheduled _effect , null , null ) ;
}
} else {
if ( DEV ) {
} catch ( e ) {
// Only log the effect stack if the error is re-thrown
log _effect _stack ( ) ;
throw e ;
}
throw error ;
} else {
handle _error ( error , last _scheduled _effect , null , null ) ;
}
} else {
if ( DEV ) {
log _effect _stack ( ) ;
}
throw error ;
}
}
flush _count ++ ;
}
/ * *
* @ param { Array < Effect > } root _effects
* @ returns { void }
* /
function flush _queued _root _effects ( root _effects ) {
var length = root _effects . length ;
if ( length === 0 ) {
return ;
}
infinite _loop _guard ( ) ;
var previously _flushing _effect = is _flushing _effect ;
is _flushing _effect = true ;
function flush _queued _root _effects ( ) {
try {
for ( var i = 0 ; i < length ; i ++ ) {
var effect = root _effects [ i ] ;
var flush _count = 0 ;
if ( ( effect . f & CLEAN ) === 0 ) {
effect . f ^= CLEAN ;
while ( queued _root _effects . length > 0 ) {
if ( flush _count ++ > 1000 ) {
infinite _loop _guard ( ) ;
}
var collected _effects = process _effects ( effect ) ;
flush _queued _effects ( collected _effects ) ;
var root _effects = queued _root _effects ;
var length = root _effects . length ;
queued _root _effects = [ ] ;
for ( var i = 0 ; i < length ; i ++ ) {
var root = root _effects [ i ] ;
if ( ( root . f & CLEAN ) === 0 ) {
root . f ^= CLEAN ;
}
var collected _effects = process _effects ( root ) ;
flush _queued _effects ( collected _effects ) ;
}
}
} finally {
is _flushing _effect = previously _flushing _effect ;
is _flushing = false ;
last _scheduled _effect = null ;
if ( DEV ) {
dev _effect _stack = [ ] ;
}
}
}
@ -724,39 +716,17 @@ function flush_queued_effects(effects) {
}
}
function process _deferred ( ) {
is _micro _task _queued = false ;
if ( flush _count > 1001 ) {
return ;
}
const previous _queued _root _effects = queued _root _effects ;
queued _root _effects = [ ] ;
flush _queued _root _effects ( previous _queued _root _effects ) ;
if ( ! is _micro _task _queued ) {
flush _count = 0 ;
last _scheduled _effect = null ;
if ( DEV ) {
dev _effect _stack = [ ] ;
}
}
}
/ * *
* @ param { Effect } signal
* @ returns { void }
* /
export function schedule _effect ( signal ) {
if ( scheduler _mode === FLUSH _MICROTASK ) {
if ( ! is _micro _task _queued ) {
is _micro _task _queued = true ;
queueMicrotask ( process _deferred ) ;
}
if ( ! is _flushing ) {
is _flushing = true ;
queueMicrotask ( flush _queued _root _effects ) ;
}
last _scheduled _effect = signal ;
var effect = signal ;
var effect = ( last _scheduled _effect = signal ) ;
while ( effect . parent !== null ) {
effect = effect . parent ;
@ -846,42 +816,30 @@ function process_effects(effect) {
}
/ * *
* Internal version of ` flushSync ` with the option to not flush previous effects .
* Returns the result of the passed function , if given .
* @ param { ( ) => any } [ fn ]
* @ returns { any }
* Synchronously flush any pending updates .
* Returns void if no callback is provided , otherwise returns the result of calling the callback .
* @ template [ T = void ]
* @ param { ( ( ) => T ) | undefined } [ fn ]
* @ returns { T }
* /
export function flush _sync ( fn ) {
var previous _scheduler _mode = scheduler _mode ;
var previous _queued _root _effects = queued _root _effects ;
try {
infinite _loop _guard ( ) ;
export function flushSync ( fn ) {
var result ;
scheduler _mode = FLUSH _SYNC ;
queued_root _effects = [ ] ;
is_micro _task _queued = false ;
flush _queued _root _effects ( previous _queued _root _effects ) ;
if ( fn ) {
is _flushing = true ;
flush _queued _root _effects ( ) ;
result = fn ( ) ;
}
var result = fn ? . ( ) ;
flush _tasks ( ) ;
while ( queued _root _effects . length > 0 ) {
is _flushing = true ;
flush _queued _root _effects ( ) ;
flush _tasks ( ) ;
if ( queued _root _effects . length > 0 ) {
flush _sync ( ) ;
}
flush _count = 0 ;
last _scheduled _effect = null ;
if ( DEV ) {
dev _effect _stack = [ ] ;
}
return result ;
} finally {
scheduler _mode = previous _scheduler _mode ;
queued _root _effects = previous _queued _root _effects ;
}
return /** @type {T} */ ( result ) ;
}
/ * *
@ -890,9 +848,9 @@ export function flush_sync(fn) {
* /
export async function tick ( ) {
await Promise . resolve ( ) ;
// By calling flush _s ync we guarantee that any pending state changes are applied after one tick.
// By calling flush S ync we guarantee that any pending state changes are applied after one tick.
// TODO look into whether we can make flushing subsequent updates synchronously in the future.
flush _s ync( ) ;
flush S ync( ) ;
}
/ * *