breaking: delegated event handlers now yield effect updates

pull/11706/head
Dominic Gannaway 2 years ago
parent e6f8e95199
commit 7aa34b4eeb

@ -0,0 +1,5 @@
---
"svelte": patch
---
breaking: delegated event handlers now yield effect updates

@ -1,5 +1,6 @@
import { render_effect } from '../../reactivity/effects.js'; import { render_effect } from '../../reactivity/effects.js';
import { all_registered_events, root_event_handles } from '../../render.js'; import { all_registered_events, root_event_handles } from '../../render.js';
import { FLUSH_YIELD, current_scheduler_mode, set_schedule_mode } from '../../runtime.js';
import { define_property, is_array } from '../../utils.js'; import { define_property, is_array } from '../../utils.js';
import { hydrating } from '../hydration.js'; import { hydrating } from '../hydration.js';
@ -180,9 +181,12 @@ export function handle_event_propagation(handler_element, event) {
} }
} }
const previous_scheduler_mode = current_scheduler_mode;
try { try {
set_schedule_mode(FLUSH_YIELD);
next(current_target); next(current_target);
} finally { } finally {
set_schedule_mode(previous_scheduler_mode);
// @ts-expect-error is used above // @ts-expect-error is used above
event.__root = handler_element; event.__root = handler_element;
// @ts-expect-error is used above // @ts-expect-error is used above

@ -28,17 +28,27 @@ import { lifecycle_outside_component } from '../shared/errors.js';
const FLUSH_MICROTASK = 0; const FLUSH_MICROTASK = 0;
const FLUSH_SYNC = 1; const FLUSH_SYNC = 1;
export const FLUSH_YIELD = 2;
// Used for DEV time error handling // Used for DEV time error handling
/** @param {WeakSet<Error>} value */ /** @param {WeakSet<Error>} value */
const handled_errors = new WeakSet(); const handled_errors = new WeakSet();
// Used for controlling the flush of effects. // Used for controlling the flush of effects.
let current_scheduler_mode = FLUSH_MICROTASK; export let current_scheduler_mode = FLUSH_MICROTASK;
// Used for handling scheduling // Used for handling scheduling
let is_micro_task_queued = false; let is_micro_task_queued = false;
let is_yield_task_queued = false;
export let is_flushing_effect = false; export let is_flushing_effect = false;
export let is_destroying_effect = false; export let is_destroying_effect = false;
/**
* @param {number} value
*/
export function set_schedule_mode(value) {
current_scheduler_mode = value;
}
/** @param {boolean} value */ /** @param {boolean} value */
export function set_is_flushing_effect(value) { export function set_is_flushing_effect(value) {
is_flushing_effect = value; is_flushing_effect = value;
@ -521,13 +531,17 @@ function infinite_loop_guard() {
* @returns {void} * @returns {void}
*/ */
function flush_queued_root_effects(root_effects) { function flush_queued_root_effects(root_effects) {
const length = root_effects.length;
if (length === 0) {
return;
}
infinite_loop_guard(); infinite_loop_guard();
var previously_flushing_effect = is_flushing_effect; var previously_flushing_effect = is_flushing_effect;
is_flushing_effect = true; is_flushing_effect = true;
try { try {
for (var i = 0; i < root_effects.length; i++) { for (var i = 0; i < length; i++) {
var effect = root_effects[i]; var effect = root_effects[i];
// When working with custom elements, the root effects might not have a root // When working with custom elements, the root effects might not have a root
@ -565,6 +579,7 @@ function flush_queued_effects(effects) {
function process_microtask() { function process_microtask() {
is_micro_task_queued = false; is_micro_task_queued = false;
is_yield_task_queued = false;
if (flush_count > 101) { if (flush_count > 101) {
return; return;
} }
@ -576,6 +591,31 @@ function process_microtask() {
} }
} }
const yield_task =
typeof requestAnimationFrame === 'undefined' ? setTimeout : requestAnimationFrame;
async function process_yieldtask() {
// TODO: replace this with scheduler.yield when it becomes standard
await new Promise((fulfil) => {
yield_task(() => {
setTimeout(fulfil, 0);
});
// In case of background task
setTimeout(fulfil, 100);
});
is_yield_task_queued = false;
is_micro_task_queued = false;
if (flush_count > 101) {
return;
}
const previous_queued_root_effects = current_queued_root_effects;
current_queued_root_effects = [];
flush_queued_root_effects(previous_queued_root_effects);
if (!is_yield_task_queued) {
flush_count = 0;
}
}
/** /**
* @param {import('#client').Effect} signal * @param {import('#client').Effect} signal
* @returns {void} * @returns {void}
@ -586,6 +626,11 @@ export function schedule_effect(signal) {
is_micro_task_queued = true; is_micro_task_queued = true;
queueMicrotask(process_microtask); queueMicrotask(process_microtask);
} }
} else if (current_scheduler_mode === FLUSH_YIELD) {
if (!is_yield_task_queued) {
is_yield_task_queued = true;
process_yieldtask();
}
} }
var effect = signal; var effect = signal;

Loading…
Cancel
Save