@ -1,6 +1,6 @@
import { DEV } from 'esm-env' ;
import { subscribe _to _store } from '../../store/utils.js' ;
import { noop , run _all } from '../common.js' ;
import { noop , run , run _all } from '../common.js' ;
import {
array _prototype ,
get _descriptor ,
@ -104,18 +104,9 @@ export let current_block = null;
/** @type {import('./types.js').ComponentContext | null} */
export let current _component _context = null ;
export let is _ssr = false ;
export let updating _derived = false ;
/ * *
* @ param { boolean } ssr
* @ returns { void }
* /
export function set _is _ssr ( ssr ) {
is _ssr = ssr ;
}
/ * *
* @ param { null | import ( './types.js' ) . ComponentContext } context
* @ returns { boolean }
@ -147,14 +138,6 @@ export function batch_inspect(target, prop, receiver) {
} ;
}
/ * *
* @ param { null | import ( './types.js' ) . ComponentContext } context _stack _item
* @ returns { void }
* /
export function set _current _component _context ( context _stack _item ) {
current _component _context = context _stack _item ;
}
/ * *
* @ param { unknown } a
* @ param { unknown } b
@ -181,8 +164,6 @@ function create_source_signal(flags, value) {
f : flags ,
// value
v : value ,
// context: We can remove this if we get rid of beforeUpdate/afterUpdate
x : null ,
// this is for DEV only
inspect : new Set ( )
} ;
@ -195,9 +176,7 @@ function create_source_signal(flags, value) {
// flags
f : flags ,
// value
v : value ,
// context: We can remove this if we get rid of beforeUpdate/afterUpdate
x : null
v : value
} ;
}
@ -346,12 +325,6 @@ function execute_signal_fn(signal) {
current _skip _consumer = ! is _flushing _effect && ( flags & UNOWNED ) !== 0 ;
current _untracking = false ;
// Render effects are invoked when the UI is about to be updated - run beforeUpdate at that point
if ( is _render _effect && current _component _context ? . u != null ) {
// update_callbacks.execute()
current _component _context . u . e ( ) ;
}
try {
let res ;
if ( is _render _effect ) {
@ -924,7 +897,7 @@ export function store_set(store, value) {
* @ param { import ( './types.js' ) . StoreReferencesContainer } stores
* /
export function unsubscribe _on _destroy ( stores ) {
on D estroy( ( ) => {
on _d estroy( ( ) => {
let store _name ;
for ( store _name in stores ) {
const ref = stores [ store _name ] ;
@ -1150,7 +1123,7 @@ export function mark_subtree_inert(signal, inert, visited_blocks = new Set()) {
* @ returns { void }
* /
function mark _signal _consumers ( signal , to _status , force _schedule ) {
const runes = is _runes ( signal . x ) ;
const runes = is _runes ( null ) ;
const consumers = signal . c ;
if ( consumers !== null ) {
const length = consumers . length ;
@ -1192,7 +1165,7 @@ export function set_signal_value(signal, value) {
! current _untracking &&
! ignore _mutation _validation &&
current _consumer !== null &&
is _runes ( signal . x ) &&
is _runes ( null ) &&
( current _consumer . f & DERIVED ) !== 0
) {
throw new Error (
@ -1208,7 +1181,6 @@ export function set_signal_value(signal, value) {
( signal . f & SOURCE ) !== 0 &&
! ( /** @type {import('./types.js').EqualsFunctions} */ ( signal . e ) ( value , signal . v ) )
) {
const component _context = signal . x ;
signal . v = value ;
// If the current signal is running for the first time, it won't have any
// consumers as we only allocate and assign the consumers after the signal
@ -1219,7 +1191,7 @@ export function set_signal_value(signal, value) {
// $effect(() => x++)
//
if (
is _runes ( component _context ) &&
is _runes ( null ) &&
current _effect !== null &&
current _effect . c === null &&
( current _effect . f & CLEAN ) !== 0
@ -1236,19 +1208,6 @@ export function set_signal_value(signal, value) {
}
}
mark _signal _consumers ( signal , DIRTY , true ) ;
// If we have afterUpdates locally on the component, but we're within a render effect
// then we will need to manually invoke the beforeUpdate/afterUpdate logic.
// TODO: should we put this being a is_runes check and only run it in non-runes mode?
if ( current _effect === null && current _queued _pre _and _render _effects . length === 0 ) {
const update _callbacks = component _context ? . u ;
if ( update _callbacks != null ) {
run _all ( update _callbacks . b ) ;
const managed = managed _effect ( ( ) => {
destroy _signal ( managed ) ;
run _all ( update _callbacks . a ) ;
} ) ;
}
}
// @ts-expect-error
if ( DEV && signal . inspect ) {
@ -1299,7 +1258,7 @@ export function derived(init) {
create _computation _signal ( flags | CLEAN , UNINITIALIZED , current _block )
) ;
signal . i = init ;
signal. x = current _component _context ;
bind_signal _to _component _context ( signal ) ;
signal . e = default _equals ;
if ( current _consumer !== null ) {
push _reference ( current _consumer , signal ) ;
@ -1327,10 +1286,27 @@ export function derived_safe_equal(init) {
/*#__NO_SIDE_EFFECTS__*/
export function source ( initial _value ) {
const source = create _source _signal ( SOURCE | CLEAN , initial _value ) ;
source. x = current _component _context ;
bind_signal _to _component _context ( source ) ;
return source ;
}
/ * *
* This function binds a signal to the component context , so that we can fire
* beforeUpdate / afterUpdate callbacks at the correct time etc
* @ param { import ( './types.js' ) . Signal } signal
* /
function bind _signal _to _component _context ( signal ) {
if ( current _component _context === null || ! current _component _context . r ) return ;
const signals = current _component _context . d ;
if ( signals ) {
signals . push ( signal ) ;
} else {
current _component _context . d = [ signal ] ;
}
}
/ * *
* @ template V
* @ param { V } initial _value
@ -1883,18 +1859,11 @@ export function value_or_fallback(value, fallback) {
/ * *
* Schedules a callback to run immediately before the component is unmounted .
*
* Out of ` onMount ` , ` beforeUpdate ` , ` afterUpdate ` and ` onDestroy ` , this is the
* only one that runs inside a server - side component .
*
* https : //svelte.dev/docs/svelte#ondestroy
* @ param { ( ) => any } fn
* @ returns { void }
* /
export function onDestroy ( fn ) {
if ( ! is _ssr ) {
user _effect ( ( ) => ( ) => untrack ( fn ) ) ;
}
function on _destroy ( fn ) {
user _effect ( ( ) => ( ) => untrack ( fn ) ) ;
}
/ * *
@ -1914,6 +1883,8 @@ export function push(props, runes = false) {
m : false ,
// parent
p : current _component _context ,
// signals
d : null ,
// props
s : props ,
// runes
@ -1945,6 +1916,56 @@ export function pop(accessors) {
}
}
/ * *
* Invoke the getter of all signals associated with a component
* so they can be registered to the effect this function is called in .
* @ param { import ( './types.js' ) . ComponentContext } context
* /
function observe _all ( context ) {
if ( context . d ) {
for ( const signal of context . d ) get ( signal ) ;
}
const props = get _descriptors ( context . s ) ;
for ( const descriptor of Object . values ( props ) ) {
if ( descriptor . get ) descriptor . get ( ) ;
}
}
/ * *
* Legacy - mode only : Call ` onMount ` callbacks and set up ` beforeUpdate ` / ` afterUpdate ` effects
* /
export function init ( ) {
const context = /** @type {import('./types.js').ComponentContext} */ ( current _component _context ) ;
const callbacks = context . u ;
if ( ! callbacks ) return ;
// beforeUpdate
pre _effect ( ( ) => {
observe _all ( context ) ;
callbacks . b . forEach ( run ) ;
} ) ;
// onMount (must run before afterUpdate)
user _effect ( ( ) => {
const fns = untrack ( ( ) => callbacks . m . map ( run ) ) ;
return ( ) => {
for ( const fn of fns ) {
if ( typeof fn === 'function' ) {
fn ( ) ;
}
}
} ;
} ) ;
// afterUpdate
user _effect ( ( ) => {
observe _all ( context ) ;
callbacks . a . forEach ( run ) ;
} ) ;
}
/ * *
* @ param { any } value
* @ param { Set < any > } visited