Skip to content

Commit 9bbc332

Browse files
authored
chore: tidy up effect init (#10931)
* move signal init logic into create_effect * tidy up * call set_signal_status inside execute_effect * tidy up * unused import
1 parent 7adc14e commit 9bbc332

File tree

3 files changed

+105
-98
lines changed

3 files changed

+105
-98
lines changed

packages/svelte/src/internal/client/reactivity/effects.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import {
77
destroy_children,
88
execute_effect,
99
get,
10+
is_flushing_effect,
1011
remove_reactions,
1112
schedule_effect,
13+
set_is_flushing_effect,
1214
set_signal_status,
1315
untrack
1416
} from '../runtime.js';
@@ -20,7 +22,8 @@ import {
2022
PRE_EFFECT,
2123
DESTROYED,
2224
INERT,
23-
IS_ELSEIF
25+
IS_ELSEIF,
26+
EFFECT_RAN
2427
} from '../constants.js';
2528
import { set } from './sources.js';
2629
import { noop } from '../../common.js';
@@ -35,7 +38,7 @@ import { remove } from '../dom/reconciler.js';
3538
*/
3639
function create_effect(type, fn, sync, init = true) {
3740
/** @type {import('#client').Effect} */
38-
const signal = {
41+
const effect = {
3942
parent: current_effect,
4043
dom: null,
4144
deps: null,
@@ -51,22 +54,34 @@ function create_effect(type, fn, sync, init = true) {
5154
};
5255

5356
if (current_effect !== null) {
54-
signal.l = current_effect.l + 1;
57+
effect.l = current_effect.l + 1;
5558
}
5659

5760
if (current_reaction !== null) {
5861
if (current_reaction.effects === null) {
59-
current_reaction.effects = [signal];
62+
current_reaction.effects = [effect];
6063
} else {
61-
current_reaction.effects.push(signal);
64+
current_reaction.effects.push(effect);
6265
}
6366
}
6467

6568
if (init) {
66-
schedule_effect(signal, sync);
69+
if (sync) {
70+
const previously_flushing_effect = is_flushing_effect;
71+
72+
try {
73+
set_is_flushing_effect(true);
74+
execute_effect(effect);
75+
effect.f |= EFFECT_RAN;
76+
} finally {
77+
set_is_flushing_effect(previously_flushing_effect);
78+
}
79+
} else {
80+
schedule_effect(effect);
81+
}
6782
}
6883

69-
return signal;
84+
return effect;
7085
}
7186

7287
/**

packages/svelte/src/internal/client/reactivity/sources.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export function set(signal, value) {
135135
) {
136136
if (current_dependencies !== null && current_dependencies.includes(signal)) {
137137
set_signal_status(current_effect, DIRTY);
138-
schedule_effect(current_effect, false);
138+
schedule_effect(current_effect);
139139
} else {
140140
if (current_untracked_writes === null) {
141141
set_current_untracked_writes([signal]);

packages/svelte/src/internal/client/runtime.js

Lines changed: 82 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ const FLUSH_SYNC = 1;
3636
let current_scheduler_mode = FLUSH_MICROTASK;
3737
// Used for handling scheduling
3838
let is_micro_task_queued = false;
39-
let is_flushing_effect = false;
39+
export let is_flushing_effect = false;
40+
41+
/** @param {boolean} value */
42+
export function set_is_flushing_effect(value) {
43+
is_flushing_effect = value;
44+
}
45+
4046
// Used for $inspect
4147
export let is_batching_effect = false;
4248
let is_inspecting_signal = false;
@@ -210,9 +216,6 @@ export function check_dirtiness(reaction) {
210216
* @returns {V}
211217
*/
212218
export function execute_reaction_fn(signal) {
213-
const fn = signal.fn;
214-
const flags = signal.f;
215-
216219
const previous_dependencies = current_dependencies;
217220
const previous_dependencies_index = current_dependencies_index;
218221
const previous_untracked_writes = current_untracked_writes;
@@ -224,11 +227,11 @@ export function execute_reaction_fn(signal) {
224227
current_dependencies_index = 0;
225228
current_untracked_writes = null;
226229
current_reaction = signal;
227-
current_skip_reaction = !is_flushing_effect && (flags & UNOWNED) !== 0;
230+
current_skip_reaction = !is_flushing_effect && (signal.f & UNOWNED) !== 0;
228231
current_untracking = false;
229232

230233
try {
231-
let res = fn();
234+
let res = signal.fn();
232235
let dependencies = /** @type {import('./types.js').Value<unknown>[]} **/ (signal.deps);
233236
if (current_dependencies !== null) {
234237
let i;
@@ -373,33 +376,35 @@ export function destroy_children(signal) {
373376
}
374377

375378
/**
376-
* @param {import('./types.js').Effect} signal
379+
* @param {import('./types.js').Effect} effect
377380
* @returns {void}
378381
*/
379-
export function execute_effect(signal) {
380-
if ((signal.f & DESTROYED) !== 0) {
382+
export function execute_effect(effect) {
383+
if ((effect.f & DESTROYED) !== 0) {
381384
return;
382385
}
383386

384-
const previous_effect = current_effect;
385-
const previous_component_context = current_component_context;
387+
set_signal_status(effect, CLEAN);
386388

387-
const component_context = signal.ctx;
389+
var component_context = effect.ctx;
388390

389-
current_effect = signal;
391+
var previous_effect = current_effect;
392+
var previous_component_context = current_component_context;
393+
394+
current_effect = effect;
390395
current_component_context = component_context;
391396

392397
try {
393-
destroy_children(signal);
394-
signal.teardown?.();
395-
const teardown = execute_reaction_fn(signal);
396-
signal.teardown = typeof teardown === 'function' ? teardown : null;
398+
destroy_children(effect);
399+
effect.teardown?.();
400+
var teardown = execute_reaction_fn(effect);
401+
effect.teardown = typeof teardown === 'function' ? teardown : null;
397402
} finally {
398403
current_effect = previous_effect;
399404
current_component_context = previous_component_context;
400405
}
401406

402-
if ((signal.f & PRE_EFFECT) !== 0 && current_queued_pre_and_render_effects.length > 0) {
407+
if ((effect.f & PRE_EFFECT) !== 0 && current_queued_pre_and_render_effects.length > 0) {
403408
flush_local_pre_effects(component_context);
404409
}
405410
}
@@ -436,7 +441,6 @@ function flush_queued_effects(effects) {
436441

437442
if ((signal.f & (DESTROYED | INERT)) === 0) {
438443
if (check_dirtiness(signal)) {
439-
set_signal_status(signal, CLEAN);
440444
execute_effect(signal);
441445
}
442446
}
@@ -466,85 +470,73 @@ function process_microtask() {
466470

467471
/**
468472
* @param {import('./types.js').Effect} signal
469-
* @param {boolean} sync
470473
* @returns {void}
471474
*/
472-
export function schedule_effect(signal, sync) {
475+
export function schedule_effect(signal) {
473476
const flags = signal.f;
474-
if (sync) {
475-
const previously_flushing_effect = is_flushing_effect;
476-
try {
477-
is_flushing_effect = true;
478-
execute_effect(signal);
479-
set_signal_status(signal, CLEAN);
480-
} finally {
481-
is_flushing_effect = previously_flushing_effect;
477+
478+
if (current_scheduler_mode === FLUSH_MICROTASK) {
479+
if (!is_micro_task_queued) {
480+
is_micro_task_queued = true;
481+
queueMicrotask(process_microtask);
482482
}
483-
} else {
484-
if (current_scheduler_mode === FLUSH_MICROTASK) {
485-
if (!is_micro_task_queued) {
486-
is_micro_task_queued = true;
487-
queueMicrotask(process_microtask);
488-
}
483+
}
484+
485+
if ((flags & EFFECT) !== 0) {
486+
current_queued_effects.push(signal);
487+
// Prevent any nested user effects from potentially triggering
488+
// before this effect is scheduled. We know they will be destroyed
489+
// so we can make them inert to avoid having to find them in the
490+
// queue and remove them.
491+
if ((flags & MANAGED) === 0) {
492+
mark_subtree_children_inert(signal, true);
489493
}
490-
if ((flags & EFFECT) !== 0) {
491-
current_queued_effects.push(signal);
492-
// Prevent any nested user effects from potentially triggering
493-
// before this effect is scheduled. We know they will be destroyed
494-
// so we can make them inert to avoid having to find them in the
495-
// queue and remove them.
496-
if ((flags & MANAGED) === 0) {
497-
mark_subtree_children_inert(signal, true);
498-
}
499-
} else {
500-
// We need to ensure we insert the signal in the right topological order. In other words,
501-
// we need to evaluate where to insert the signal based off its level and whether or not it's
502-
// a pre-effect and within the same block. By checking the signals in the queue in reverse order
503-
// we can find the right place quickly. TODO: maybe opt to use a linked list rather than an array
504-
// for these operations.
505-
const length = current_queued_pre_and_render_effects.length;
506-
let should_append = length === 0;
507-
508-
if (!should_append) {
509-
const target_level = signal.l;
510-
const is_pre_effect = (flags & PRE_EFFECT) !== 0;
511-
let target_signal;
512-
let target_signal_level;
513-
let is_target_pre_effect;
514-
let i = length;
515-
while (true) {
516-
target_signal = current_queued_pre_and_render_effects[--i];
517-
target_signal_level = target_signal.l;
518-
if (target_signal_level <= target_level) {
519-
if (i + 1 === length) {
520-
should_append = true;
521-
} else {
522-
is_target_pre_effect = (target_signal.f & PRE_EFFECT) !== 0;
523-
if (
524-
target_signal_level < target_level ||
525-
target_signal !== signal ||
526-
(is_target_pre_effect && !is_pre_effect)
527-
) {
528-
i++;
529-
}
530-
current_queued_pre_and_render_effects.splice(i, 0, signal);
494+
} else {
495+
// We need to ensure we insert the signal in the right topological order. In other words,
496+
// we need to evaluate where to insert the signal based off its level and whether or not it's
497+
// a pre-effect and within the same block. By checking the signals in the queue in reverse order
498+
// we can find the right place quickly. TODO: maybe opt to use a linked list rather than an array
499+
// for these operations.
500+
const length = current_queued_pre_and_render_effects.length;
501+
let should_append = length === 0;
502+
503+
if (!should_append) {
504+
const target_level = signal.l;
505+
const is_pre_effect = (flags & PRE_EFFECT) !== 0;
506+
let target_signal;
507+
let target_signal_level;
508+
let is_target_pre_effect;
509+
let i = length;
510+
while (true) {
511+
target_signal = current_queued_pre_and_render_effects[--i];
512+
target_signal_level = target_signal.l;
513+
if (target_signal_level <= target_level) {
514+
if (i + 1 === length) {
515+
should_append = true;
516+
} else {
517+
is_target_pre_effect = (target_signal.f & PRE_EFFECT) !== 0;
518+
if (
519+
target_signal_level < target_level ||
520+
target_signal !== signal ||
521+
(is_target_pre_effect && !is_pre_effect)
522+
) {
523+
i++;
531524
}
532-
break;
533-
}
534-
if (i === 0) {
535-
current_queued_pre_and_render_effects.unshift(signal);
536-
break;
525+
current_queued_pre_and_render_effects.splice(i, 0, signal);
537526
}
527+
break;
528+
}
529+
if (i === 0) {
530+
current_queued_pre_and_render_effects.unshift(signal);
531+
break;
538532
}
539533
}
534+
}
540535

541-
if (should_append) {
542-
current_queued_pre_and_render_effects.push(signal);
543-
}
536+
if (should_append) {
537+
current_queued_pre_and_render_effects.push(signal);
544538
}
545539
}
546-
547-
signal.f |= EFFECT_RAN;
548540
}
549541

550542
/**
@@ -696,7 +688,7 @@ export function get(signal) {
696688
current_untracked_writes.includes(signal)
697689
) {
698690
set_signal_status(current_effect, DIRTY);
699-
schedule_effect(current_effect, false);
691+
schedule_effect(current_effect);
700692
}
701693
}
702694

@@ -772,7 +764,7 @@ export function mark_subtree_inert(signal, inert) {
772764
if (is_already_inert !== inert) {
773765
signal.f ^= INERT;
774766
if (!inert && (flags & CLEAN) === 0) {
775-
schedule_effect(signal, false);
767+
schedule_effect(signal);
776768
}
777769
}
778770

@@ -819,7 +811,7 @@ export function mark_reactions(signal, to_status, force_schedule) {
819811
force_schedule
820812
);
821813
} else {
822-
schedule_effect(/** @type {import('#client').Effect} */ (reaction), false);
814+
schedule_effect(/** @type {import('#client').Effect} */ (reaction));
823815
}
824816
}
825817
}
@@ -1075,7 +1067,7 @@ export function pop(component) {
10751067
if (effects !== null) {
10761068
context_stack_item.e = null;
10771069
for (let i = 0; i < effects.length; i++) {
1078-
schedule_effect(effects[i], false);
1070+
schedule_effect(effects[i]);
10791071
}
10801072
}
10811073
current_component_context = context_stack_item.p;

0 commit comments

Comments
 (0)