summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSatya Rohith <me@satyarohith.com>2024-04-29 14:23:54 +0530
committerGitHub <noreply@github.com>2024-04-29 08:53:54 +0000
commit455cf1743f70cb12025e36b3c4eb9a213fe77199 (patch)
tree7a8532218ad1b572d55444195315b0b53994ad1a
parent021a0dc9b1063bff67dc295c61d9f4bf787c18fb (diff)
fix(ext/node): add support for MessagePort.removeListener/off (#23598)
Closes https://github.com/denoland/deno/issues/23564
-rw-r--r--ext/node/polyfills/worker_threads.ts24
-rw-r--r--ext/web/13_message_port.js5
-rw-r--r--tests/specs/node/worker_threads/__test__.jsonc8
-rw-r--r--tests/specs/node/worker_threads/message_port_removelistener.mjs9
-rw-r--r--tests/specs/node/worker_threads/message_port_removelistener.mjs.out1
5 files changed, 47 insertions, 0 deletions
diff --git a/ext/node/polyfills/worker_threads.ts b/ext/node/polyfills/worker_threads.ts
index 8f531368a..e88e6368b 100644
--- a/ext/node/polyfills/worker_threads.ts
+++ b/ext/node/polyfills/worker_threads.ts
@@ -473,6 +473,12 @@ class NodeMessageChannel {
}
}
+const listeners = new SafeWeakMap<
+ // deno-lint-ignore no-explicit-any
+ (...args: any[]) => void,
+ // deno-lint-ignore no-explicit-any
+ (ev: any) => any
+>();
function webMessagePortToNodeMessagePort(port: MessagePort) {
port.on = port.addListener = function (this: MessagePort, name, listener) {
// deno-lint-ignore no-explicit-any
@@ -486,6 +492,24 @@ function webMessagePortToNodeMessagePort(port: MessagePort) {
} else {
throw new Error(`Unknown event: "${name}"`);
}
+ listeners.set(listener, _listener);
+ return this;
+ };
+ port.off = port.removeListener = function (
+ this: MessagePort,
+ name,
+ listener,
+ ) {
+ if (name == "message") {
+ port.removeEventListener("message", listeners.get(listener)!);
+ } else if (name == "messageerror") {
+ port.removeEventListener("messageerror", listeners.get(listener)!);
+ } else if (name == "close") {
+ port.removeEventListener("close", listeners.get(listener)!);
+ } else {
+ throw new Error(`Unknown event: "${name}"`);
+ }
+ listeners.delete(listener);
return this;
};
port[nodeWorkerThreadCloseCb] = () => {
diff --git a/ext/web/13_message_port.js b/ext/web/13_message_port.js
index 4e4184f2a..93145e8f7 100644
--- a/ext/web/13_message_port.js
+++ b/ext/web/13_message_port.js
@@ -190,6 +190,11 @@ class MessagePort extends EventTarget {
this[_enabled] = true;
while (true) {
if (this[_id] === null) break;
+ // Exit if no message event listeners are present in Node compat mode.
+ if (
+ typeof this[nodeWorkerThreadCloseCb] == "function" &&
+ messageEventListenerCount === 0
+ ) break;
let data;
try {
data = await op_message_port_recv_message(
diff --git a/tests/specs/node/worker_threads/__test__.jsonc b/tests/specs/node/worker_threads/__test__.jsonc
new file mode 100644
index 000000000..adcb9a85d
--- /dev/null
+++ b/tests/specs/node/worker_threads/__test__.jsonc
@@ -0,0 +1,8 @@
+{
+ "steps": [{
+ "args": "run message_port_removelistener.mjs",
+ "output": "message_port_removelistener.mjs.out",
+ // Note: successful exit asserts that the test passed
+ "exitCode": 0
+ }]
+}
diff --git a/tests/specs/node/worker_threads/message_port_removelistener.mjs b/tests/specs/node/worker_threads/message_port_removelistener.mjs
new file mode 100644
index 000000000..e0cac6ce9
--- /dev/null
+++ b/tests/specs/node/worker_threads/message_port_removelistener.mjs
@@ -0,0 +1,9 @@
+import { MessageChannel } from "node:worker_threads";
+
+const { port1, port2 } = new MessageChannel();
+const listener = (message) => {
+ console.log(message);
+ port1.off("message", listener);
+};
+port1.on("message", listener);
+port2.postMessage("Hello World!");
diff --git a/tests/specs/node/worker_threads/message_port_removelistener.mjs.out b/tests/specs/node/worker_threads/message_port_removelistener.mjs.out
new file mode 100644
index 000000000..980a0d5f1
--- /dev/null
+++ b/tests/specs/node/worker_threads/message_port_removelistener.mjs.out
@@ -0,0 +1 @@
+Hello World!