lib: use private field in AbortController

Instead of validating the receiver ourselves, let V8 handle
the validation using the semantics of private fields.

PR-URL: https://github.com/nodejs/node/pull/43820
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
Joyee Cheung 2022-07-16 14:07:53 +08:00 committed by GitHub
parent e54ee80d0b
commit 73ba8830d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 6 additions and 19 deletions

View file

@ -292,34 +292,21 @@ function abortSignal(signal, reason) {
signal.dispatchEvent(event); signal.dispatchEvent(event);
} }
// TODO(joyeecheung): use private fields and we'll get invalid access
// validation from V8 instead of throwing ERR_INVALID_THIS ourselves.
const kSignal = Symbol('signal');
function validateAbortController(obj) {
if (obj?.[kSignal] === undefined)
throw new ERR_INVALID_THIS('AbortController');
}
class AbortController { class AbortController {
constructor() { #signal = createAbortSignal();
this[kSignal] = createAbortSignal();
}
/** /**
* @type {AbortSignal} * @type {AbortSignal}
*/ */
get signal() { get signal() {
validateAbortController(this); return this.#signal;
return this[kSignal];
} }
/** /**
* @param {any} reason * @param {any} reason
*/ */
abort(reason = new DOMException('This operation was aborted', 'AbortError')) { abort(reason = new DOMException('This operation was aborted', 'AbortError')) {
validateAbortController(this); abortSignal(this.#signal, reason);
abortSignal(this[kSignal], reason);
} }
[customInspectSymbol](depth, options) { [customInspectSymbol](depth, options) {

View file

@ -108,11 +108,11 @@ const { setTimeout: sleep } = require('timers/promises');
for (const badController of badAbortControllers) { for (const badController of badAbortControllers) {
throws( throws(
() => acSignalGet.call(badController), () => acSignalGet.call(badController),
{ code: 'ERR_INVALID_THIS', name: 'TypeError' } { name: 'TypeError' }
); );
throws( throws(
() => acAbort.call(badController), () => acAbort.call(badController),
{ code: 'ERR_INVALID_THIS', name: 'TypeError' } { name: 'TypeError' }
); );
} }
} }
@ -139,7 +139,7 @@ const { setTimeout: sleep } = require('timers/promises');
for (const badSignal of badAbortSignals) { for (const badSignal of badAbortSignals) {
throws( throws(
() => signalAbortedGet.call(badSignal), () => signalAbortedGet.call(badSignal),
{ code: 'ERR_INVALID_THIS', name: 'TypeError' } { name: 'TypeError' }
); );
} }
} }