Skip to content

Commit 576dbb7

Browse files
authored
Merge branch 'main' into save-bytes
2 parents 94ddcad + 8759dad commit 576dbb7

File tree

1 file changed

+36
-57
lines changed

1 file changed

+36
-57
lines changed

src/diff/props.js

Lines changed: 36 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,17 @@ function setStyle(style, key, value) {
1313
}
1414
}
1515

16-
// A "virtual clock" to solve issues like https://github.com/preactjs/preact/issues/3927.
16+
// A logical clock to solve issues like https://github.com/preactjs/preact/issues/3927.
1717
// When the DOM performs an event it leaves micro-ticks in between bubbling up which means that
1818
// an event can trigger on a newly reated DOM-node while the event bubbles up.
1919
//
20-
// Originally inspired by Vue https://github.com/vuejs/core/blob/main/packages/runtime-dom/src/modules/events.ts#L90-L101,
21-
// but modified to use a virtual clock instead of Date.now() in case event handlers get attached and
22-
// events get dispatched during the same millisecond.
20+
// Originally inspired by Vue
21+
// (https://github.com/vuejs/core/blob/caeb8a68811a1b0f79/packages/runtime-dom/src/modules/events.ts#L90-L101),
22+
// but modified to use a logical clock instead of Date.now() in case event handlers get attached
23+
// and events get dispatched during the same millisecond.
2324
//
24-
// Odd values are reserved for event dispatch times, and even values are reserved for new
25-
// event handler attachment times.
26-
//
27-
// The clock is incremented before a new event is dispatched if the value is even
28-
// (i.e a new event handler was attached after the previous new event).
29-
// The clock is also incremented when a new event handler gets attached if the value is odd
30-
// (i.e. a new event was dispatched after the previous new event dispatch).
25+
// The clock is incremented after each new event dispatch. This allows 1 000 000 new events
26+
// per second for over 280 years before the value reaches Number.MAX_SAFE_INTEGER (2**53 - 1).
3127
let eventClock = 0;
3228

3329
/**
@@ -85,21 +81,12 @@ export function setProperty(dom, name, value, oldValue, isSvg) {
8581

8682
if (value) {
8783
if (!oldValue) {
88-
// If any new events were dispatched between this moment and the last time
89-
// an event handler was attached (i.e. `eventClock` is an odd number),
90-
// then increment `eventClock` first.
91-
//
92-
// The following line is a compacted version of:
93-
// if (eventClock % 2 === 1) {
94-
// eventClock += 1;
95-
// }
96-
// value._attached = eventClock;
97-
value._attached = eventClock += eventClock % 2;
84+
value._attached = eventClock;
9885
dom.addEventListener(
99-
name,
100-
useCapture ? eventProxyCapture : eventProxy,
101-
useCapture
102-
);
86+
name,
87+
useCapture ? eventProxyCapture : eventProxy,
88+
useCapture
89+
);
10390
} else {
10491
value._attached = oldValue._attached;
10592
}
@@ -156,40 +143,32 @@ export function setProperty(dom, name, value, oldValue, isSvg) {
156143
}
157144

158145
/**
159-
* Proxy an event to hooked event handlers
160-
* @param {PreactEvent} e The event object from the browser
146+
* Create an event proxy function.
147+
* @param {boolean} useCapture Is the event handler for the capture phase.
161148
* @private
162149
*/
163-
function eventProxy(e) {
164-
if (this._listeners) {
165-
const eventHandler = this._listeners[e.type + false];
166-
// If e._dispatched is set, it has to be an odd number, so !e._dispatched must be true if set.
167-
if (!e._dispatched) {
168-
// If any new event handlers were attached after the previous new event dispatch
169-
// (i.e. `eventClock` is an even number), then increment `eventClock` first.
170-
//
171-
// The following line is a compacted version of:
172-
// if (eventClock % 2 === 0) {
173-
// eventClock += 1;
174-
// }
175-
// e._dispatched = eventClock;
176-
e._dispatched = eventClock += (eventClock + 1) % 2;
177-
// When the _dispatched is smaller than the time when the targetted event handler was attached
178-
// we know we have bubbled up to an element that was added during patching the dom.
179-
} else if (e._dispatched < eventHandler._attached) {
180-
return;
150+
function createEventProxy(useCapture) {
151+
/**
152+
* Proxy an event to hooked event handlers
153+
* @param {PreactEvent} e The event object from the browser
154+
* @private
155+
*/
156+
return function (e) {
157+
if (this._listeners) {
158+
const eventHandler = this._listeners[e.type + useCapture];
159+
if (e._dispatched == null) {
160+
e._dispatched = eventClock++;
161+
162+
// When `e._dispatched` is smaller than the time when the targeted event
163+
// handler was attached we know we have bubbled up to an element that was added
164+
// during patching the DOM.
165+
} else if (e._dispatched < eventHandler._attached) {
166+
return;
167+
}
168+
return eventHandler(options.event ? options.event(e) : e);
181169
}
182-
return eventHandler(options.event ? options.event(e) : e);
183-
}
170+
};
184171
}
185172

186-
/**
187-
* Proxy an event to hooked event handlers
188-
* @param {PreactEvent} e The event object from the browser
189-
* @private
190-
*/
191-
function eventProxyCapture(e) {
192-
if (this._listeners) {
193-
return this._listeners[e.type + true](options.event ? options.event(e) : e);
194-
}
195-
}
173+
const eventProxy = createEventProxy(false);
174+
const eventProxyCapture = createEventProxy(true);

0 commit comments

Comments
 (0)