diff --git a/src/component.js b/src/component.js index 7f39862206..3eddccef41 100644 --- a/src/component.js +++ b/src/component.js @@ -2,6 +2,7 @@ import { assign } from './util'; import { diff, commitRoot } from './diff/index'; import options from './options'; import { Fragment } from './create-element'; +import { inEvent } from './diff/props'; /** * Base Component class. Provides `setState()` and `forceUpdate()`, which @@ -183,6 +184,18 @@ let rerenderQueue = []; let prevDebounce; +const microTick = + typeof Promise == 'function' + ? Promise.prototype.then.bind(Promise.resolve()) + : setTimeout; +function defer(cb) { + if (inEvent) { + setTimeout(cb); + } else { + microTick(cb); + } +} + /** * Enqueue a rerender of a component * @param {import('./internal').Component} c The component to rerender @@ -196,7 +209,7 @@ export function enqueueRender(c) { prevDebounce !== options.debounceRendering ) { prevDebounce = options.debounceRendering; - (prevDebounce || setTimeout)(process); + (prevDebounce || defer)(process); } } diff --git a/src/diff/props.js b/src/diff/props.js index 89e773ab89..00725566af 100644 --- a/src/diff/props.js +++ b/src/diff/props.js @@ -141,15 +141,29 @@ export function setProperty(dom, name, value, oldValue, isSvg) { } } +export let inEvent = false; + /** * Proxy an event to hooked event handlers * @param {Event} e The event object from the browser * @private */ function eventProxy(e) { - return this._listeners[e.type + false](options.event ? options.event(e) : e); + inEvent = true; + try { + return this._listeners[e.type + false]( + options.event ? options.event(e) : e + ); + } finally { + inEvent = false; + } } function eventProxyCapture(e) { - return this._listeners[e.type + true](options.event ? options.event(e) : e); + inEvent = true; + try { + return this._listeners[e.type + true](options.event ? options.event(e) : e); + } finally { + inEvent = false; + } }