mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-27 04:01:11 +08:00
feat: BroadcastChannel 载荷盒与 GC 家族表接线
This commit is contained in:
Generated
+19
-19
@@ -1160,7 +1160,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_builtins"
|
name = "oxide_builtins"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"fast-float",
|
"fast-float",
|
||||||
@@ -1185,7 +1185,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_bytecode"
|
name = "oxide_bytecode"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1193,7 +1193,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cfg"
|
name = "oxide_cfg"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_emit",
|
"oxide_emit",
|
||||||
@@ -1204,7 +1204,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cli"
|
name = "oxide_cli"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
@@ -1226,7 +1226,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_code_cache"
|
name = "oxide_code_cache"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lru",
|
"lru",
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
@@ -1235,7 +1235,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_compiler"
|
name = "oxide_compiler"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1255,7 +1255,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_dce"
|
name = "oxide_dce"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1269,7 +1269,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_emit"
|
name = "oxide_emit"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
@@ -1284,7 +1284,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_engine"
|
name = "oxide_engine"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_compiler",
|
"oxide_compiler",
|
||||||
@@ -1296,7 +1296,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_ir"
|
name = "oxide_ir"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1305,7 +1305,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_kernel"
|
name = "oxide_kernel"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
@@ -1319,7 +1319,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_liveness"
|
name = "oxide_liveness"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1331,7 +1331,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_log"
|
name = "oxide_log"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
@@ -1340,7 +1340,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_parser"
|
name = "oxide_parser"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
"oxc_ast",
|
"oxc_ast",
|
||||||
@@ -1355,7 +1355,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_regalloc"
|
name = "oxide_regalloc"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1371,7 +1371,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_runtime_api"
|
name = "oxide_runtime_api"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
@@ -1384,7 +1384,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_test262"
|
name = "oxide_test262"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_compiler",
|
"oxide_compiler",
|
||||||
@@ -1402,7 +1402,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_types"
|
name = "oxide_types"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
@@ -1415,7 +1415,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_vm"
|
name = "oxide_vm"
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.8.87"
|
version = "0.8.88"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
rust-version = "1.80"
|
rust-version = "1.80"
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
//! BroadcastChannel 载荷盒:mpsc 发送/接收对与通道名存于对象 `native_fn` 槽,
|
||||||
|
//! 向 GC 家族表暴露 size/drop 两自由函数。
|
||||||
|
//!
|
||||||
|
//! 载荷盒无对象边(mpsc 非 GC 边、通道名为 Rust `String`),家族表 `ops_for`
|
||||||
|
//! 臂三边函数全 `None`,mark 链不消费本模块。
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
use oxide_kernel::message_queue;
|
||||||
|
use oxide_types::object::JsObject;
|
||||||
|
|
||||||
|
use crate::message_value::MessageValue;
|
||||||
|
|
||||||
|
/// BroadcastChannel 载荷盒:存于对象 `native_fn` 槽(`Box::into_raw`,realm
|
||||||
|
/// 局部单线程)。`name` 是通道名(Rust `String`,注册表键),`tx` 是本通道的
|
||||||
|
/// mpsc 发送端(`Send`),`rx` 是配对的 mpsc 接收端(`!Send`,realm 局部),
|
||||||
|
/// `closed` 是关闭标志。`tx` 与 `rx` 是 `channel()` 配对,`tx.send(v)` 写入本
|
||||||
|
/// 通道 `rx`。
|
||||||
|
///
|
||||||
|
#[expect(dead_code)] // 字段由构造器与方法消费,载荷盒当前仅建盒与释放
|
||||||
|
struct BroadcastChannelInner {
|
||||||
|
name: String,
|
||||||
|
tx: message_queue::Sender<MessageValue>,
|
||||||
|
rx: message_queue::Receiver<MessageValue>,
|
||||||
|
closed: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 取载荷盒指针:仅 BroadcastChannel 标签对象返回 `Some`,其余标签返回 `None`。
|
||||||
|
fn broadcast_channel_payload_ptr(obj: &JsObject) -> Option<*mut BroadcastChannelInner> {
|
||||||
|
if !obj.is_broadcast_channel() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
obj.native_fn().map(|ptr| ptr.as_ptr() as *mut BroadcastChannelInner)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 只读核算 BroadcastChannel 载荷盒字节(不释放)。
|
||||||
|
///
|
||||||
|
/// mpsc 内部缓冲在 Arc 通道内、盒不可寻址,不计入(有界轻微少计,只推迟
|
||||||
|
/// GC 触发,不影响触发正确性)。
|
||||||
|
pub fn broadcast_channel_native_size(obj: &JsObject) -> u64 {
|
||||||
|
let Some(ptr) = broadcast_channel_payload_ptr(obj) else {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
if ptr.is_null() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mem::size_of::<BroadcastChannelInner>() as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 释放 BroadcastChannel 载荷盒(`Box<BroadcastChannelInner>`),返回释放字节数。
|
||||||
|
///
|
||||||
|
/// 盒 drop 时发送端与接收端各减一次 mpsc 引用计数,`name` String 随盒释放。
|
||||||
|
/// 槽置空保证重复调用零释放(幂等)。
|
||||||
|
pub fn drop_broadcast_channel_native(obj: &mut JsObject) -> u64 {
|
||||||
|
let bytes = broadcast_channel_native_size(obj);
|
||||||
|
if bytes == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let Some(ptr) = broadcast_channel_payload_ptr(obj) else {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
// SAFETY: ptr 非空(broadcast_channel_native_size 已验证),Box::from_raw 恰好释放一次。
|
||||||
|
unsafe { drop(Box::from_raw(ptr)) };
|
||||||
|
obj.set_native_fn(None);
|
||||||
|
bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||||
|
use oxide_types::object::NativeFnPtr;
|
||||||
|
use oxide_types::value::JsValue;
|
||||||
|
|
||||||
|
/// 构造真实通道并把双端移入载荷盒。
|
||||||
|
fn channel_payload() -> BroadcastChannelInner {
|
||||||
|
let (tx, rx) = message_queue::channel::<MessageValue>();
|
||||||
|
BroadcastChannelInner {
|
||||||
|
name: "test".to_owned(),
|
||||||
|
tx,
|
||||||
|
rx,
|
||||||
|
closed: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 手工构造带载荷盒的 BroadcastChannel 对象(不经 Vm,只验 GC 两自由函数)。
|
||||||
|
fn channel_object_with_payload(inner: BroadcastChannelInner) -> JsObject {
|
||||||
|
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::undefined());
|
||||||
|
obj.type_tag = JsObject::OBJ_TYPE_BROADCAST_CHANNEL;
|
||||||
|
let payload_ptr = Box::into_raw(Box::new(inner));
|
||||||
|
// SAFETY: 载荷盒形态与 native_fn 槽存储约定一致,测试结束前恰好释放一次。
|
||||||
|
obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(payload_ptr as *const ()) }));
|
||||||
|
obj
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn size_and_drop_idempotent() {
|
||||||
|
let mut obj = channel_object_with_payload(channel_payload());
|
||||||
|
let struct_bytes = mem::size_of::<BroadcastChannelInner>() as u64;
|
||||||
|
assert_eq!(broadcast_channel_native_size(&obj), struct_bytes);
|
||||||
|
// 首次 drop 释放结构体;槽置空后二次 drop 零释放。
|
||||||
|
assert_eq!(drop_broadcast_channel_native(&mut obj), struct_bytes);
|
||||||
|
assert_eq!(drop_broadcast_channel_native(&mut obj), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn channel_roundtrip_through_box() {
|
||||||
|
let mut obj = channel_object_with_payload(channel_payload());
|
||||||
|
let ptr = broadcast_channel_payload_ptr(&obj).unwrap();
|
||||||
|
// SAFETY: 载荷盒测试期间存活。
|
||||||
|
unsafe {
|
||||||
|
assert!(!(*ptr).closed);
|
||||||
|
(*ptr).tx.send(MessageValue::Number(1.0)).unwrap();
|
||||||
|
assert!(matches!((*ptr).rx.try_recv().unwrap(), MessageValue::Number(n) if n == 1.0));
|
||||||
|
}
|
||||||
|
drop_broadcast_channel_native(&mut obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn payload_ptr_brand_guard() {
|
||||||
|
// 非 BroadcastChannel 类型标签(PLAIN)对象取载荷指针恒 None。
|
||||||
|
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::undefined());
|
||||||
|
let payload_ptr = Box::into_raw(Box::new(channel_payload()));
|
||||||
|
// SAFETY: 同 channel_object_with_payload 的载荷盒形态。
|
||||||
|
obj.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(payload_ptr as *const ()) }));
|
||||||
|
assert!(broadcast_channel_payload_ptr(&obj).is_none());
|
||||||
|
// SAFETY: 测试构造的盒,恰好释放一次。
|
||||||
|
unsafe { drop(Box::from_raw(payload_ptr)) };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,8 @@ pub mod atomics;
|
|||||||
pub mod bigint;
|
pub mod bigint;
|
||||||
/// Boolean 内置对象实现(constructor 与 prototype 的 valueOf/toString)。
|
/// Boolean 内置对象实现(constructor 与 prototype 的 valueOf/toString)。
|
||||||
pub mod boolean;
|
pub mod boolean;
|
||||||
|
/// BroadcastChannel 载荷盒(mpsc 发送/接收对与通道名,GC size/drop 两自由函数)。
|
||||||
|
pub mod broadcast_channel;
|
||||||
/// builtins 层日志宏(`builtins_error`/`builtins_info` 等),target 为 `oxide::builtins`。
|
/// builtins 层日志宏(`builtins_error`/`builtins_info` 等),target 为 `oxide::builtins`。
|
||||||
pub mod builtins_log;
|
pub mod builtins_log;
|
||||||
/// Console 全局对象实现(log/warn/error/info/debug/trace 方法)。
|
/// Console 全局对象实现(log/warn/error/info/debug/trace 方法)。
|
||||||
|
|||||||
@@ -223,6 +223,10 @@ impl JsObject {
|
|||||||
/// MessagePort 对象:mpsc 双端(发往对端 / 收自对端)与对端端口裸指针
|
/// MessagePort 对象:mpsc 双端(发往对端 / 收自对端)与对端端口裸指针
|
||||||
/// 存于 `native_fn` 槽的载荷盒(`MessagePortInner`),对端端口为双向 GC 边。
|
/// 存于 `native_fn` 槽的载荷盒(`MessagePortInner`),对端端口为双向 GC 边。
|
||||||
pub const OBJ_TYPE_MESSAGE_PORT: u8 = 33;
|
pub const OBJ_TYPE_MESSAGE_PORT: u8 = 33;
|
||||||
|
/// BroadcastChannel 对象:mpsc 发送/接收对与通道名存于 `native_fn` 槽的
|
||||||
|
/// 载荷盒(`BroadcastChannelInner`),无对象边(mpsc 非 GC 边、通道名为
|
||||||
|
/// Rust `String`)。
|
||||||
|
pub const OBJ_TYPE_BROADCAST_CHANNEL: u8 = 34;
|
||||||
/// `is_session_epoch` 字段中的 session 标记位。
|
/// `is_session_epoch` 字段中的 session 标记位。
|
||||||
pub const SESSION_EPOCH_BIT: u8 = 0x01;
|
pub const SESSION_EPOCH_BIT: u8 = 0x01;
|
||||||
/// `is_session_epoch` 字段中的 GC 标记位。
|
/// `is_session_epoch` 字段中的 GC 标记位。
|
||||||
@@ -305,6 +309,11 @@ impl JsObject {
|
|||||||
pub fn is_message_port(&self) -> bool {
|
pub fn is_message_port(&self) -> bool {
|
||||||
self.type_tag == Self::OBJ_TYPE_MESSAGE_PORT
|
self.type_tag == Self::OBJ_TYPE_MESSAGE_PORT
|
||||||
}
|
}
|
||||||
|
/// 是否 BroadcastChannel 对象(`native_fn` 槽存 mpsc 发送/接收对与通道名)。
|
||||||
|
#[inline]
|
||||||
|
pub fn is_broadcast_channel(&self) -> bool {
|
||||||
|
self.type_tag == Self::OBJ_TYPE_BROADCAST_CHANNEL
|
||||||
|
}
|
||||||
/// 是否 DataView 对象。
|
/// 是否 DataView 对象。
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_data_view_obj(&self) -> bool {
|
pub fn is_data_view_obj(&self) -> bool {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! native 载荷家族的单点分类与每家族边函数引用(家族表)。
|
//! native 载荷家族的单点分类与每家族边函数引用(家族表)。
|
||||||
//!
|
//!
|
||||||
//! 分类是复合谓词:header 位(map/set/module_ns)优先于 `type_tag`,
|
//! 分类是复合谓词:header 位(map/set/module_ns)优先于 `type_tag`,
|
||||||
//! 两维互斥、一个对象至多归入一个家族。tag 维显式枚举全部 0..=33,
|
//! 两维互斥、一个对象至多归入一个家族。tag 维显式枚举全部 0..=34,
|
||||||
//! 未登记 tag panic。
|
//! 未登记 tag panic。
|
||||||
//!
|
//!
|
||||||
//! 关键约定:
|
//! 关键约定:
|
||||||
@@ -16,7 +16,7 @@ use oxide_types::value::JsValue;
|
|||||||
|
|
||||||
/// native 载荷家族。
|
/// native 载荷家族。
|
||||||
///
|
///
|
||||||
/// 14 个 native 家族 + 空家族;空家族是无 native 盒类型的显式归类结果。
|
/// 15 个 native 家族 + 空家族;空家族是无 native 盒类型的显式归类结果。
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub(crate) enum NativeBoxFamily {
|
pub(crate) enum NativeBoxFamily {
|
||||||
/// 无 native 载荷盒。
|
/// 无 native 载荷盒。
|
||||||
@@ -51,6 +51,8 @@ pub(crate) enum NativeBoxFamily {
|
|||||||
RegExp,
|
RegExp,
|
||||||
/// MessagePort 端口对象(tag 33,mpsc 双端与对端端口边)。
|
/// MessagePort 端口对象(tag 33,mpsc 双端与对端端口边)。
|
||||||
MessagePort,
|
MessagePort,
|
||||||
|
/// BroadcastChannel 通道对象(tag 34,mpsc 发送/接收对与通道名,无对象边)。
|
||||||
|
BroadcastChannel,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 一个家族的边操作集(每家族函数引用,单一注册面)。
|
/// 一个家族的边操作集(每家族函数引用,单一注册面)。
|
||||||
@@ -83,7 +85,7 @@ pub(crate) fn classify(obj: &JsObject) -> NativeBoxFamily {
|
|||||||
/// 按类型 tag 分类 native 载荷家族。
|
/// 按类型 tag 分类 native 载荷家族。
|
||||||
///
|
///
|
||||||
/// # 边界与前提
|
/// # 边界与前提
|
||||||
/// - 0..=33 全 tag 显式枚举;未登记 tag(34 及以上)panic。
|
/// - 0..=34 全 tag 显式枚举;未登记 tag(35 及以上)panic。
|
||||||
pub(crate) fn classify_by_tag(tag: u8) -> NativeBoxFamily {
|
pub(crate) fn classify_by_tag(tag: u8) -> NativeBoxFamily {
|
||||||
match tag {
|
match tag {
|
||||||
JsObject::OBJ_TYPE_ARRAY_BUFFER => NativeBoxFamily::ArrayBuffer,
|
JsObject::OBJ_TYPE_ARRAY_BUFFER => NativeBoxFamily::ArrayBuffer,
|
||||||
@@ -121,6 +123,7 @@ pub(crate) fn classify_by_tag(tag: u8) -> NativeBoxFamily {
|
|||||||
JsObject::OBJ_TYPE_HTML_DDA => NativeBoxFamily::None,
|
JsObject::OBJ_TYPE_HTML_DDA => NativeBoxFamily::None,
|
||||||
JsObject::OBJ_TYPE_RAW_JSON => NativeBoxFamily::None,
|
JsObject::OBJ_TYPE_RAW_JSON => NativeBoxFamily::None,
|
||||||
JsObject::OBJ_TYPE_MESSAGE_PORT => NativeBoxFamily::MessagePort,
|
JsObject::OBJ_TYPE_MESSAGE_PORT => NativeBoxFamily::MessagePort,
|
||||||
|
JsObject::OBJ_TYPE_BROADCAST_CHANNEL => NativeBoxFamily::BroadcastChannel,
|
||||||
_ => panic!("unregistered type tag: {tag}"),
|
_ => panic!("unregistered type tag: {tag}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,6 +214,13 @@ pub(crate) fn ops_for(family: NativeBoxFamily) -> NativeBoxOps {
|
|||||||
string_edges: None,
|
string_edges: None,
|
||||||
cell_edges: None,
|
cell_edges: None,
|
||||||
},
|
},
|
||||||
|
// BroadcastChannel 载荷盒:无对象边(mpsc 非 GC 边、通道名为 Rust String),
|
||||||
|
// 三边函数全空,仅 size/drop 链消费。
|
||||||
|
NativeBoxFamily::BroadcastChannel => NativeBoxOps {
|
||||||
|
object_edges: None,
|
||||||
|
string_edges: None,
|
||||||
|
cell_edges: None,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,13 +251,14 @@ mod tests {
|
|||||||
JsObject::OBJ_TYPE_SHARED_ARRAY_BUFFER => NativeBoxFamily::SharedArrayBuffer,
|
JsObject::OBJ_TYPE_SHARED_ARRAY_BUFFER => NativeBoxFamily::SharedArrayBuffer,
|
||||||
JsObject::OBJ_TYPE_REGEXP | JsObject::OBJ_TYPE_REGEX_STUB => NativeBoxFamily::RegExp,
|
JsObject::OBJ_TYPE_REGEXP | JsObject::OBJ_TYPE_REGEX_STUB => NativeBoxFamily::RegExp,
|
||||||
JsObject::OBJ_TYPE_MESSAGE_PORT => NativeBoxFamily::MessagePort,
|
JsObject::OBJ_TYPE_MESSAGE_PORT => NativeBoxFamily::MessagePort,
|
||||||
|
JsObject::OBJ_TYPE_BROADCAST_CHANNEL => NativeBoxFamily::BroadcastChannel,
|
||||||
_ => NativeBoxFamily::None,
|
_ => NativeBoxFamily::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tag_dimension_every_tag_hits_exactly_one_family() {
|
fn tag_dimension_every_tag_hits_exactly_one_family() {
|
||||||
for tag in 0..=33u8 {
|
for tag in 0..=34u8 {
|
||||||
let obj = obj_with_tag(tag);
|
let obj = obj_with_tag(tag);
|
||||||
let family = classify(&obj);
|
let family = classify(&obj);
|
||||||
assert_eq!(family, expected_family_for_tag(tag), "tag {tag} 家族不一致");
|
assert_eq!(family, expected_family_for_tag(tag), "tag {tag} 家族不一致");
|
||||||
@@ -281,7 +292,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "unregistered type tag")]
|
#[should_panic(expected = "unregistered type tag")]
|
||||||
fn unregistered_tag_panics() {
|
fn unregistered_tag_panics() {
|
||||||
let obj = obj_with_tag(34);
|
let obj = obj_with_tag(35);
|
||||||
classify(&obj);
|
classify(&obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ use crate::native_box_dispatch;
|
|||||||
use crate::vm::RootGroup;
|
use crate::vm::RootGroup;
|
||||||
use crate::vm::Vm;
|
use crate::vm::Vm;
|
||||||
use oxide_builtins::{
|
use oxide_builtins::{
|
||||||
array_buffer, data_view, disposable_stack, map, message_channel, module, regexp, set, typed_array, weak_map,
|
array_buffer, broadcast_channel, data_view, disposable_stack, map, message_channel, module, regexp, set,
|
||||||
|
typed_array, weak_map,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// session 级 mark-sweep GC 的状态与统计。
|
/// session 级 mark-sweep GC 的状态与统计。
|
||||||
@@ -130,6 +131,7 @@ impl SessionGc {
|
|||||||
bytes += crate::async_generator::async_generator_native_size(obj);
|
bytes += crate::async_generator::async_generator_native_size(obj);
|
||||||
bytes += weak_map::weak_map_native_size(obj);
|
bytes += weak_map::weak_map_native_size(obj);
|
||||||
bytes += message_channel::message_port_native_size(obj);
|
bytes += message_channel::message_port_native_size(obj);
|
||||||
|
bytes += broadcast_channel::broadcast_channel_native_size(obj);
|
||||||
|
|
||||||
bytes
|
bytes
|
||||||
}
|
}
|
||||||
@@ -570,6 +572,7 @@ impl SessionGc {
|
|||||||
freed_bytes += crate::async_generator::drop_async_generator_native(obj);
|
freed_bytes += crate::async_generator::drop_async_generator_native(obj);
|
||||||
freed_bytes += weak_map::drop_weak_map_native(obj);
|
freed_bytes += weak_map::drop_weak_map_native(obj);
|
||||||
freed_bytes += message_channel::drop_message_port_native(obj);
|
freed_bytes += message_channel::drop_message_port_native(obj);
|
||||||
|
freed_bytes += broadcast_channel::drop_broadcast_channel_native(obj);
|
||||||
|
|
||||||
freed_bytes
|
freed_bytes
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user