mirror of
https://github.com/denoland/deno.git
synced 2025-12-23 08:48:24 +00:00
refactor: merge deno_broadcast_channel into deno_web (#31198)
This commit deprecated `deno_broadcast_channel` crate and merges it into `deno_web`. This will allow us to limit number of crates we need to publish and (maybe) improve compile and link times. The actual `ext/broadcast_channel` directory will be removed in a follow up PR, once a new version is published and points to deno_web crate.
This commit is contained in:
parent
2eb0341526
commit
4d2b56911f
24 changed files with 299 additions and 330 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
|
@ -1795,19 +1795,6 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno_broadcast_channel"
|
||||
version = "0.215.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
"deno_features",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno_bundle_runtime"
|
||||
version = "0.8.0"
|
||||
|
|
@ -2799,7 +2786,6 @@ dependencies = [
|
|||
"async-trait",
|
||||
"color-print",
|
||||
"deno_ast",
|
||||
"deno_broadcast_channel",
|
||||
"deno_bundle_runtime",
|
||||
"deno_canvas",
|
||||
"deno_core",
|
||||
|
|
@ -3071,6 +3057,7 @@ dependencies = [
|
|||
"deno_bench_util",
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
"deno_features",
|
||||
"deno_permissions",
|
||||
"deno_webidl",
|
||||
"encoding_rs",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ members = [
|
|||
"cli/lib",
|
||||
"cli/rt",
|
||||
"cli/snapshot",
|
||||
"ext/broadcast_channel",
|
||||
"ext/bundle",
|
||||
"ext/canvas",
|
||||
"ext/cron",
|
||||
|
|
@ -86,7 +85,6 @@ denokv_remote = "0.12.0"
|
|||
denokv_sqlite = { default-features = false, version = "0.12.0" }
|
||||
|
||||
# exts
|
||||
deno_broadcast_channel = { version = "0.215.0", path = "./ext/broadcast_channel" }
|
||||
deno_bundle_runtime = { version = "0.8.0", path = "./ext/bundle" }
|
||||
deno_canvas = { version = "0.90.0", path = "./ext/canvas" }
|
||||
deno_cron = { version = "0.101.0", path = "./ext/cron" }
|
||||
|
|
@ -438,8 +436,6 @@ opt-level = 3
|
|||
opt-level = 3
|
||||
[profile.release.package.deno_bench_util]
|
||||
opt-level = 3
|
||||
[profile.release.package.deno_broadcast_channel]
|
||||
opt-level = 3
|
||||
[profile.release.package.deno_core]
|
||||
opt-level = 3
|
||||
[profile.release.package.deno_crypto]
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use deno_runtime::UNSTABLE_FEATURES;
|
|||
use deno_runtime::WorkerExecutionMode;
|
||||
use deno_runtime::WorkerLogLevel;
|
||||
use deno_runtime::colors;
|
||||
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||
use deno_runtime::deno_core;
|
||||
use deno_runtime::deno_core::CompiledWasmModuleStore;
|
||||
use deno_runtime::deno_core::Extension;
|
||||
|
|
@ -38,6 +37,7 @@ use deno_runtime::deno_process::NpmProcessStateProviderRc;
|
|||
use deno_runtime::deno_telemetry::OtelConfig;
|
||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||
use deno_runtime::deno_web::BlobStore;
|
||||
use deno_runtime::deno_web::InMemoryBroadcastChannel;
|
||||
use deno_runtime::fmt_errors::format_js_error;
|
||||
use deno_runtime::inspector_server::InspectorServer;
|
||||
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
|
||||
|
|
|
|||
|
|
@ -2,22 +2,13 @@
|
|||
|
||||
[package]
|
||||
name = "deno_broadcast_channel"
|
||||
version = "0.215.0"
|
||||
version = "0.216.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
readme = "README.md"
|
||||
repository.workspace = true
|
||||
description = "Implementation of BroadcastChannel API for Deno"
|
||||
description = "DEPRECATED: Use deno_web instead"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
async-trait.workspace = true
|
||||
deno_core.workspace = true
|
||||
deno_error.workspace = true
|
||||
deno_features.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
uuid.workspace = true
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
# deno_broadcast_channel
|
||||
# deno_cache
|
||||
|
||||
This crate implements the BroadcastChannel functions of Deno.
|
||||
|
||||
Spec: https://html.spec.whatwg.org/multipage/web-messaging.html
|
||||
This crate has been deprecated, use
|
||||
[deno_web](https://crates.io/crates/deno_web) instead.
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use deno_core::parking_lot::Mutex;
|
||||
use tokio::sync::broadcast;
|
||||
use tokio::sync::mpsc;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::BroadcastChannel;
|
||||
use crate::BroadcastChannelError;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InMemoryBroadcastChannel(Arc<Mutex<broadcast::Sender<Message>>>);
|
||||
|
||||
pub struct InMemoryBroadcastChannelResource {
|
||||
rx: tokio::sync::Mutex<(
|
||||
broadcast::Receiver<Message>,
|
||||
mpsc::UnboundedReceiver<()>,
|
||||
)>,
|
||||
cancel_tx: mpsc::UnboundedSender<()>,
|
||||
uuid: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Message {
|
||||
name: Arc<String>,
|
||||
data: Arc<Vec<u8>>,
|
||||
uuid: Uuid,
|
||||
}
|
||||
|
||||
impl Default for InMemoryBroadcastChannel {
|
||||
fn default() -> Self {
|
||||
let (tx, _) = broadcast::channel(256);
|
||||
Self(Arc::new(Mutex::new(tx)))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl BroadcastChannel for InMemoryBroadcastChannel {
|
||||
type Resource = InMemoryBroadcastChannelResource;
|
||||
|
||||
fn subscribe(&self) -> Result<Self::Resource, BroadcastChannelError> {
|
||||
let (cancel_tx, cancel_rx) = mpsc::unbounded_channel();
|
||||
let broadcast_rx = self.0.lock().subscribe();
|
||||
let rx = tokio::sync::Mutex::new((broadcast_rx, cancel_rx));
|
||||
let uuid = Uuid::new_v4();
|
||||
Ok(Self::Resource {
|
||||
rx,
|
||||
cancel_tx,
|
||||
uuid,
|
||||
})
|
||||
}
|
||||
|
||||
fn unsubscribe(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
) -> Result<(), BroadcastChannelError> {
|
||||
Ok(resource.cancel_tx.send(())?)
|
||||
}
|
||||
|
||||
async fn send(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
name: String,
|
||||
data: Vec<u8>,
|
||||
) -> Result<(), BroadcastChannelError> {
|
||||
let name = Arc::new(name);
|
||||
let data = Arc::new(data);
|
||||
let uuid = resource.uuid;
|
||||
self.0.lock().send(Message { name, data, uuid })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn recv(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
) -> Result<Option<crate::Message>, BroadcastChannelError> {
|
||||
let mut g = resource.rx.lock().await;
|
||||
let (broadcast_rx, cancel_rx) = &mut *g;
|
||||
loop {
|
||||
let result = tokio::select! {
|
||||
r = broadcast_rx.recv() => r,
|
||||
_ = cancel_rx.recv() => return Ok(None),
|
||||
};
|
||||
use tokio::sync::broadcast::error::RecvError::*;
|
||||
match result {
|
||||
Err(Closed) => return Ok(None),
|
||||
Err(Lagged(_)) => (), // Backlogged, messages dropped.
|
||||
Ok(message) if message.uuid == resource.uuid => (), // Self-send.
|
||||
Ok(message) => {
|
||||
let name = String::clone(&message.name);
|
||||
let data = Vec::clone(&message.data);
|
||||
return Ok(Some((name, data)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl deno_core::Resource for InMemoryBroadcastChannelResource {}
|
||||
|
|
@ -1,163 +1 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
mod in_memory_broadcast_channel;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use deno_core::JsBuffer;
|
||||
use deno_core::OpState;
|
||||
use deno_core::Resource;
|
||||
use deno_core::ResourceId;
|
||||
use deno_core::op2;
|
||||
use deno_error::JsErrorBox;
|
||||
use deno_features::FeatureChecker;
|
||||
pub use in_memory_broadcast_channel::InMemoryBroadcastChannel;
|
||||
pub use in_memory_broadcast_channel::InMemoryBroadcastChannelResource;
|
||||
use tokio::sync::broadcast::error::SendError as BroadcastSendError;
|
||||
use tokio::sync::mpsc::error::SendError as MpscSendError;
|
||||
|
||||
pub const UNSTABLE_FEATURE_NAME: &str = "broadcast-channel";
|
||||
|
||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||
pub enum BroadcastChannelError {
|
||||
#[class(inherit)]
|
||||
#[error(transparent)]
|
||||
Resource(
|
||||
#[from]
|
||||
#[inherit]
|
||||
deno_core::error::ResourceError,
|
||||
),
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
MPSCSendError(MpscSendError<Box<dyn std::fmt::Debug + Send + Sync>>),
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
BroadcastSendError(
|
||||
BroadcastSendError<Box<dyn std::fmt::Debug + Send + Sync>>,
|
||||
),
|
||||
#[class(inherit)]
|
||||
#[error(transparent)]
|
||||
Other(#[inherit] JsErrorBox),
|
||||
}
|
||||
|
||||
impl<T: std::fmt::Debug + Send + Sync + 'static> From<MpscSendError<T>>
|
||||
for BroadcastChannelError
|
||||
{
|
||||
fn from(value: MpscSendError<T>) -> Self {
|
||||
BroadcastChannelError::MPSCSendError(MpscSendError(Box::new(value.0)))
|
||||
}
|
||||
}
|
||||
impl<T: std::fmt::Debug + Send + Sync + 'static> From<BroadcastSendError<T>>
|
||||
for BroadcastChannelError
|
||||
{
|
||||
fn from(value: BroadcastSendError<T>) -> Self {
|
||||
BroadcastChannelError::BroadcastSendError(BroadcastSendError(Box::new(
|
||||
value.0,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait BroadcastChannel: Clone {
|
||||
type Resource: Resource;
|
||||
|
||||
fn subscribe(&self) -> Result<Self::Resource, BroadcastChannelError>;
|
||||
|
||||
fn unsubscribe(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
) -> Result<(), BroadcastChannelError>;
|
||||
|
||||
async fn send(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
name: String,
|
||||
data: Vec<u8>,
|
||||
) -> Result<(), BroadcastChannelError>;
|
||||
|
||||
async fn recv(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
) -> Result<Option<Message>, BroadcastChannelError>;
|
||||
}
|
||||
|
||||
pub type Message = (String, Vec<u8>);
|
||||
|
||||
#[op2(fast)]
|
||||
#[smi]
|
||||
pub fn op_broadcast_subscribe<BC>(
|
||||
state: &mut OpState,
|
||||
) -> Result<ResourceId, BroadcastChannelError>
|
||||
where
|
||||
BC: BroadcastChannel + 'static,
|
||||
{
|
||||
state
|
||||
.borrow::<Arc<FeatureChecker>>()
|
||||
.check_or_exit(UNSTABLE_FEATURE_NAME, "BroadcastChannel");
|
||||
let bc = state.borrow::<BC>();
|
||||
let resource = bc.subscribe()?;
|
||||
Ok(state.resource_table.add(resource))
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
pub fn op_broadcast_unsubscribe<BC>(
|
||||
state: &mut OpState,
|
||||
#[smi] rid: ResourceId,
|
||||
) -> Result<(), BroadcastChannelError>
|
||||
where
|
||||
BC: BroadcastChannel + 'static,
|
||||
{
|
||||
let resource = state.resource_table.get::<BC::Resource>(rid)?;
|
||||
let bc = state.borrow::<BC>();
|
||||
bc.unsubscribe(&resource)
|
||||
}
|
||||
|
||||
#[op2(async)]
|
||||
pub async fn op_broadcast_send<BC>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
#[string] name: String,
|
||||
#[buffer] buf: JsBuffer,
|
||||
) -> Result<(), BroadcastChannelError>
|
||||
where
|
||||
BC: BroadcastChannel + 'static,
|
||||
{
|
||||
let resource = state.borrow().resource_table.get::<BC::Resource>(rid)?;
|
||||
let bc = state.borrow().borrow::<BC>().clone();
|
||||
bc.send(&resource, name, buf.to_vec()).await
|
||||
}
|
||||
|
||||
#[op2(async)]
|
||||
#[serde]
|
||||
pub async fn op_broadcast_recv<BC>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
) -> Result<Option<Message>, BroadcastChannelError>
|
||||
where
|
||||
BC: BroadcastChannel + 'static,
|
||||
{
|
||||
let resource = state.borrow().resource_table.get::<BC::Resource>(rid)?;
|
||||
let bc = state.borrow().borrow::<BC>().clone();
|
||||
bc.recv(&resource).await
|
||||
}
|
||||
|
||||
deno_core::extension!(deno_broadcast_channel,
|
||||
deps = [ deno_webidl, deno_web ],
|
||||
parameters = [BC: BroadcastChannel],
|
||||
ops = [
|
||||
op_broadcast_subscribe<BC>,
|
||||
op_broadcast_unsubscribe<BC>,
|
||||
op_broadcast_send<BC>,
|
||||
op_broadcast_recv<BC>,
|
||||
],
|
||||
esm = [ "01_broadcast_channel.js" ],
|
||||
options = {
|
||||
bc: BC,
|
||||
},
|
||||
state = |state, options| {
|
||||
state.put(options.bc);
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import {
|
|||
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
||||
import { notImplemented } from "ext:deno_node/_utils.ts";
|
||||
import { EventEmitter } from "node:events";
|
||||
import { BroadcastChannel } from "ext:deno_broadcast_channel/01_broadcast_channel.js";
|
||||
import { BroadcastChannel } from "ext:deno_web/01_broadcast_channel.js";
|
||||
import { untransferableSymbol } from "ext:deno_node/internal_binding/util.ts";
|
||||
import process from "node:process";
|
||||
import { createRequire } from "node:module";
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ bytes.workspace = true
|
|||
chrono = { workspace = true, features = ["now"] }
|
||||
deno_core.workspace = true
|
||||
deno_error.workspace = true
|
||||
deno_features.workspace = true
|
||||
deno_permissions.workspace = true
|
||||
encoding_rs.workspace = true
|
||||
flate2 = { workspace = true, features = ["default"] }
|
||||
|
|
|
|||
|
|
@ -33,7 +33,12 @@ fn setup() -> Vec<Extension> {
|
|||
|
||||
vec![
|
||||
deno_webidl::deno_webidl::init(),
|
||||
deno_web::deno_web::init::<Permissions>(Default::default(), None, None),
|
||||
deno_web::deno_web::init::<Permissions, deno_web::InMemoryBroadcastChannel>(
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
Default::default(),
|
||||
),
|
||||
bench_setup::init(),
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,12 @@ fn setup() -> Vec<Extension> {
|
|||
|
||||
vec![
|
||||
deno_webidl::deno_webidl::init(),
|
||||
deno_web::deno_web::init::<Permissions>(Default::default(), None, None),
|
||||
deno_web::deno_web::init::<Permissions, deno_web::InMemoryBroadcastChannel>(
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
Default::default(),
|
||||
),
|
||||
bench_setup::init(),
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,12 @@ fn setup() -> Vec<Extension> {
|
|||
|
||||
vec![
|
||||
deno_webidl::deno_webidl::init(),
|
||||
deno_web::deno_web::init::<Permissions>(Default::default(), None, None),
|
||||
deno_web::deno_web::init::<Permissions, deno_web::InMemoryBroadcastChannel>(
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
Default::default(),
|
||||
),
|
||||
bench_setup::init(),
|
||||
]
|
||||
}
|
||||
|
|
|
|||
240
ext/web/broadcast_channel.rs
Normal file
240
ext/web/broadcast_channel.rs
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use deno_core::JsBuffer;
|
||||
use deno_core::OpState;
|
||||
use deno_core::Resource;
|
||||
use deno_core::ResourceId;
|
||||
use deno_core::op2;
|
||||
use deno_core::parking_lot::Mutex;
|
||||
use deno_error::JsErrorBox;
|
||||
use deno_features::FeatureChecker;
|
||||
use tokio::sync::broadcast;
|
||||
use tokio::sync::broadcast::error::SendError as BroadcastSendError;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::mpsc::error::SendError as MpscSendError;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub const UNSTABLE_FEATURE_NAME: &str = "broadcast-channel";
|
||||
|
||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||
pub enum BroadcastChannelError {
|
||||
#[class(inherit)]
|
||||
#[error(transparent)]
|
||||
Resource(
|
||||
#[from]
|
||||
#[inherit]
|
||||
deno_core::error::ResourceError,
|
||||
),
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
MPSCSendError(MpscSendError<Box<dyn std::fmt::Debug + Send + Sync>>),
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
BroadcastSendError(
|
||||
BroadcastSendError<Box<dyn std::fmt::Debug + Send + Sync>>,
|
||||
),
|
||||
#[class(inherit)]
|
||||
#[error(transparent)]
|
||||
Other(#[inherit] JsErrorBox),
|
||||
}
|
||||
|
||||
impl<T: std::fmt::Debug + Send + Sync + 'static> From<MpscSendError<T>>
|
||||
for BroadcastChannelError
|
||||
{
|
||||
fn from(value: MpscSendError<T>) -> Self {
|
||||
BroadcastChannelError::MPSCSendError(MpscSendError(Box::new(value.0)))
|
||||
}
|
||||
}
|
||||
impl<T: std::fmt::Debug + Send + Sync + 'static> From<BroadcastSendError<T>>
|
||||
for BroadcastChannelError
|
||||
{
|
||||
fn from(value: BroadcastSendError<T>) -> Self {
|
||||
BroadcastChannelError::BroadcastSendError(BroadcastSendError(Box::new(
|
||||
value.0,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait BroadcastChannel: Clone {
|
||||
type Resource: Resource;
|
||||
|
||||
fn subscribe(&self) -> Result<Self::Resource, BroadcastChannelError>;
|
||||
|
||||
fn unsubscribe(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
) -> Result<(), BroadcastChannelError>;
|
||||
|
||||
async fn send(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
name: String,
|
||||
data: Vec<u8>,
|
||||
) -> Result<(), BroadcastChannelError>;
|
||||
|
||||
async fn recv(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
) -> Result<Option<Message>, BroadcastChannelError>;
|
||||
}
|
||||
|
||||
pub type Message = (String, Vec<u8>);
|
||||
|
||||
#[op2(fast)]
|
||||
#[smi]
|
||||
pub fn op_broadcast_subscribe<BC>(
|
||||
state: &mut OpState,
|
||||
) -> Result<ResourceId, BroadcastChannelError>
|
||||
where
|
||||
BC: BroadcastChannel + 'static,
|
||||
{
|
||||
state
|
||||
.borrow::<Arc<FeatureChecker>>()
|
||||
.check_or_exit(UNSTABLE_FEATURE_NAME, "BroadcastChannel");
|
||||
let bc = state.borrow::<BC>();
|
||||
let resource = bc.subscribe()?;
|
||||
Ok(state.resource_table.add(resource))
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
pub fn op_broadcast_unsubscribe<BC>(
|
||||
state: &mut OpState,
|
||||
#[smi] rid: ResourceId,
|
||||
) -> Result<(), BroadcastChannelError>
|
||||
where
|
||||
BC: BroadcastChannel + 'static,
|
||||
{
|
||||
let resource = state.resource_table.get::<BC::Resource>(rid)?;
|
||||
let bc = state.borrow::<BC>();
|
||||
bc.unsubscribe(&resource)
|
||||
}
|
||||
|
||||
#[op2(async)]
|
||||
pub async fn op_broadcast_send<BC>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
#[string] name: String,
|
||||
#[buffer] buf: JsBuffer,
|
||||
) -> Result<(), BroadcastChannelError>
|
||||
where
|
||||
BC: BroadcastChannel + 'static,
|
||||
{
|
||||
let resource = state.borrow().resource_table.get::<BC::Resource>(rid)?;
|
||||
let bc = state.borrow().borrow::<BC>().clone();
|
||||
bc.send(&resource, name, buf.to_vec()).await
|
||||
}
|
||||
|
||||
#[op2(async)]
|
||||
#[serde]
|
||||
pub async fn op_broadcast_recv<BC>(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
#[smi] rid: ResourceId,
|
||||
) -> Result<Option<Message>, BroadcastChannelError>
|
||||
where
|
||||
BC: BroadcastChannel + 'static,
|
||||
{
|
||||
let resource = state.borrow().resource_table.get::<BC::Resource>(rid)?;
|
||||
let bc = state.borrow().borrow::<BC>().clone();
|
||||
bc.recv(&resource).await
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InMemoryBroadcastChannel(
|
||||
Arc<Mutex<broadcast::Sender<InMemoryChannelMessage>>>,
|
||||
);
|
||||
|
||||
pub struct InMemoryBroadcastChannelResource {
|
||||
rx: tokio::sync::Mutex<(
|
||||
broadcast::Receiver<InMemoryChannelMessage>,
|
||||
mpsc::UnboundedReceiver<()>,
|
||||
)>,
|
||||
cancel_tx: mpsc::UnboundedSender<()>,
|
||||
uuid: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct InMemoryChannelMessage {
|
||||
name: Arc<String>,
|
||||
data: Arc<Vec<u8>>,
|
||||
uuid: Uuid,
|
||||
}
|
||||
|
||||
impl Default for InMemoryBroadcastChannel {
|
||||
fn default() -> Self {
|
||||
let (tx, _) = broadcast::channel(256);
|
||||
Self(Arc::new(Mutex::new(tx)))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl BroadcastChannel for InMemoryBroadcastChannel {
|
||||
type Resource = InMemoryBroadcastChannelResource;
|
||||
|
||||
fn subscribe(&self) -> Result<Self::Resource, BroadcastChannelError> {
|
||||
let (cancel_tx, cancel_rx) = mpsc::unbounded_channel();
|
||||
let broadcast_rx = self.0.lock().subscribe();
|
||||
let rx = tokio::sync::Mutex::new((broadcast_rx, cancel_rx));
|
||||
let uuid = Uuid::new_v4();
|
||||
Ok(Self::Resource {
|
||||
rx,
|
||||
cancel_tx,
|
||||
uuid,
|
||||
})
|
||||
}
|
||||
|
||||
fn unsubscribe(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
) -> Result<(), BroadcastChannelError> {
|
||||
Ok(resource.cancel_tx.send(())?)
|
||||
}
|
||||
|
||||
async fn send(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
name: String,
|
||||
data: Vec<u8>,
|
||||
) -> Result<(), BroadcastChannelError> {
|
||||
let name = Arc::new(name);
|
||||
let data = Arc::new(data);
|
||||
let uuid = resource.uuid;
|
||||
self
|
||||
.0
|
||||
.lock()
|
||||
.send(InMemoryChannelMessage { name, data, uuid })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn recv(
|
||||
&self,
|
||||
resource: &Self::Resource,
|
||||
) -> Result<Option<Message>, BroadcastChannelError> {
|
||||
let mut g = resource.rx.lock().await;
|
||||
let (broadcast_rx, cancel_rx) = &mut *g;
|
||||
loop {
|
||||
let result = tokio::select! {
|
||||
r = broadcast_rx.recv() => r,
|
||||
_ = cancel_rx.recv() => return Ok(None),
|
||||
};
|
||||
use tokio::sync::broadcast::error::RecvError::*;
|
||||
match result {
|
||||
Err(Closed) => return Ok(None),
|
||||
Err(Lagged(_)) => (), // Backlogged, messages dropped.
|
||||
Ok(message) if message.uuid == resource.uuid => (), // Self-send.
|
||||
Ok(message) => {
|
||||
let name = String::clone(&message.name);
|
||||
let data = Vec::clone(&message.data);
|
||||
return Ok(Some((name, data)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl deno_core::Resource for InMemoryBroadcastChannelResource {}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
mod blob;
|
||||
mod broadcast_channel;
|
||||
pub mod cache;
|
||||
mod compression;
|
||||
mod console;
|
||||
|
|
@ -40,6 +41,8 @@ use crate::blob::op_blob_read_part;
|
|||
use crate::blob::op_blob_remove_part;
|
||||
use crate::blob::op_blob_revoke_object_url;
|
||||
use crate::blob::op_blob_slice_part;
|
||||
pub use crate::broadcast_channel::BroadcastChannel;
|
||||
pub use crate::broadcast_channel::InMemoryBroadcastChannel;
|
||||
pub use crate::cache::CreateCache;
|
||||
pub use crate::message_port::JsMessageData;
|
||||
pub use crate::message_port::MessagePort;
|
||||
|
|
@ -59,7 +62,7 @@ use crate::timers::op_time_origin;
|
|||
|
||||
deno_core::extension!(deno_web,
|
||||
deps = [ deno_webidl ],
|
||||
parameters = [P: TimersPermission],
|
||||
parameters = [P: TimersPermission, BC: BroadcastChannel],
|
||||
ops = [
|
||||
op_base64_decode,
|
||||
op_base64_encode,
|
||||
|
|
@ -111,6 +114,10 @@ deno_core::extension!(deno_web,
|
|||
urlpattern::op_urlpattern_parse,
|
||||
urlpattern::op_urlpattern_process_match_input,
|
||||
console::op_preview_entries,
|
||||
broadcast_channel::op_broadcast_subscribe<BC>,
|
||||
broadcast_channel::op_broadcast_unsubscribe<BC>,
|
||||
broadcast_channel::op_broadcast_send<BC>,
|
||||
broadcast_channel::op_broadcast_recv<BC>,
|
||||
],
|
||||
esm = [
|
||||
"00_infra.js",
|
||||
|
|
@ -135,12 +142,14 @@ deno_core::extension!(deno_web,
|
|||
"00_url.js",
|
||||
"01_urlpattern.js",
|
||||
"01_console.js",
|
||||
"01_broadcast_channel.js"
|
||||
],
|
||||
lazy_loaded_esm = [ "webtransport.js" ],
|
||||
options = {
|
||||
blob_store: Arc<BlobStore>,
|
||||
maybe_location: Option<Url>,
|
||||
maybe_create_cache: Option<CreateCache>,
|
||||
bc: BC,
|
||||
},
|
||||
state = |state, options| {
|
||||
state.put(options.blob_store);
|
||||
|
|
@ -151,6 +160,7 @@ deno_core::extension!(deno_web,
|
|||
state.put(create_cache);
|
||||
}
|
||||
state.put(StartTime::default());
|
||||
state.put(options.bc);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
deno_ast = { workspace = true, optional = true }
|
||||
deno_broadcast_channel.workspace = true
|
||||
deno_bundle_runtime.workspace = true
|
||||
deno_canvas.workspace = true
|
||||
deno_core.workspace = true
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import * as streams from "ext:deno_web/06_streams.js";
|
|||
import * as fileReader from "ext:deno_web/10_filereader.js";
|
||||
import * as webSocket from "ext:deno_websocket/01_websocket.js";
|
||||
import * as webSocketStream from "ext:deno_websocket/02_websocketstream.js";
|
||||
import * as broadcastChannel from "ext:deno_broadcast_channel/01_broadcast_channel.js";
|
||||
import * as broadcastChannel from "ext:deno_web/01_broadcast_channel.js";
|
||||
import * as file from "ext:deno_web/09_file.js";
|
||||
import * as formData from "ext:deno_fetch/21_formdata.js";
|
||||
import * as request from "ext:deno_fetch/23_request.js";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
pub use deno_broadcast_channel;
|
||||
pub use deno_canvas;
|
||||
pub use deno_core;
|
||||
pub use deno_cron;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ extension!(runtime,
|
|||
deno_websocket,
|
||||
deno_webstorage,
|
||||
deno_crypto,
|
||||
deno_broadcast_channel,
|
||||
deno_node,
|
||||
deno_ffi,
|
||||
deno_net,
|
||||
|
|
|
|||
|
|
@ -27,16 +27,16 @@ pub fn create_runtime_snapshot(
|
|||
let mut extensions: Vec<Extension> = vec![
|
||||
deno_telemetry::deno_telemetry::lazy_init(),
|
||||
deno_webidl::deno_webidl::lazy_init(),
|
||||
deno_web::deno_web::lazy_init::<Permissions>(),
|
||||
deno_web::deno_web::lazy_init::<
|
||||
Permissions,
|
||||
deno_web::InMemoryBroadcastChannel,
|
||||
>(),
|
||||
deno_webgpu::deno_webgpu::lazy_init(),
|
||||
deno_canvas::deno_canvas::lazy_init(),
|
||||
deno_fetch::deno_fetch::lazy_init::<Permissions>(),
|
||||
deno_websocket::deno_websocket::lazy_init::<Permissions>(),
|
||||
deno_webstorage::deno_webstorage::lazy_init(),
|
||||
deno_crypto::deno_crypto::lazy_init(),
|
||||
deno_broadcast_channel::deno_broadcast_channel::lazy_init::<
|
||||
deno_broadcast_channel::InMemoryBroadcastChannel,
|
||||
>(),
|
||||
deno_ffi::deno_ffi::lazy_init::<Permissions>(),
|
||||
deno_net::deno_net::lazy_init::<Permissions>(),
|
||||
deno_tls::deno_tls::lazy_init(),
|
||||
|
|
|
|||
|
|
@ -217,10 +217,11 @@ pub fn get_extensions_in_snapshot() -> Vec<Extension> {
|
|||
vec![
|
||||
deno_telemetry::deno_telemetry::init(),
|
||||
deno_webidl::deno_webidl::init(),
|
||||
deno_web::deno_web::init::<Permissions>(
|
||||
deno_web::deno_web::init::<Permissions, deno_web::InMemoryBroadcastChannel>(
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
None,
|
||||
deno_web::InMemoryBroadcastChannel::default(),
|
||||
),
|
||||
deno_webgpu::deno_webgpu::init(),
|
||||
deno_canvas::deno_canvas::init(),
|
||||
|
|
@ -228,9 +229,6 @@ pub fn get_extensions_in_snapshot() -> Vec<Extension> {
|
|||
deno_websocket::deno_websocket::init::<Permissions>(),
|
||||
deno_webstorage::deno_webstorage::init(None),
|
||||
deno_crypto::deno_crypto::init(None),
|
||||
deno_broadcast_channel::deno_broadcast_channel::init(
|
||||
deno_broadcast_channel::InMemoryBroadcastChannel::default(),
|
||||
),
|
||||
deno_ffi::deno_ffi::init::<Permissions>(None),
|
||||
deno_net::deno_net::init::<Permissions>(None, None),
|
||||
deno_tls::deno_tls::init(),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ use std::sync::atomic::Ordering;
|
|||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
use deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||
use deno_core::CancelHandle;
|
||||
use deno_core::CompiledWasmModuleStore;
|
||||
use deno_core::DetachedBuffer;
|
||||
|
|
@ -49,6 +48,7 @@ use deno_terminal::colors;
|
|||
use deno_tls::RootCertStoreProvider;
|
||||
use deno_tls::TlsKeys;
|
||||
use deno_web::BlobStore;
|
||||
use deno_web::InMemoryBroadcastChannel;
|
||||
use deno_web::JsMessageData;
|
||||
use deno_web::MessagePort;
|
||||
use deno_web::Transferable;
|
||||
|
|
@ -522,10 +522,11 @@ impl WebWorker {
|
|||
deno_telemetry::deno_telemetry::init(),
|
||||
// Web APIs
|
||||
deno_webidl::deno_webidl::init(),
|
||||
deno_web::deno_web::init::<PermissionsContainer>(
|
||||
deno_web::deno_web::init::<PermissionsContainer, InMemoryBroadcastChannel>(
|
||||
services.blob_store,
|
||||
Some(options.main_module.clone()),
|
||||
create_cache,
|
||||
services.broadcast_channel,
|
||||
),
|
||||
deno_webgpu::deno_webgpu::init(),
|
||||
deno_canvas::deno_canvas::init(),
|
||||
|
|
@ -543,9 +544,6 @@ impl WebWorker {
|
|||
deno_websocket::deno_websocket::init::<PermissionsContainer>(),
|
||||
deno_webstorage::deno_webstorage::init(None).disable(),
|
||||
deno_crypto::deno_crypto::init(options.seed),
|
||||
deno_broadcast_channel::deno_broadcast_channel::init(
|
||||
services.broadcast_channel,
|
||||
),
|
||||
deno_ffi::deno_ffi::init::<PermissionsContainer>(
|
||||
services.deno_rt_native_addon_loader.clone(),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ use std::sync::atomic::Ordering;
|
|||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
|
||||
use deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||
use deno_core::CompiledWasmModuleStore;
|
||||
use deno_core::Extension;
|
||||
use deno_core::InspectorSessionKind;
|
||||
|
|
@ -47,6 +46,7 @@ use deno_tls::RootCertStoreProvider;
|
|||
use deno_tls::TlsKeys;
|
||||
use deno_web::BlobStore;
|
||||
use deno_web::CreateCache;
|
||||
use deno_web::InMemoryBroadcastChannel;
|
||||
use deno_web::cache::CacheImpl;
|
||||
use deno_web::cache::SqliteBackedCache;
|
||||
use log::debug;
|
||||
|
|
@ -530,10 +530,14 @@ impl MainWorker {
|
|||
|
||||
js_runtime
|
||||
.lazy_init_extensions(vec![
|
||||
deno_web::deno_web::args::<PermissionsContainer>(
|
||||
deno_web::deno_web::args::<
|
||||
PermissionsContainer,
|
||||
InMemoryBroadcastChannel,
|
||||
>(
|
||||
services.blob_store.clone(),
|
||||
options.bootstrap.location.clone(),
|
||||
create_cache,
|
||||
services.broadcast_channel.clone(),
|
||||
),
|
||||
deno_fetch::deno_fetch::args::<PermissionsContainer>(
|
||||
deno_fetch::Options {
|
||||
|
|
@ -552,9 +556,6 @@ impl MainWorker {
|
|||
options.origin_storage_dir.clone(),
|
||||
),
|
||||
deno_crypto::deno_crypto::args(options.seed),
|
||||
deno_broadcast_channel::deno_broadcast_channel::args(
|
||||
services.broadcast_channel.clone(),
|
||||
),
|
||||
deno_ffi::deno_ffi::args::<PermissionsContainer>(
|
||||
services.deno_rt_native_addon_loader.clone(),
|
||||
),
|
||||
|
|
@ -1050,16 +1051,16 @@ fn common_extensions<
|
|||
deno_telemetry::deno_telemetry::init(),
|
||||
// Web APIs
|
||||
deno_webidl::deno_webidl::init(),
|
||||
deno_web::deno_web::lazy_init::<PermissionsContainer>(),
|
||||
deno_web::deno_web::lazy_init::<
|
||||
PermissionsContainer,
|
||||
InMemoryBroadcastChannel,
|
||||
>(),
|
||||
deno_webgpu::deno_webgpu::init(),
|
||||
deno_canvas::deno_canvas::init(),
|
||||
deno_fetch::deno_fetch::lazy_init::<PermissionsContainer>(),
|
||||
deno_websocket::deno_websocket::lazy_init::<PermissionsContainer>(),
|
||||
deno_webstorage::deno_webstorage::lazy_init(),
|
||||
deno_crypto::deno_crypto::lazy_init(),
|
||||
deno_broadcast_channel::deno_broadcast_channel::lazy_init::<
|
||||
InMemoryBroadcastChannel,
|
||||
>(),
|
||||
deno_ffi::deno_ffi::lazy_init::<PermissionsContainer>(),
|
||||
deno_net::deno_net::lazy_init::<PermissionsContainer>(),
|
||||
deno_tls::deno_tls::init(),
|
||||
|
|
|
|||
|
|
@ -504,7 +504,7 @@
|
|||
"ext:cli/40_lint_selector.js": "../cli/js/40_lint_selector.js",
|
||||
"ext:core/mod.js": "../../deno_core/core/core.d.ts",
|
||||
"ext:core/ops": "./ops.d.ts",
|
||||
"ext:deno_broadcast_channel/01_broadcast_channel.js": "../ext/broadcast_channel/01_broadcast_channel.js",
|
||||
"ext:deno_web/01_broadcast_channel.js": "../ext/deno_web/01_broadcast_channel.js",
|
||||
"ext:deno_canvas/01_image.js": "../ext/canvas/01_image.js",
|
||||
"ext:deno_web/01_console.js": "../ext/console/01_console.js",
|
||||
"ext:deno_cron/01_cron.ts": "../ext/cron/01_cron.ts",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue