lib: brand check event handler property receivers

Event handler properties defined by `defineEventHandler` should check
if the receiver is a valid `EventTarget`.

PR-URL: https://github.com/nodejs/node/pull/44483
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
legendecas 2022-09-16 00:51:58 +08:00
parent ecd5de08b7
commit f529f73bd7
No known key found for this signature in database
GPG Key ID: CB3C9EC2BC27057C
2 changed files with 47 additions and 27 deletions

View File

@ -34,7 +34,7 @@ const {
ERR_INVALID_THIS,
}
} = require('internal/errors');
const { validateObject, validateString } = require('internal/validators');
const { validateObject, validateString, validateInternalField } = require('internal/validators');
const {
customInspectSymbol,
@ -492,6 +492,7 @@ function initEventTarget(self) {
self[kEvents] = new SafeMap();
self[kMaxEventTargetListeners] = EventEmitter.defaultMaxListeners;
self[kMaxEventTargetListenersWarned] = false;
self[kHandlers] = new SafeMap();
}
class EventTarget {
@ -1021,15 +1022,18 @@ function makeEventHandler(handler) {
function defineEventHandler(emitter, name) {
// 8.1.5.1 Event handlers - basically `on[eventName]` attributes
ObjectDefineProperty(emitter, `on${name}`, {
__proto__: null,
get() {
const propName = `on${name}`;
function get() {
validateInternalField(this, kHandlers, 'EventTarget');
return this[kHandlers]?.get(name)?.handler ?? null;
},
set(value) {
if (!this[kHandlers]) {
this[kHandlers] = new SafeMap();
}
ObjectDefineProperty(get, 'name', {
__proto__: null,
value: `get ${propName}`,
});
function set(value) {
validateInternalField(this, kHandlers, 'EventTarget');
let wrappedHandler = this[kHandlers]?.get(name);
if (wrappedHandler) {
if (typeof wrappedHandler.handler === 'function') {
@ -1048,7 +1052,16 @@ function defineEventHandler(emitter, name) {
this.addEventListener(name, wrappedHandler);
}
this[kHandlers].set(name, wrappedHandler);
},
}
ObjectDefineProperty(set, 'name', {
__proto__: null,
value: `set ${propName}`,
});
ObjectDefineProperty(emitter, propName, {
__proto__: null,
get,
set,
configurable: true,
enumerable: true
});

View File

@ -418,6 +418,12 @@ function validateLinkHeaderValue(value, name) {
}
}
const validateInternalField = hideStackFrames((object, fieldKey, className) => {
if (typeof object !== 'object' || object === null || !ObjectPrototypeHasOwnProperty(object, fieldKey)) {
throw new ERR_INVALID_ARG_TYPE('this', className, object);
}
});
module.exports = {
isInt32,
isUint32,
@ -440,5 +446,6 @@ module.exports = {
validateUndefined,
validateUnion,
validateAbortSignal,
validateLinkHeaderValue
validateLinkHeaderValue,
validateInternalField,
};