mirror of https://github.com/nodejs/node.git
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: https://github.com/nodejs/node/issues/35748 PR-URL: https://github.com/nodejs/node/pull/35811 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
81ba3ae699
commit
f20a783a31
|
@ -1282,9 +1282,10 @@ This is not used in Node.js and is provided purely for completeness.
|
||||||
added: v14.5.0
|
added: v14.5.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
* Type: {boolean} Always returns `false`.
|
* Type: {boolean} True for Node.js internal events, false otherwise.
|
||||||
|
|
||||||
This is not used in Node.js and is provided purely for completeness.
|
Currently only `AbortSignal`s' `"abort"` event is fired with `isTrusted`
|
||||||
|
set to `true`.
|
||||||
|
|
||||||
#### `event.preventDefault()`
|
#### `event.preventDefault()`
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
|
|
|
@ -11,7 +11,8 @@ const {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
EventTarget,
|
EventTarget,
|
||||||
Event
|
Event,
|
||||||
|
kTrustEvent
|
||||||
} = require('internal/event_target');
|
} = require('internal/event_target');
|
||||||
const {
|
const {
|
||||||
customInspectSymbol,
|
customInspectSymbol,
|
||||||
|
@ -49,7 +50,9 @@ ObjectDefineProperties(AbortSignal.prototype, {
|
||||||
function abortSignal(signal) {
|
function abortSignal(signal) {
|
||||||
if (signal[kAborted]) return;
|
if (signal[kAborted]) return;
|
||||||
signal[kAborted] = true;
|
signal[kAborted] = true;
|
||||||
const event = new Event('abort');
|
const event = new Event('abort', {
|
||||||
|
[kTrustEvent]: true
|
||||||
|
});
|
||||||
if (typeof signal.onabort === 'function') {
|
if (typeof signal.onabort === 'function') {
|
||||||
signal.onabort(event);
|
signal.onabort(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,12 @@ const {
|
||||||
ObjectAssign,
|
ObjectAssign,
|
||||||
ObjectDefineProperties,
|
ObjectDefineProperties,
|
||||||
ObjectDefineProperty,
|
ObjectDefineProperty,
|
||||||
|
ObjectGetOwnPropertyDescriptor,
|
||||||
String,
|
String,
|
||||||
Symbol,
|
Symbol,
|
||||||
SymbolFor,
|
SymbolFor,
|
||||||
SymbolToStringTag,
|
SymbolToStringTag,
|
||||||
|
SafeWeakSet,
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -41,6 +43,7 @@ const kRemoveListener = Symbol('kRemoveListener');
|
||||||
const kIsNodeStyleListener = Symbol('kIsNodeStyleListener');
|
const kIsNodeStyleListener = Symbol('kIsNodeStyleListener');
|
||||||
const kMaxListeners = Symbol('kMaxListeners');
|
const kMaxListeners = Symbol('kMaxListeners');
|
||||||
const kMaxListenersWarned = Symbol('kMaxListenersWarned');
|
const kMaxListenersWarned = Symbol('kMaxListenersWarned');
|
||||||
|
const kTrustEvent = Symbol('kTrustEvent');
|
||||||
|
|
||||||
// Lazy load perf_hooks to avoid the additional overhead on startup
|
// Lazy load perf_hooks to avoid the additional overhead on startup
|
||||||
let perf_hooks;
|
let perf_hooks;
|
||||||
|
@ -61,7 +64,12 @@ const kBubbles = Symbol('bubbles');
|
||||||
const kComposed = Symbol('composed');
|
const kComposed = Symbol('composed');
|
||||||
const kPropagationStopped = Symbol('propagationStopped');
|
const kPropagationStopped = Symbol('propagationStopped');
|
||||||
|
|
||||||
const isTrusted = () => false;
|
const isTrustedSet = new SafeWeakSet();
|
||||||
|
const isTrusted = ObjectGetOwnPropertyDescriptor({
|
||||||
|
get isTrusted() {
|
||||||
|
return isTrustedSet.has(this);
|
||||||
|
}
|
||||||
|
}, 'isTrusted').get;
|
||||||
|
|
||||||
class Event {
|
class Event {
|
||||||
constructor(type, options) {
|
constructor(type, options) {
|
||||||
|
@ -77,6 +85,10 @@ class Event {
|
||||||
this[kDefaultPrevented] = false;
|
this[kDefaultPrevented] = false;
|
||||||
this[kTimestamp] = lazyNow();
|
this[kTimestamp] = lazyNow();
|
||||||
this[kPropagationStopped] = false;
|
this[kPropagationStopped] = false;
|
||||||
|
if (options != null && options[kTrustEvent]) {
|
||||||
|
isTrustedSet.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
// isTrusted is special (LegacyUnforgeable)
|
// isTrusted is special (LegacyUnforgeable)
|
||||||
ObjectDefineProperty(this, 'isTrusted', {
|
ObjectDefineProperty(this, 'isTrusted', {
|
||||||
get: isTrusted,
|
get: isTrusted,
|
||||||
|
@ -573,5 +585,6 @@ module.exports = {
|
||||||
initNodeEventTarget,
|
initNodeEventTarget,
|
||||||
kCreateEvent,
|
kCreateEvent,
|
||||||
kNewListener,
|
kNewListener,
|
||||||
|
kTrustEvent,
|
||||||
kRemoveListener,
|
kRemoveListener,
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,6 +101,10 @@ primordials.SafeSet = makeSafe(
|
||||||
Set,
|
Set,
|
||||||
class SafeSet extends Set {}
|
class SafeSet extends Set {}
|
||||||
);
|
);
|
||||||
|
primordials.SafeWeakSet = makeSafe(
|
||||||
|
WeakSet,
|
||||||
|
class SafeWeakSet extends WeakSet {}
|
||||||
|
);
|
||||||
primordials.SafePromise = makeSafe(
|
primordials.SafePromise = makeSafe(
|
||||||
Promise,
|
Promise,
|
||||||
class SafePromise extends Promise {}
|
class SafePromise extends Promise {}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
// Flags: --no-warnings
|
// Flags: --no-warnings --expose-internals
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
|
|
||||||
const { ok, strictEqual } = require('assert');
|
const { ok, strictEqual } = require('assert');
|
||||||
|
const { Event } = require('internal/event_target');
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// Tests that abort is fired with the correct event type on AbortControllers
|
||||||
const ac = new AbortController();
|
const ac = new AbortController();
|
||||||
ok(ac.signal);
|
ok(ac.signal);
|
||||||
ac.signal.onabort = common.mustCall((event) => {
|
ac.signal.onabort = common.mustCall((event) => {
|
||||||
|
@ -20,3 +22,33 @@ const { ok, strictEqual } = require('assert');
|
||||||
ac.abort();
|
ac.abort();
|
||||||
ok(ac.signal.aborted);
|
ok(ac.signal.aborted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Tests that abort events are trusted
|
||||||
|
const ac = new AbortController();
|
||||||
|
ac.signal.addEventListener('abort', common.mustCall((event) => {
|
||||||
|
ok(event.isTrusted);
|
||||||
|
}));
|
||||||
|
ac.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Tests that abort events have the same `isTrusted` reference
|
||||||
|
const first = new AbortController();
|
||||||
|
const second = new AbortController();
|
||||||
|
let ev1, ev2;
|
||||||
|
const ev3 = new Event('abort');
|
||||||
|
first.signal.addEventListener('abort', common.mustCall((event) => {
|
||||||
|
ev1 = event;
|
||||||
|
}));
|
||||||
|
second.signal.addEventListener('abort', common.mustCall((event) => {
|
||||||
|
ev2 = event;
|
||||||
|
}));
|
||||||
|
first.abort();
|
||||||
|
second.abort();
|
||||||
|
const firstTrusted = Reflect.getOwnPropertyDescriptor(ev1, 'isTrusted').get;
|
||||||
|
const secondTrusted = Reflect.getOwnPropertyDescriptor(ev2, 'isTrusted').get;
|
||||||
|
const untrusted = Reflect.getOwnPropertyDescriptor(ev3, 'isTrusted').get;
|
||||||
|
strictEqual(firstTrusted, secondTrusted);
|
||||||
|
strictEqual(untrusted, firstTrusted);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue