Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
23468fd
http2: fix allowHttp1+Upgrade, broken by shouldUpgradeCallback
pimterry Sep 20, 2025
fe492c7
process: fix hrtime fast call signatures
Renegade334 Jul 13, 2025
81548ab
wasi: fix WasiFunction fast call signature
Renegade334 Jul 13, 2025
cee3622
timers: fix binding fast call signatures
Renegade334 Jul 13, 2025
78efd1b
benchmark: update num to n in dgram offset-length
brunocroh Sep 1, 2025
af0a8ba
benchmark: adjust dgram offset-length len values
brunocroh Sep 1, 2025
af3a59d
test: verify tracing channel doesn't swallow unhandledRejection
Flarna Sep 24, 2025
4e8d99f
benchmark: update num to n in dgram offset-length
brunocroh Sep 12, 2025
6764ce8
benchmark: update count to n in permission startup
brunocroh Sep 12, 2025
af33e8e
benchmark: remove unused variable from util/priority-queue
brunocroh Sep 12, 2025
c7c597e
src: use RAII for uv_process_options_t
iknoom Sep 20, 2025
54b439f
src: fill `options_args`, `options_env` after vectors are finalized
iknoom Sep 22, 2025
b58df47
test: fix typo of test-benchmark-readline.js
deokjinkim Sep 23, 2025
26394cd
test: expand tls-check-server-identity coverage
diangogav Sep 24, 2025
df72dc9
console,util: improve array inspection performance
BridgeAR Sep 27, 2025
d1fb8a5
src: avoid unnecessary string -> `char*` -> string round trips
addaleax Sep 28, 2025
1289ef8
src: remove unnecessary shadowed functions on Utf8Value & BufferValue
addaleax Sep 28, 2025
764d356
src: remove unnecessary `std::string` error messages
addaleax Sep 28, 2025
c3be122
src: allow `std::string_view` arguments to `SPrintF()` and friends
addaleax Sep 28, 2025
9fae03c
tools: use dependabot cooldown and move tools/doc
RafaelGSS Sep 30, 2025
6e386c0
src: make ToLower/ToUpper input args more flexible
addaleax Sep 28, 2025
987841a
src: avoid unnecessary string allocations in SPrintF impl
addaleax Sep 28, 2025
4206406
test: mark test-web-locks skip on IBM i
sravani1510 Oct 1, 2025
81a3055
process: fix default `env` for `process.execve`
richardlau Oct 1, 2025
609c063
src: remove unused variables from report
iknoom Oct 2, 2025
e4b95a5
test: replace diagnostics_channel stackframe in output snapshots
legendecas Oct 3, 2025
c2dd6ee
process: fix wrong asyncContext under unhandled-rejections=strict
islandryu Oct 4, 2025
ea5cfd9
lib: implement passive listener behavior per spec
Amemome Oct 4, 2025
56abc4a
lib: optimize priority queue
gurgunday Oct 4, 2025
aac90d3
tools: verify signatures when updating nghttp*
aduh95 Oct 5, 2025
b928ea9
test: ensure that the message event is fired
lpinca Oct 5, 2025
40fea57
tools: add message on auto-fixing js lint issues in gh workflow
dario-piotrowicz Oct 5, 2025
ef67d09
http: improve writeEarlyHints by avoiding for-of loop
haramj Oct 6, 2025
2197097
src: remove `AnalyzeTemporaryDtors` option from .clang-tidy
iknoom Sep 25, 2025
76b4cab
src: bring permissions macros in line with general C/C++ standards
addaleax Sep 28, 2025
6ac4ab1
2025-10-28, Version 22.21.1 'Jod' (LTS)
nodejs-github-bot Oct 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
lib: implement passive listener behavior per spec
Implements the WHATWG DOM specification for passive event listeners,
ensuring that calls to `preventDefault()` are correctly ignored within
a passive listener context.

