Skip to content

Commit f08e2c0

Browse files
benjamingrtargos
authored andcommitted
events: make abort_controller event trusted
The AbortController abort event is trusted, currently we fire all events with isTrusted: false. Allow dispatching events internally with `isTrusted: true` and add a test for it. Co-Authored-By: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Fixes: #35748 PR-URL: #35811 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 438d9de commit f08e2c0

File tree

5 files changed

+59
-6
lines changed

5 files changed

+59
-6
lines changed

doc/api/events.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1282,9 +1282,10 @@ This is not used in Node.js and is provided purely for completeness.
12821282
added: v14.5.0
12831283
-->
12841284

1285-
* Type: {boolean} Always returns `false`.
1285+
* Type: {boolean} True for Node.js internal events, false otherwise.
12861286

1287-
This is not used in Node.js and is provided purely for completeness.
1287+
Currently only `AbortSignal`s' `"abort"` event is fired with `isTrusted`
1288+
set to `true`.
12881289

12891290
#### `event.preventDefault()`
12901291
<!-- YAML

lib/internal/abort_controller.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ const {
1111

1212
const {
1313
EventTarget,
14-
Event
14+
Event,
15+
kTrustEvent
1516
} = require('internal/event_target');
1617
const {
1718
customInspectSymbol,
@@ -49,7 +50,9 @@ ObjectDefineProperties(AbortSignal.prototype, {
4950
function abortSignal(signal) {
5051
if (signal[kAborted]) return;
5152
signal[kAborted] = true;
52-
const event = new Event('abort');
53+
const event = new Event('abort', {
54+
[kTrustEvent]: true
55+
});
5356
if (typeof signal.onabort === 'function') {
5457
signal.onabort(event);
5558
}

lib/internal/event_target.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ const {
99
ObjectAssign,
1010
ObjectDefineProperties,
1111
ObjectDefineProperty,
12+
ObjectGetOwnPropertyDescriptor,
1213
String,
1314
Symbol,
1415
SymbolFor,
1516
SymbolToStringTag,
17+
SafeWeakSet,
1618
} = primordials;
1719

1820
const {
@@ -41,6 +43,7 @@ const kRemoveListener = Symbol('kRemoveListener');
4143
const kIsNodeStyleListener = Symbol('kIsNodeStyleListener');
4244
const kMaxListeners = Symbol('kMaxListeners');
4345
const kMaxListenersWarned = Symbol('kMaxListenersWarned');
46+
const kTrustEvent = Symbol('kTrustEvent');
4447

4548
// Lazy load perf_hooks to avoid the additional overhead on startup
4649
let perf_hooks;
@@ -61,7 +64,12 @@ const kBubbles = Symbol('bubbles');
6164
const kComposed = Symbol('composed');
6265
const kPropagationStopped = Symbol('propagationStopped');
6366

64-
const isTrusted = () => false;
67+
const isTrustedSet = new SafeWeakSet();
68+
const isTrusted = ObjectGetOwnPropertyDescriptor({
69+
get isTrusted() {
70+
return isTrustedSet.has(this);
71+
}
72+
}, 'isTrusted').get;
6573

6674
class Event {
6775
constructor(type, options) {
@@ -77,6 +85,10 @@ class Event {
7785
this[kDefaultPrevented] = false;
7886
this[kTimestamp] = lazyNow();
7987
this[kPropagationStopped] = false;
88+
if (options != null && options[kTrustEvent]) {
89+
isTrustedSet.add(this);
90+
}
91+
8092
// isTrusted is special (LegacyUnforgeable)
8193
ObjectDefineProperty(this, 'isTrusted', {
8294
get: isTrusted,
@@ -573,5 +585,6 @@ module.exports = {
573585
initNodeEventTarget,
574586
kCreateEvent,
575587
kNewListener,
588+
kTrustEvent,
576589
kRemoveListener,
577590
};

lib/internal/per_context/primordials.js

+4
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ primordials.SafeSet = makeSafe(
101101
Set,
102102
class SafeSet extends Set {}
103103
);
104+
primordials.SafeWeakSet = makeSafe(
105+
WeakSet,
106+
class SafeWeakSet extends WeakSet {}
107+
);
104108
primordials.SafePromise = makeSafe(
105109
Promise,
106110
class SafePromise extends Promise {}

test/parallel/test-abortcontroller.js

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
// Flags: --no-warnings
1+
// Flags: --no-warnings --expose-internals
22
'use strict';
33

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

66
const { ok, strictEqual } = require('assert');
7+
const { Event } = require('internal/event_target');
78

89
{
10+
// Tests that abort is fired with the correct event type on AbortControllers
911
const ac = new AbortController();
1012
ok(ac.signal);
1113
ac.signal.onabort = common.mustCall((event) => {
@@ -20,3 +22,33 @@ const { ok, strictEqual } = require('assert');
2022
ac.abort();
2123
ok(ac.signal.aborted);
2224
}
25+
26+
{
27+
// Tests that abort events are trusted
28+
const ac = new AbortController();
29+
ac.signal.addEventListener('abort', common.mustCall((event) => {
30+
ok(event.isTrusted);
31+
}));
32+
ac.abort();
33+
}
34+
35+
{
36+
// Tests that abort events have the same `isTrusted` reference
37+
const first = new AbortController();
38+
const second = new AbortController();
39+
let ev1, ev2;
40+
const ev3 = new Event('abort');
41+
first.signal.addEventListener('abort', common.mustCall((event) => {
42+
ev1 = event;
43+
}));
44+
second.signal.addEventListener('abort', common.mustCall((event) => {
45+
ev2 = event;
46+
}));
47+
first.abort();
48+
second.abort();
49+
const firstTrusted = Reflect.getOwnPropertyDescriptor(ev1, 'isTrusted').get;
50+
const secondTrusted = Reflect.getOwnPropertyDescriptor(ev2, 'isTrusted').get;
51+
const untrusted = Reflect.getOwnPropertyDescriptor(ev3, 'isTrusted').get;
52+
strictEqual(firstTrusted, secondTrusted);
53+
strictEqual(untrusted, firstTrusted);
54+
}

0 commit comments

Comments
 (0)