1
1
import { DEV } from 'esm-env' ;
2
2
import { subscribe_to_store } from '../../store/utils.js' ;
3
- import { noop , run_all } from '../common.js' ;
3
+ import { noop , run , run_all } from '../common.js' ;
4
4
import {
5
5
array_prototype ,
6
6
get_descriptor ,
@@ -104,18 +104,9 @@ export let current_block = null;
104
104
105
105
/** @type {import('./types.js').ComponentContext | null } */
106
106
export let current_component_context = null ;
107
- export let is_ssr = false ;
108
107
109
108
export let updating_derived = false ;
110
109
111
- /**
112
- * @param {boolean } ssr
113
- * @returns {void }
114
- */
115
- export function set_is_ssr ( ssr ) {
116
- is_ssr = ssr ;
117
- }
118
-
119
110
/**
120
111
* @param {null | import('./types.js').ComponentContext } context
121
112
* @returns {boolean }
@@ -147,14 +138,6 @@ export function batch_inspect(target, prop, receiver) {
147
138
} ;
148
139
}
149
140
150
- /**
151
- * @param {null | import('./types.js').ComponentContext } context_stack_item
152
- * @returns {void }
153
- */
154
- export function set_current_component_context ( context_stack_item ) {
155
- current_component_context = context_stack_item ;
156
- }
157
-
158
141
/**
159
142
* @param {unknown } a
160
143
* @param {unknown } b
@@ -181,8 +164,6 @@ function create_source_signal(flags, value) {
181
164
f : flags ,
182
165
// value
183
166
v : value ,
184
- // context: We can remove this if we get rid of beforeUpdate/afterUpdate
185
- x : null ,
186
167
// this is for DEV only
187
168
inspect : new Set ( )
188
169
} ;
@@ -195,9 +176,7 @@ function create_source_signal(flags, value) {
195
176
// flags
196
177
f : flags ,
197
178
// value
198
- v : value ,
199
- // context: We can remove this if we get rid of beforeUpdate/afterUpdate
200
- x : null
179
+ v : value
201
180
} ;
202
181
}
203
182
@@ -346,12 +325,6 @@ function execute_signal_fn(signal) {
346
325
current_skip_consumer = ! is_flushing_effect && ( flags & UNOWNED ) !== 0 ;
347
326
current_untracking = false ;
348
327
349
- // Render effects are invoked when the UI is about to be updated - run beforeUpdate at that point
350
- if ( is_render_effect && current_component_context ?. u != null ) {
351
- // update_callbacks.execute()
352
- current_component_context . u . e ( ) ;
353
- }
354
-
355
328
try {
356
329
let res ;
357
330
if ( is_render_effect ) {
@@ -924,7 +897,7 @@ export function store_set(store, value) {
924
897
* @param {import('./types.js').StoreReferencesContainer } stores
925
898
*/
926
899
export function unsubscribe_on_destroy ( stores ) {
927
- onDestroy ( ( ) => {
900
+ on_destroy ( ( ) => {
928
901
let store_name ;
929
902
for ( store_name in stores ) {
930
903
const ref = stores [ store_name ] ;
@@ -1150,7 +1123,7 @@ export function mark_subtree_inert(signal, inert, visited_blocks = new Set()) {
1150
1123
* @returns {void }
1151
1124
*/
1152
1125
function mark_signal_consumers ( signal , to_status , force_schedule ) {
1153
- const runes = is_runes ( signal . x ) ;
1126
+ const runes = is_runes ( null ) ;
1154
1127
const consumers = signal . c ;
1155
1128
if ( consumers !== null ) {
1156
1129
const length = consumers . length ;
@@ -1192,7 +1165,7 @@ export function set_signal_value(signal, value) {
1192
1165
! current_untracking &&
1193
1166
! ignore_mutation_validation &&
1194
1167
current_consumer !== null &&
1195
- is_runes ( signal . x ) &&
1168
+ is_runes ( null ) &&
1196
1169
( current_consumer . f & DERIVED ) !== 0
1197
1170
) {
1198
1171
throw new Error (
@@ -1208,7 +1181,6 @@ export function set_signal_value(signal, value) {
1208
1181
( signal . f & SOURCE ) !== 0 &&
1209
1182
! ( /** @type {import('./types.js').EqualsFunctions } */ ( signal . e ) ( value , signal . v ) )
1210
1183
) {
1211
- const component_context = signal . x ;
1212
1184
signal . v = value ;
1213
1185
// If the current signal is running for the first time, it won't have any
1214
1186
// consumers as we only allocate and assign the consumers after the signal
@@ -1219,7 +1191,7 @@ export function set_signal_value(signal, value) {
1219
1191
// $effect(() => x++)
1220
1192
//
1221
1193
if (
1222
- is_runes ( component_context ) &&
1194
+ is_runes ( null ) &&
1223
1195
current_effect !== null &&
1224
1196
current_effect . c === null &&
1225
1197
( current_effect . f & CLEAN ) !== 0
@@ -1236,19 +1208,6 @@ export function set_signal_value(signal, value) {
1236
1208
}
1237
1209
}
1238
1210
mark_signal_consumers ( signal , DIRTY , true ) ;
1239
- // If we have afterUpdates locally on the component, but we're within a render effect
1240
- // then we will need to manually invoke the beforeUpdate/afterUpdate logic.
1241
- // TODO: should we put this being a is_runes check and only run it in non-runes mode?
1242
- if ( current_effect === null && current_queued_pre_and_render_effects . length === 0 ) {
1243
- const update_callbacks = component_context ?. u ;
1244
- if ( update_callbacks != null ) {
1245
- run_all ( update_callbacks . b ) ;
1246
- const managed = managed_effect ( ( ) => {
1247
- destroy_signal ( managed ) ;
1248
- run_all ( update_callbacks . a ) ;
1249
- } ) ;
1250
- }
1251
- }
1252
1211
1253
1212
// @ts -expect-error
1254
1213
if ( DEV && signal . inspect ) {
@@ -1299,7 +1258,7 @@ export function derived(init) {
1299
1258
create_computation_signal ( flags | CLEAN , UNINITIALIZED , current_block )
1300
1259
) ;
1301
1260
signal . i = init ;
1302
- signal . x = current_component_context ;
1261
+ bind_signal_to_component_context ( signal ) ;
1303
1262
signal . e = default_equals ;
1304
1263
if ( current_consumer !== null ) {
1305
1264
push_reference ( current_consumer , signal ) ;
@@ -1327,10 +1286,27 @@ export function derived_safe_equal(init) {
1327
1286
/*#__NO_SIDE_EFFECTS__*/
1328
1287
export function source ( initial_value ) {
1329
1288
const source = create_source_signal ( SOURCE | CLEAN , initial_value ) ;
1330
- source . x = current_component_context ;
1289
+ bind_signal_to_component_context ( source ) ;
1331
1290
return source ;
1332
1291
}
1333
1292
1293
+ /**
1294
+ * This function binds a signal to the component context, so that we can fire
1295
+ * beforeUpdate/afterUpdate callbacks at the correct time etc
1296
+ * @param {import('./types.js').Signal } signal
1297
+ */
1298
+ function bind_signal_to_component_context ( signal ) {
1299
+ if ( current_component_context === null || ! current_component_context . r ) return ;
1300
+
1301
+ const signals = current_component_context . d ;
1302
+
1303
+ if ( signals ) {
1304
+ signals . push ( signal ) ;
1305
+ } else {
1306
+ current_component_context . d = [ signal ] ;
1307
+ }
1308
+ }
1309
+
1334
1310
/**
1335
1311
* @template V
1336
1312
* @param {V } initial_value
@@ -1883,18 +1859,11 @@ export function value_or_fallback(value, fallback) {
1883
1859
1884
1860
/**
1885
1861
* Schedules a callback to run immediately before the component is unmounted.
1886
- *
1887
- * Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the
1888
- * only one that runs inside a server-side component.
1889
- *
1890
- * https://svelte.dev/docs/svelte#ondestroy
1891
1862
* @param {() => any } fn
1892
1863
* @returns {void }
1893
1864
*/
1894
- export function onDestroy ( fn ) {
1895
- if ( ! is_ssr ) {
1896
- user_effect ( ( ) => ( ) => untrack ( fn ) ) ;
1897
- }
1865
+ function on_destroy ( fn ) {
1866
+ user_effect ( ( ) => ( ) => untrack ( fn ) ) ;
1898
1867
}
1899
1868
1900
1869
/**
@@ -1914,6 +1883,8 @@ export function push(props, runes = false) {
1914
1883
m : false ,
1915
1884
// parent
1916
1885
p : current_component_context ,
1886
+ // signals
1887
+ d : null ,
1917
1888
// props
1918
1889
s : props ,
1919
1890
// runes
@@ -1945,6 +1916,56 @@ export function pop(accessors) {
1945
1916
}
1946
1917
}
1947
1918
1919
+ /**
1920
+ * Invoke the getter of all signals associated with a component
1921
+ * so they can be registered to the effect this function is called in.
1922
+ * @param {import('./types.js').ComponentContext } context
1923
+ */
1924
+ function observe_all ( context ) {
1925
+ if ( context . d ) {
1926
+ for ( const signal of context . d ) get ( signal ) ;
1927
+ }
1928
+
1929
+ const props = get_descriptors ( context . s ) ;
1930
+ for ( const descriptor of Object . values ( props ) ) {
1931
+ if ( descriptor . get ) descriptor . get ( ) ;
1932
+ }
1933
+ }
1934
+
1935
+ /**
1936
+ * Legacy-mode only: Call `onMount` callbacks and set up `beforeUpdate`/`afterUpdate` effects
1937
+ */
1938
+ export function init ( ) {
1939
+ const context = /** @type {import('./types.js').ComponentContext } */ ( current_component_context ) ;
1940
+ const callbacks = context . u ;
1941
+
1942
+ if ( ! callbacks ) return ;
1943
+
1944
+ // beforeUpdate
1945
+ pre_effect ( ( ) => {
1946
+ observe_all ( context ) ;
1947
+ callbacks . b . forEach ( run ) ;
1948
+ } ) ;
1949
+
1950
+ // onMount (must run before afterUpdate)
1951
+ user_effect ( ( ) => {
1952
+ const fns = untrack ( ( ) => callbacks . m . map ( run ) ) ;
1953
+ return ( ) => {
1954
+ for ( const fn of fns ) {
1955
+ if ( typeof fn === 'function' ) {
1956
+ fn ( ) ;
1957
+ }
1958
+ }
1959
+ } ;
1960
+ } ) ;
1961
+
1962
+ // afterUpdate
1963
+ user_effect ( ( ) => {
1964
+ observe_all ( context ) ;
1965
+ callbacks . a . forEach ( run ) ;
1966
+ } ) ;
1967
+ }
1968
+
1948
1969
/**
1949
1970
* @param {any } value
1950
1971
* @param {Set<any> } visited
0 commit comments