|
|
|
|
@ -159,12 +159,15 @@ export function delegate(events) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// used to store the reference to the currently propagated event
|
|
|
|
|
// to prevent garbage collection between microtasks in Firefox
|
|
|
|
|
// to prevent garbage collection between microtasks in Firefox (<= 141)
|
|
|
|
|
// If the event object is GCed too early, the expando __root property
|
|
|
|
|
// set on the event object is lost, causing the event delegation
|
|
|
|
|
// to process the event twice
|
|
|
|
|
let last_propagated_event = null;
|
|
|
|
|
|
|
|
|
|
// whether a task is already queued to clear `last_propagated_event`
|
|
|
|
|
let last_propagated_event_clear_scheduled = false;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @this {EventTarget}
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
@ -179,6 +182,21 @@ export function handle_event_propagation(event) {
|
|
|
|
|
|
|
|
|
|
last_propagated_event = event;
|
|
|
|
|
|
|
|
|
|
// The reference is only needed while the event can still reach another
|
|
|
|
|
// delegated root, i.e. during the current (synchronous) dispatch and its
|
|
|
|
|
// microtask checkpoints. Clearing it in a later task preserves the
|
|
|
|
|
// Firefox workaround while making sure the slot doesn't retain the last
|
|
|
|
|
// event forever — through `event.target` it would otherwise keep the
|
|
|
|
|
// entire detached subtree of whatever the user last clicked in alive
|
|
|
|
|
// until the next delegated event happens to arrive.
|
|
|
|
|
if (!last_propagated_event_clear_scheduled) {
|
|
|
|
|
last_propagated_event_clear_scheduled = true;
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
last_propagated_event_clear_scheduled = false;
|
|
|
|
|
last_propagated_event = null;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// composedPath contains list of nodes the event has propagated through.
|
|
|
|
|
// We check `event_symbol` to skip all nodes below it in case this is a
|
|
|
|
|
// parent of the `event_symbol` node, which indicates that there's nested
|
|
|
|
|
|