Skip to content

Commit

Permalink
events: support event handlers on prototypes
Browse files Browse the repository at this point in the history
PR-URL: nodejs#35931
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Daijiro Wachi <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
  • Loading branch information
benjamingr authored and targos committed Apr 24, 2021
1 parent eaedd56 commit ac9532c
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 13 deletions.
21 changes: 14 additions & 7 deletions lib/internal/event_target.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const {
Symbol,
SymbolFor,
SymbolToStringTag,
SafeWeakMap,
SafeWeakSet,
} = primordials;

Expand Down Expand Up @@ -576,21 +577,27 @@ function emitUnhandledRejectionOrErr(that, err, event) {
process.emit('error', err, event);
}

// A map of emitter -> map of name -> handler
const eventHandlerValueMap = new SafeWeakMap();

function defineEventHandler(emitter, name) {
// 8.1.5.1 Event handlers - basically `on[eventName]` attributes
let eventHandlerValue;
Object.defineProperty(emitter, `on${name}`, {
ObjectDefineProperty(emitter, `on${name}`, {
get() {
return eventHandlerValue;
return eventHandlerValueMap.get(this)?.get(name);
},
set(value) {
if (eventHandlerValue) {
emitter.removeEventListener(name, eventHandlerValue);
const oldValue = eventHandlerValueMap.get(this)?.get(name);
if (oldValue) {
this.removeEventListener(name, oldValue);
}
if (typeof value === 'function') {
emitter.addEventListener(name, value);
this.addEventListener(name, value);
}
if (!eventHandlerValueMap.has(this)) {
eventHandlerValueMap.set(this, new Map());
}
eventHandlerValue = value;
eventHandlerValueMap.get(this).set(name, value);
},
configurable: true,
enumerable: true
Expand Down
5 changes: 3 additions & 2 deletions lib/internal/worker/io.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,14 @@ ObjectDefineProperty(
// This is called from inside the `MessagePort` constructor.
function oninit() {
initNodeEventTarget(this);
// TODO(addaleax): This should be on MessagePort.prototype, but
// defineEventHandler() does not support that.
defineEventHandler(this, 'message');
defineEventHandler(this, 'messageerror');
setupPortReferencing(this, this, 'message');
}

defineEventHandler(MessagePort.prototype, 'message');
defineEventHandler(MessagePort.prototype, 'messageerror');

ObjectDefineProperty(MessagePort.prototype, onInitSymbol, {
enumerable: true,
writable: false,
Expand Down
6 changes: 2 additions & 4 deletions test/parallel/test-worker-message-port.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,7 @@ const { MessageChannel, MessagePort } = require('worker_threads');
assert.deepStrictEqual(
Object.getOwnPropertyNames(MessagePort.prototype).sort(),
[
// TODO(addaleax): This should include onmessage (and eventually
// onmessageerror).
'close', 'constructor', 'postMessage', 'ref', 'start',
'unref'
'close', 'constructor', 'onmessage', 'onmessageerror', 'postMessage',
'ref', 'start', 'unref'
]);
}

0 comments on commit ac9532c

Please sign in to comment.