Skip to content
/ node Public
forked from nodejs/node

Commit

Permalink
lib: brand check event handler property receivers
Browse files Browse the repository at this point in the history
Event handler properties defined by `defineEventHandler` should check
if the receiver is a valid `EventTarget`.

PR-URL: nodejs#44483
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Minwoo Jung <[email protected]>
Reviewed-By: James M Snell <[email protected]>
  • Loading branch information
legendecas authored and panva committed Oct 4, 2022
1 parent a7eedc2 commit 45469cd
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 27 deletions.
65 changes: 39 additions & 26 deletions lib/internal/event_target.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -492,6 +492,7 @@ function initEventTarget(self) {
self[kEvents] = new SafeMap();
self[kMaxEventTargetListeners] = EventEmitter.defaultMaxListeners;
self[kMaxEventTargetListenersWarned] = false;
self[kHandlers] = new SafeMap();
}

class EventTarget {
Expand Down Expand Up @@ -1021,34 +1022,46 @@ function makeEventHandler(handler) {

function defineEventHandler(emitter, name) {
// 8.1.5.1 Event handlers - basically `on[eventName]` attributes
ObjectDefineProperty(emitter, `on${name}`, {
const propName = `on${name}`;
function get() {
validateInternalField(this, kHandlers, 'EventTarget');
return this[kHandlers]?.get(name)?.handler ?? null;
}
ObjectDefineProperty(get, 'name', {
__proto__: null,
get() {
return this[kHandlers]?.get(name)?.handler ?? null;
},
set(value) {
if (!this[kHandlers]) {
this[kHandlers] = new SafeMap();
value: `get ${propName}`,
});

function set(value) {
validateInternalField(this, kHandlers, 'EventTarget');
let wrappedHandler = this[kHandlers]?.get(name);
if (wrappedHandler) {
if (typeof wrappedHandler.handler === 'function') {
this[kEvents].get(name).size--;
const size = this[kEvents].get(name).size;
this[kRemoveListener](size, name, wrappedHandler.handler, false);
}
let wrappedHandler = this[kHandlers]?.get(name);
if (wrappedHandler) {
if (typeof wrappedHandler.handler === 'function') {
this[kEvents].get(name).size--;
const size = this[kEvents].get(name).size;
this[kRemoveListener](size, name, wrappedHandler.handler, false);
}
wrappedHandler.handler = value;
if (typeof wrappedHandler.handler === 'function') {
this[kEvents].get(name).size++;
const size = this[kEvents].get(name).size;
this[kNewListener](size, name, value, false, false, false, false);
}
} else {
wrappedHandler = makeEventHandler(value);
this.addEventListener(name, wrappedHandler);
wrappedHandler.handler = value;
if (typeof wrappedHandler.handler === 'function') {
this[kEvents].get(name).size++;
const size = this[kEvents].get(name).size;
this[kNewListener](size, name, value, false, false, false, false);
}
this[kHandlers].set(name, wrappedHandler);
},
} else {
wrappedHandler = makeEventHandler(value);
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
});
Expand Down
9 changes: 8 additions & 1 deletion lib/internal/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -440,5 +446,6 @@ module.exports = {
validateUndefined,
validateUnion,
validateAbortSignal,
validateLinkHeaderValue
validateLinkHeaderValue,
validateInternalField,
};

0 comments on commit 45469cd

Please sign in to comment.