Skip to content

Commit a159a32

Browse files
committed
lib: implement passive listener preventDefault behavior per spec
Implement Web API spec-compliant behavior for passive event listeners where preventDefault() and returnValue setting are ignored during passive listener execution. - Add kInPassiveListener symbol to track passive listener state - Modify preventDefault() to ignore calls during passive listener execution - Add returnValue setter that respects passive listener state - Set/clear passive flag around listener invocation in dispatchEvent Fixes WPT test cases that were previously failing in AddEventListenerOptions-passive.any.js and satisfies expected behaviors: - preventDefault should be ignored if-and-only-if the passive option is true - returnValue should be ignored if-and-only-if the passive option is true - passive behavior of one listener should be unaffected by other listeners Refs: https://dom.spec.whatwg.org/#dom-event-preventdefault
1 parent 2e5c8df commit a159a32

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

lib/internal/event_target.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ const { now } = require('internal/perf/utils');
7676

7777
const kType = Symbol('type');
7878
const kDetail = Symbol('detail');
79+
const kInPassiveListener = Symbol('kInPassiveListener');
7980

8081
const isTrustedSet = new SafeWeakSet();
8182
const isTrusted = ObjectGetOwnPropertyDescriptor({
@@ -178,6 +179,9 @@ class Event {
178179
preventDefault() {
179180
if (!isEvent(this))
180181
throw new ERR_INVALID_THIS('Event');
182+
if (this[kInPassiveListener]) {
183+
return;
184+
}
181185
this.#defaultPrevented = true;
182186
}
183187

@@ -266,6 +270,21 @@ class Event {
266270
return !this.#cancelable || !this.#defaultPrevented;
267271
}
268272

273+
/**
274+
* @type {boolean}
275+
*/
276+
set returnValue(value) {
277+
if (!isEvent(this))
278+
throw new ERR_INVALID_THIS('Event');
279+
280+
if (!value) {
281+
if (this[kInPassiveListener]) {
282+
return;
283+
}
284+
this.#defaultPrevented = true;
285+
}
286+
}
287+
269288
/**
270289
* @type {boolean}
271290
*/
@@ -760,7 +779,6 @@ class EventTarget {
760779
throw new ERR_EVENT_RECURSION(event.type);
761780

762781
this[kHybridDispatch](event, event.type, event);
763-
764782
return event.defaultPrevented !== true;
765783
}
766784

@@ -824,7 +842,13 @@ class EventTarget {
824842
handler.callback.deref() : handler.callback;
825843
let result;
826844
if (callback) {
845+
if (handler.passive && !handler.isNodeStyleListener) {
846+
arg[kInPassiveListener] = true;
847+
}
827848
result = FunctionPrototypeCall(callback, this, arg);
849+
if (handler.passive && !handler.isNodeStyleListener) {
850+
arg[kInPassiveListener] = false;
851+
}
828852
if (!handler.isNodeStyleListener) {
829853
arg[kIsBeingDispatched] = false;
830854
}

0 commit comments

Comments
 (0)