mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix(ext/node) implement receiveMessageOnPort for node:worker_threads (#22766)
Implementation of `receiveMessageOnPort` for `node:worker_threads` Fixes: #22702
This commit is contained in:
parent
16dbbfa64a
commit
80dbcd3ddf
8 changed files with 95 additions and 4 deletions
|
@ -8,21 +8,25 @@ import {
|
||||||
op_host_recv_ctrl,
|
op_host_recv_ctrl,
|
||||||
op_host_recv_message,
|
op_host_recv_message,
|
||||||
op_host_terminate_worker,
|
op_host_terminate_worker,
|
||||||
|
op_message_port_recv_message_sync,
|
||||||
op_require_read_closest_package_json,
|
op_require_read_closest_package_json,
|
||||||
} from "ext:core/ops";
|
} from "ext:core/ops";
|
||||||
import { BroadcastChannel } from "ext:deno_broadcast_channel/01_broadcast_channel.js";
|
|
||||||
import {
|
import {
|
||||||
deserializeJsMessageData,
|
deserializeJsMessageData,
|
||||||
MessageChannel,
|
MessageChannel,
|
||||||
MessagePort,
|
MessagePort,
|
||||||
|
MessagePortIdSymbol,
|
||||||
|
MessagePortPrototype,
|
||||||
serializeJsMessageData,
|
serializeJsMessageData,
|
||||||
} from "ext:deno_web/13_message_port.js";
|
} from "ext:deno_web/13_message_port.js";
|
||||||
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
||||||
import { log } from "ext:runtime/06_util.js";
|
import { log } from "ext:runtime/06_util.js";
|
||||||
import { notImplemented } from "ext:deno_node/_utils.ts";
|
import { notImplemented } from "ext:deno_node/_utils.ts";
|
||||||
import { EventEmitter, once } from "node:events";
|
import { EventEmitter, once } from "node:events";
|
||||||
|
import { BroadcastChannel } from "ext:deno_broadcast_channel/01_broadcast_channel.js";
|
||||||
import { isAbsolute, resolve } from "node:path";
|
import { isAbsolute, resolve } from "node:path";
|
||||||
|
|
||||||
|
const { ObjectPrototypeIsPrototypeOf } = primordials;
|
||||||
const {
|
const {
|
||||||
Error,
|
Error,
|
||||||
Symbol,
|
Symbol,
|
||||||
|
@ -496,9 +500,24 @@ export function markAsUntransferable() {
|
||||||
export function moveMessagePortToContext() {
|
export function moveMessagePortToContext() {
|
||||||
notImplemented("moveMessagePortToContext");
|
notImplemented("moveMessagePortToContext");
|
||||||
}
|
}
|
||||||
export function receiveMessageOnPort() {
|
|
||||||
notImplemented("receiveMessageOnPort");
|
/**
|
||||||
|
* @param { MessagePort } port
|
||||||
|
* @returns {object | undefined}
|
||||||
|
*/
|
||||||
|
export function receiveMessageOnPort(port: MessagePort): object | undefined {
|
||||||
|
if (!(ObjectPrototypeIsPrototypeOf(MessagePortPrototype, port))) {
|
||||||
|
const err = new TypeError(
|
||||||
|
'The "port" argument must be a MessagePort instance',
|
||||||
|
);
|
||||||
|
err["code"] = "ERR_INVALID_ARG_TYPE";
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
const data = op_message_port_recv_message_sync(port[MessagePortIdSymbol]);
|
||||||
|
if (data === null) return undefined;
|
||||||
|
return { message: deserializeJsMessageData(data)[0] };
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
BroadcastChannel,
|
BroadcastChannel,
|
||||||
MessageChannel,
|
MessageChannel,
|
||||||
|
|
|
@ -83,6 +83,7 @@ webidl.configureInterface(MessageChannel);
|
||||||
const MessageChannelPrototype = MessageChannel.prototype;
|
const MessageChannelPrototype = MessageChannel.prototype;
|
||||||
|
|
||||||
const _id = Symbol("id");
|
const _id = Symbol("id");
|
||||||
|
const MessagePortIdSymbol = _id;
|
||||||
const _enabled = Symbol("enabled");
|
const _enabled = Symbol("enabled");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -380,6 +381,7 @@ export {
|
||||||
deserializeJsMessageData,
|
deserializeJsMessageData,
|
||||||
MessageChannel,
|
MessageChannel,
|
||||||
MessagePort,
|
MessagePort,
|
||||||
|
MessagePortIdSymbol,
|
||||||
MessagePortPrototype,
|
MessagePortPrototype,
|
||||||
serializeJsMessageData,
|
serializeJsMessageData,
|
||||||
structuredClone,
|
structuredClone,
|
||||||
|
|
6
ext/web/internal.d.ts
vendored
6
ext/web/internal.d.ts
vendored
|
@ -110,4 +110,10 @@ declare module "ext:deno_web/13_message_port.js" {
|
||||||
data: Uint8Array;
|
data: Uint8Array;
|
||||||
transferables: Transferable[];
|
transferables: Transferable[];
|
||||||
}
|
}
|
||||||
|
const MessageChannel: typeof MessageChannel;
|
||||||
|
const MessagePort: typeof MessagePort;
|
||||||
|
const MessagePortIdSymbol: typeof MessagePortIdSymbol;
|
||||||
|
function deserializeJsMessageData(
|
||||||
|
messageData: messagePort.MessageData,
|
||||||
|
): [object, object[]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ pub use crate::message_port::create_entangled_message_port;
|
||||||
use crate::message_port::op_message_port_create_entangled;
|
use crate::message_port::op_message_port_create_entangled;
|
||||||
use crate::message_port::op_message_port_post_message;
|
use crate::message_port::op_message_port_post_message;
|
||||||
use crate::message_port::op_message_port_recv_message;
|
use crate::message_port::op_message_port_recv_message;
|
||||||
|
use crate::message_port::op_message_port_recv_message_sync;
|
||||||
pub use crate::message_port::JsMessageData;
|
pub use crate::message_port::JsMessageData;
|
||||||
pub use crate::message_port::MessagePort;
|
pub use crate::message_port::MessagePort;
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ deno_core::extension!(deno_web,
|
||||||
op_message_port_create_entangled,
|
op_message_port_create_entangled,
|
||||||
op_message_port_post_message,
|
op_message_port_post_message,
|
||||||
op_message_port_recv_message,
|
op_message_port_recv_message,
|
||||||
|
op_message_port_recv_message_sync,
|
||||||
compression::op_compression_new,
|
compression::op_compression_new,
|
||||||
compression::op_compression_write,
|
compression::op_compression_write,
|
||||||
compression::op_compression_finish,
|
compression::op_compression_finish,
|
||||||
|
|
|
@ -17,6 +17,7 @@ use deno_core::Resource;
|
||||||
use deno_core::ResourceId;
|
use deno_core::ResourceId;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use tokio::sync::mpsc::error::TryRecvError;
|
||||||
use tokio::sync::mpsc::unbounded_channel;
|
use tokio::sync::mpsc::unbounded_channel;
|
||||||
use tokio::sync::mpsc::UnboundedReceiver;
|
use tokio::sync::mpsc::UnboundedReceiver;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
@ -227,3 +228,22 @@ pub async fn op_message_port_recv_message(
|
||||||
let cancel = RcRef::map(resource.clone(), |r| &r.cancel);
|
let cancel = RcRef::map(resource.clone(), |r| &r.cancel);
|
||||||
resource.port.recv(state).or_cancel(cancel).await?
|
resource.port.recv(state).or_cancel(cancel).await?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op2]
|
||||||
|
#[serde]
|
||||||
|
pub fn op_message_port_recv_message_sync(
|
||||||
|
state: &mut OpState, // Rc<RefCell<OpState>>,
|
||||||
|
#[smi] rid: ResourceId,
|
||||||
|
) -> Result<Option<JsMessageData>, AnyError> {
|
||||||
|
let resource = state.resource_table.get::<MessagePortResource>(rid)?;
|
||||||
|
let mut rx = resource.port.rx.borrow_mut();
|
||||||
|
|
||||||
|
match rx.try_recv() {
|
||||||
|
Ok((d, t)) => Ok(Some(JsMessageData {
|
||||||
|
data: d,
|
||||||
|
transferables: serialize_transferables(state, t),
|
||||||
|
})),
|
||||||
|
Err(TryRecvError::Empty) => Ok(None),
|
||||||
|
Err(TryRecvError::Disconnected) => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -104,6 +104,8 @@
|
||||||
"test-util.js",
|
"test-util.js",
|
||||||
"test-webcrypto-sign-verify.js",
|
"test-webcrypto-sign-verify.js",
|
||||||
"test-whatwg-url-properties.js",
|
"test-whatwg-url-properties.js",
|
||||||
|
// needs replace ".on" => ".addEventListener" in L29
|
||||||
|
"test-worker-message-port-receive-message.js",
|
||||||
"test-zlib-convenience-methods.js",
|
"test-zlib-convenience-methods.js",
|
||||||
"test-zlib-empty-buffer.js",
|
"test-zlib-empty-buffer.js",
|
||||||
"test-zlib-invalid-input.js",
|
"test-zlib-invalid-input.js",
|
||||||
|
@ -665,6 +667,7 @@
|
||||||
"test-whatwg-url-custom-tostringtag.js",
|
"test-whatwg-url-custom-tostringtag.js",
|
||||||
"test-whatwg-url-override-hostname.js",
|
"test-whatwg-url-override-hostname.js",
|
||||||
"test-whatwg-url-properties.js",
|
"test-whatwg-url-properties.js",
|
||||||
|
"test-worker-message-port-receive-message.js",
|
||||||
"test-zlib-close-after-error.js",
|
"test-zlib-close-after-error.js",
|
||||||
"test-zlib-close-after-write.js",
|
"test-zlib-close-after-write.js",
|
||||||
"test-zlib-convenience-methods.js",
|
"test-zlib-convenience-methods.js",
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// deno-fmt-ignore-file
|
||||||
|
// deno-lint-ignore-file
|
||||||
|
|
||||||
|
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
||||||
|
// Taken from Node 18.12.1
|
||||||
|
// This file is automatically generated by `tools/node_compat/setup.ts`. Do not modify this file manually.
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const { MessageChannel, receiveMessageOnPort } = require('worker_threads');
|
||||||
|
|
||||||
|
const { port1, port2 } = new MessageChannel();
|
||||||
|
|
||||||
|
const message1 = { hello: 'world' };
|
||||||
|
const message2 = { foo: 'bar' };
|
||||||
|
|
||||||
|
// Make sure receiveMessageOnPort() works in a FIFO way, the same way it does
|
||||||
|
// when we’re using events.
|
||||||
|
assert.strictEqual(receiveMessageOnPort(port2), undefined);
|
||||||
|
port1.postMessage(message1);
|
||||||
|
port1.postMessage(message2);
|
||||||
|
assert.deepStrictEqual(receiveMessageOnPort(port2), { message: message1 });
|
||||||
|
assert.deepStrictEqual(receiveMessageOnPort(port2), { message: message2 });
|
||||||
|
assert.strictEqual(receiveMessageOnPort(port2), undefined);
|
||||||
|
assert.strictEqual(receiveMessageOnPort(port2), undefined);
|
||||||
|
|
||||||
|
// Make sure message handlers aren’t called.
|
||||||
|
port2.addEventListener('message', common.mustNotCall());
|
||||||
|
port1.postMessage(message1);
|
||||||
|
assert.deepStrictEqual(receiveMessageOnPort(port2), { message: message1 });
|
||||||
|
port1.close();
|
||||||
|
|
||||||
|
for (const value of [null, 0, -1, {}, []]) {
|
||||||
|
assert.throws(() => receiveMessageOnPort(value), {
|
||||||
|
name: 'TypeError',
|
||||||
|
code: 'ERR_INVALID_ARG_TYPE',
|
||||||
|
message: 'The "port" argument must be a MessagePort instance'
|
||||||
|
});
|
||||||
|
}
|
|
@ -2710,7 +2710,6 @@ Total: 2998
|
||||||
- [parallel/test-worker-message-port-message-port-transferring.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-message-port-transferring.js)
|
- [parallel/test-worker-message-port-message-port-transferring.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-message-port-transferring.js)
|
||||||
- [parallel/test-worker-message-port-move.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-move.js)
|
- [parallel/test-worker-message-port-move.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-move.js)
|
||||||
- [parallel/test-worker-message-port-multiple-sharedarraybuffers.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-multiple-sharedarraybuffers.js)
|
- [parallel/test-worker-message-port-multiple-sharedarraybuffers.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-multiple-sharedarraybuffers.js)
|
||||||
- [parallel/test-worker-message-port-receive-message.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-receive-message.js)
|
|
||||||
- [parallel/test-worker-message-port-terminate-transfer-list.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-terminate-transfer-list.js)
|
- [parallel/test-worker-message-port-terminate-transfer-list.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-terminate-transfer-list.js)
|
||||||
- [parallel/test-worker-message-port-transfer-closed.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-transfer-closed.js)
|
- [parallel/test-worker-message-port-transfer-closed.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-transfer-closed.js)
|
||||||
- [parallel/test-worker-message-port-transfer-duplicate.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-transfer-duplicate.js)
|
- [parallel/test-worker-message-port-transfer-duplicate.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-worker-message-port-transfer-duplicate.js)
|
||||||
|
|
Loading…
Reference in a new issue