diff --git a/src/diff/props.js b/src/diff/props.js index 31bbb5daf5..8ef0e273cf 100644 --- a/src/diff/props.js +++ b/src/diff/props.js @@ -1,6 +1,17 @@ import { IS_NON_DIMENSIONAL, NULL, SVG_NAMESPACE } from '../constants'; import options from '../options'; +// Per-instance unique key for event clock stamps. Each Preact copy on the page +// gets its own random suffix so that `_dispatched` / `_attached` properties on +// shared event objects and handler functions cannot collide across instances. +// ~1 in 60M collision odds - if you have that many praect versions on the page, +// you deserve some weird bugs. +// In 11 we can replace this with a +// Symbol +let _id = Math.random().toString(8), + EVENT_DISPATCHED = '__d' + _id, + EVENT_ATTACHED = '__a' + _id; + function setStyle(style, key, value) { if (key[0] == '-') { style.setProperty(key, value == NULL ? '' : value); @@ -79,14 +90,14 @@ export function setProperty(dom, name, value, oldValue, namespace) { if (value) { if (!oldValue) { - value._attached = eventClock; + value[EVENT_ATTACHED] = eventClock; dom.addEventListener( name, useCapture ? eventProxyCapture : eventProxy, useCapture ); } else { - value._attached = oldValue._attached; + value[EVENT_ATTACHED] = oldValue[EVENT_ATTACHED]; } } else { dom.removeEventListener( @@ -155,13 +166,13 @@ function createEventProxy(useCapture) { return function (e) { if (this._listeners) { const eventHandler = this._listeners[e.type + useCapture]; - if (e._dispatched == NULL) { - e._dispatched = eventClock++; + if (e[EVENT_DISPATCHED] == NULL) { + e[EVENT_DISPATCHED] = eventClock++; - // When `e._dispatched` is smaller than the time when the targeted event + // When `e[EVENT_DISPATCHED]` is smaller than the time when the targeted event // handler was attached we know we have bubbled up to an element that was added // during patching the DOM. - } else if (e._dispatched < eventHandler._attached) { + } else if (e[EVENT_DISPATCHED] < eventHandler[EVENT_ATTACHED]) { return; } return eventHandler(options.event ? options.event(e) : e); diff --git a/src/internal.d.ts b/src/internal.d.ts index 481d4b12d8..58e0d54d62 100644 --- a/src/internal.d.ts +++ b/src/internal.d.ts @@ -125,7 +125,9 @@ export interface PreactElement extends preact.ContainerNode { } export interface PreactEvent extends Event { - _dispatched?: number; + // Keyed by a per-instance unique string (e.g. `__dXXXXX`) so that + // multiple Preact copies on the same page don't share event clock stamps. + [key: string]: any; } // We use the `current` property to differentiate between the two kinds of Refs so