chore: ensure binding events are without context (#14194)

* chore: ensure binding events are without context

* doh
pull/14184/head
Dominic Gannaway 1 week ago committed by GitHub
parent 5ce1159ec3
commit 7eb4cb91d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,6 +1,6 @@
import { DEV } from 'esm-env';
import { render_effect, teardown } from '../../../reactivity/effects.js';
import { listen_to_event_and_reset_event } from './shared.js';
import { listen_to_event_and_reset_event, without_reactive_context } from './shared.js';
import * as e from '../../../errors.js';
import { is } from '../../../proxy.js';
import { queue_micro_task } from '../../task.js';

@ -1,4 +1,10 @@
import { teardown } from '../../../reactivity/effects.js';
import {
active_effect,
active_reaction,
set_active_effect,
set_active_reaction
} from '../../../runtime.js';
import { add_form_reset_listener } from '../misc.js';
/**
@ -25,6 +31,23 @@ export function listen(target, events, handler, call_handler_immediately = true)
});
}
/**
* @template T
* @param {() => T} fn
*/
export function without_reactive_context(fn) {
var previous_reaction = active_reaction;
var previous_effect = active_effect;
set_active_reaction(null);
set_active_effect(null);
try {
return fn();
} finally {
set_active_reaction(previous_reaction);
set_active_effect(previous_effect);
}
}
/**
* Listen to the given event, and then instantiate a global form reset listener if not already done,
* to notify all bindings when the form is reset
@ -34,7 +57,7 @@ export function listen(target, events, handler, call_handler_immediately = true)
* @param {() => void} [on_reset]
*/
export function listen_to_event_and_reset_event(element, event, handler, on_reset = handler) {
element.addEventListener(event, handler);
element.addEventListener(event, () => without_reactive_context(handler));
// @ts-expect-error
const prev = element.__on_r;
if (prev) {

@ -1,5 +1,5 @@
import { effect, render_effect, teardown } from '../../../reactivity/effects.js';
import { listen } from './shared.js';
import { listen, without_reactive_context } from './shared.js';
/**
* @param {'x' | 'y'} type
@ -10,13 +10,14 @@ import { listen } from './shared.js';
export function bind_window_scroll(type, get, set = get) {
var is_scrolling_x = type === 'x';
var target_handler = () => {
var target_handler = () =>
without_reactive_context(() => {
scrolling = true;
clearTimeout(timeout);
timeout = setTimeout(clear, 100); // TODO use scrollend event if supported (or when supported everywhere?)
set(window[is_scrolling_x ? 'scrollX' : 'scrollY']);
};
});
addEventListener('scroll', target_handler, {
passive: true
@ -61,5 +62,5 @@ export function bind_window_scroll(type, get, set = get) {
* @param {(size: number) => void} set
*/
export function bind_window_size(type, set) {
listen(window, ['resize'], () => set(window[type]));
listen(window, ['resize'], () => without_reactive_context(() => set(window[type])));
}

@ -11,6 +11,7 @@ import {
set_active_effect,
set_active_reaction
} from '../../runtime.js';
import { without_reactive_context } from './bindings/shared.js';
/** @type {Set<string>} */
export const all_registered_events = new Set();
@ -61,17 +62,9 @@ export function create_event(event_name, dom, handler, options) {
handle_event_propagation.call(dom, event);
}
if (!event.cancelBubble) {
var previous_reaction = active_reaction;
var previous_effect = active_effect;
set_active_reaction(null);
set_active_effect(null);
try {
return without_reactive_context(() => {
return handler.call(this, event);
} finally {
set_active_reaction(previous_reaction);
set_active_effect(previous_effect);
}
});
}
}

Loading…
Cancel
Save