An internal `kInPassiveListener` state is added to the Event object
to track when a passive listener is executing. The `preventDefault()`
method and the `returnValue` setter are modified to check this state,
as well as the event's `cancelable` property. This state is reliably
cleaned up within a `finally` block to prevent state pollution in
case a listener throws an error.

This resolves previously failing Web Platform Tests (WPT) in
`AddEventListenerOptions-passive.any.js`.

Refs: https://dom.spec.whatwg.org/#dom-event-preventdefault
PR-URL: #59995
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Mattias Buelens <mattias@buelens.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Jason Zhang <xzha4350@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
Amemome authored and aduh95 committed Oct 22, 2025
commit ea5cfd98c5543fee460939405f42ee7046a003ce
25 changes: 23 additions & 2 deletions lib/internal/event_target.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const { now } = require('internal/perf/utils');

const kType = Symbol('type');
const kDetail = Symbol('detail');
const kInPassiveListener = Symbol('kInPassiveListener');

const isTrustedSet = new SafeWeakSet();
const isTrusted = ObjectGetOwnPropertyDescriptor({
Expand Down Expand Up @@ -127,6 +128,7 @@ class Event {

this[kTarget] = null;
this[kIsBeingDispatched] = false;
this[kInPassiveListener] = false;
}

/**
Expand Down Expand Up @@ -178,6 +180,7 @@ class Event {
preventDefault() {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');
if (!this.#cancelable || this[kInPassiveListener]) return;
this.#defaultPrevented = true;
}

Expand Down Expand Up @@ -266,6 +269,19 @@ class Event {
return !this.#cancelable || !this.#defaultPrevented;
}

/**
* @type {boolean}
*/
set returnValue(value) {
if (!isEvent(this))
throw new ERR_INVALID_THIS('Event');

if (!value) {
if (!this.#cancelable || this[kInPassiveListener]) return;
this.#defaultPrevented = true;
}
}

/**
* @type {boolean}
*/
Expand Down Expand Up @@ -760,7 +776,6 @@ class EventTarget {
throw new ERR_EVENT_RECURSION(event.type);

this[kHybridDispatch](event, event.type, event);

return event.defaultPrevented !== true;
}

Expand Down Expand Up @@ -813,8 +828,8 @@ class EventTarget {
this[kRemoveListener](root.size, type, listener, capture);
}

let arg;
try {
let arg;
if (handler.isNodeStyleListener) {
arg = nodeValue;
} else {
Expand All @@ -824,6 +839,9 @@ class EventTarget {
handler.callback.deref() : handler.callback;
let result;
if (callback) {
if (handler.passive && !handler.isNodeStyleListener) {
arg[kInPassiveListener] = true;
}
result = FunctionPrototypeCall(callback, this, arg);
if (!handler.isNodeStyleListener) {
arg[kIsBeingDispatched] = false;
Expand All @@ -833,6 +851,9 @@ class EventTarget {
addCatch(result);
} catch (err) {
emitUncaughtException(err);
} finally {
if (arg?.[kInPassiveListener])
arg[kInPassiveListener] = false;
}

handler = next;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const common = require('../common');
require('../common');

// Manually converted from https://github.com/web-platform-tests/wpt/blob/master/dom/events/AddEventListenerOptions-passive.html
// in order to define the `document` ourselves
Expand Down Expand Up @@ -58,7 +58,6 @@ const {
testPassiveValue({}, true);
testPassiveValue({ passive: false }, true);

common.skip('TODO: passive listeners is still broken');
testPassiveValue({ passive: 1 }, false);
testPassiveValue({ passive: true }, false);
testPassiveValue({ passive: 0 }, true);
Expand Down
9 changes: 0 additions & 9 deletions test/wpt/status/dom/events.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
{
"AddEventListenerOptions-passive.any.js": {
"fail": {
"expected": [
"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 the presence of other listeners"
]
}
},
"Event-dispatch-listener-order.window.js": {
"skip": "document is not defined"
},
Expand Down