Files
OxideJS-New/crates/oxide_runtime_api/src/host.rs
T

466 lines
24 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! `VmHost` trait:builtins 依赖的 `Vm` 能力集合,trait 面向泛型而非对象安全。
use std::ffi::c_void;
use std::sync::Arc;
use oxide_kernel::KernelCore;
use oxide_types::mem::P;
use oxide_types::object::{Cell, JsObject, PropAttributes};
use oxide_types::value::JsValue;
/// shape 节点只读投影:shape forge 节点字段的中立镜像(免跨 crate 引用具体类型)。
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ShapeNode {
/// shape 整数标识。
pub id: u32,
/// 本节点新增的属性名(字符串键 si;`u32::MAX` 为哨兵,表示无属性)。
pub property_name: u32,
/// 父 shape id(根节点为 `None`)。
pub parent: Option<u32>,
/// 根到本 shape 的非哨兵属性数。
pub depth: u32,
}
/// 内建对象种类:session builtin world 中 builtins 读取的原型与构造器槽位。
///
/// 变体与 builtin world 字段一一对应,仅覆盖 builtins 实际读取的槽位;
/// 新增内建读取面时在此追加变体(尾操作,零位移)。
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ProtoKind {
// 基础原型
ObjectProto,
ArrayProto,
FunctionProto,
StringProto,
NumberProto,
BooleanProto,
SymbolProto,
BigIntProto,
// 错误族原型
ErrorProto,
TypeErrorProto,
ReferenceErrorProto,
RangeErrorProto,
SyntaxErrorProto,
UriErrorProto,
EvalErrorProto,
SuppressedErrorProto,
// 集合 / 正则 / 日期原型
DateProto,
SetProto,
MapProto,
RegExpProto,
// 缓冲与视图原型
ArrayBufferProto,
SharedArrayBufferProto,
DataViewProto,
TypedArrayProto,
Int8ArrayProto,
Uint8ArrayProto,
Uint8ClampedArrayProto,
Int16ArrayProto,
Uint16ArrayProto,
Int32ArrayProto,
Uint32ArrayProto,
Float32ArrayProto,
Float64ArrayProto,
BigInt64ArrayProto,
BigUint64ArrayProto,
// Temporal 原型
InstantProto,
PlainDateProto,
PlainTimeProto,
DurationProto,
ZonedDateTimeProto,
PlainDateTimeProto,
PlainMonthDayProto,
PlainYearMonthProto,
// 迭代器原型
IteratorProto,
ArrayIteratorProto,
MapIteratorProto,
SetIteratorProto,
StringIteratorProto,
RegExpStringIteratorProto,
IteratorHelperProto,
DisposableStackProto,
AsyncDisposableStackProto,
// 构造器
RegExpConstructor,
ArrayBufferConstructor,
SharedArrayBufferConstructor,
Int8ArrayConstructor,
Uint8ArrayConstructor,
Uint8ClampedArrayConstructor,
Int16ArrayConstructor,
Uint16ArrayConstructor,
Int32ArrayConstructor,
Uint32ArrayConstructor,
Float32ArrayConstructor,
Float64ArrayConstructor,
BigInt64ArrayConstructor,
BigUint64ArrayConstructor,
// 消息通道原型
MessagePortProto,
// 广播通道原型
BroadcastChannelProto,
}
/// builtins 依赖的 `Vm` 能力集合。
///
/// 方法签名是 `Vm` 上同名固有方法的逐字节拷贝;`impl VmHost for Vm` 委托给
/// 它们。trait 刻意保持扁平且非对象安全——builtins 始终接受 `&mut impl VmHost`。
///
/// 边界:本 trait 是单 realm 接口——所有方法只作用于所属 VM 的当前 realm,
/// 不含跨 realm(跨线程)值传递方法。跨 realm 值传递由
/// `oxide_builtins::message_value` 的独立函数实现(源 realm 侧 `detach_message`、
/// 目标 realm 侧 `rehydrate_message`,经 `MessageValue` 中间表示),不挂本 trait,
/// 免污染单 realm 接口。trait 亦无 realm 查找方法:`realm_id` 只用于符号编码
/// (符号身份 = (realm 编号, 局部下标) 的 realm 维度),不用于查找他 realm 对象。
pub trait VmHost {
// 寄存器访问
fn reg(&self, idx: u8) -> JsValue;
fn set_reg(&mut self, idx: u8, val: JsValue);
/// 当前 native 调用 spill 溢出区的实参个数(寄存器窗口 253 之外的部分)。
///
/// # 边界与前提
/// - 仅在 native 实现内部、实参仍有效时读取;无溢出时为 0。
fn native_overflow_count(&self) -> usize;
/// 读 spill 溢出区第 `i` 个实参(0 基,相对溢出区起点)。
///
/// # 边界与前提
/// - `i` 必须小于 [`Self::native_overflow_count`]。
fn native_overflow_at(&self, i: usize) -> JsValue;
/// 当前 native 调用的完整实参个数(寄存器窗口 + spill 溢出区,不含 receiver)。
///
/// 供支持大实参集的 builtin(如 `String.fromCodePoint`)遍历全部实参;
/// 尚未改用本接口的 builtin 仍按 `args` 索引读寄存器。
fn native_arg_count(&self, args: &[u8]) -> usize {
args.len().saturating_sub(1) + self.native_overflow_count()
}
/// 第 `idx` 个实参(0 基,不含 receiver):窗口内读寄存器,窗口外读 spill 溢出区。
///
/// # 边界与前提
/// - `idx` 必须小于 [`Self::native_arg_count`]。
fn native_arg_at(&self, args: &[u8], idx: usize) -> JsValue {
let window = args.len().saturating_sub(1);
if idx < window {
self.reg(args[idx + 1])
} else {
self.native_overflow_at(idx - window)
}
}
/// 当前 native 调用是否以构造形态发起(NEW/SUPER native 臂与 `construct_with`
/// native 臂置 true,普通调用入口置 false,调用结束即恢复)。
///
/// # 边界与前提
/// - 仅在 native 实现内部读取;构造器 builtin 据此判定向 receiver 物化,
/// 不得用寄存器推断(native 调用与调用方共享寄存器文件,new.target
/// 槽在类构造器帧内残留类构造器对象)。
fn constructing_native(&self) -> bool;
// 对象分配 / 字符串创建
fn alloc_object(&mut self, obj: JsObject) -> *mut JsObject;
fn new_string(&mut self, s: &str) -> JsValue;
/// move 接收 `String` 创建会话字符串,避免一次整串克隆。
fn new_string_owned(&mut self, s: String) -> JsValue;
/// 有限 double 转串,带十六槽 last-value 缓存:命中返回已登记为 GC 根的
/// session 串,miss 走原数值转串链并写槽。
///
/// # 注意事项
/// - 非有限值(NaN/±Infinity)走永久常量表,不进槽。
/// - `full_reset` 在 session 串释放前清空槽;轻量 `reset` 保留槽
/// (session 串跨 eval 存活,缓存串仍有效)。
fn number_to_string_cached(&mut self, d: f64) -> JsValue;
/// 取 ASCII 单字符的永久字符串值:命中返回共享 perm 串(零分配、可指针
/// 短路比较),非 ASCII 返回 `None` 由调用方回落普通字符串创建。
///
/// # 注意事项
/// `&self` 可借用期调用;`None` 回落 `new_string` 是 `&mut` 路径,须先结束
/// 本次 `&self` 借用(返回值即时消费即可)。
fn single_char(&self, ch: char) -> Option<JsValue> {
if ch.is_ascii() {
Some(JsValue::string(oxide_types::string_forge::single_char_ptr(ch as u8)))
} else {
None
}
}
/// 借出字符串值的 UTF-16 单元序列(Flat 惰性编码 / FlatU16 直接借用 /
/// Cons 扁平化缓存),生命周期绑定到 `&self` 借用。调用方须保证
/// `val` 为字符串值。
fn string_units(&self, val: JsValue) -> std::borrow::Cow<'_, [u16]>;
/// 取单单元的永久字符串值:ASCII 单元命中共享 perm 串(零分配、可指针
/// 短路),非 ASCII 返回 `None` 由调用方回落单元创建。
fn single_unit(&self, u: u16) -> Option<JsValue> {
if u < 0x80 {
Some(JsValue::string(oxide_types::string_forge::single_char_ptr(u as u8)))
} else {
None
}
}
/// 以单元序列创建会话字符串(智能路由:含孤立 surrogate 落 FlatU16)。
fn new_string_units(&mut self, units: &[u16]) -> JsValue;
/// 同 `new_string_units`,以 owned 单元序列接收,避免一次克隆。
fn new_string_units_owned(&mut self, units: Vec<u16>) -> JsValue;
/// 分配 BigInt 值(num_bigint::BigInt box 登记到 VM,返回携带指针的 `JsValue`)。
fn new_bigint(&mut self, v: num_bigint::BigInt) -> JsValue;
/// 读取 BigInt 值;调用方须保证 `val.is_bigint()`。
fn bigint_value(&mut self, val: JsValue) -> &num_bigint::BigInt;
// 内核能力面(perm interner / shape forge / builtin world / global object)
/// intern 字符串键,返回其 si(perm interner,零分配共享键空间)。
fn perm_intern(&self, s: &str) -> u32;
/// 由 si 反查字符串键文本(si 非已登记字符串键时为 `None`)。
fn perm_lookup(&self, si: u32) -> Option<&str>;
/// shape 转换:在 `parent` 上追加属性 `prop_si` 返回新 shape id;
/// 相同 (parent, prop_si) 组合恒返回同一 id。
fn make_shape(&self, parent: u32, prop_si: u32) -> u32;
/// 查 shape `shape_id` 中属性 `prop_si` 的槽位(该 shape 链上无此属性为 `None`)。
fn lookup_position(&self, shape_id: u32, prop_si: u32) -> Option<u32>;
/// 读 shape 节点(id 非有效 shape 为 `None`)。
fn get_shape(&self, id: u32) -> Option<ShapeNode>;
/// perm interner 裸指针(调用方解引用读键空间;interner 随 VM 存活)。
fn perm_interner_ptr(&self) -> *const c_void;
/// shape forge 裸指针(调用方解引用读 shape 链;forge 随 VM 存活)。
fn shape_forge_ptr(&self) -> *const c_void;
/// 读当前 session builtin world 的内建对象指针(原型 / 构造器)。
fn builtin_proto(&self, kind: ProtoKind) -> *mut JsObject;
/// 读 String 默认迭代器裸指针(绑定层未捕获时为 null 指针)。
fn string_default_iterator(&self) -> *const JsObject;
/// 读当前 session 全局对象(引用计数持久指针,跨调用存活)。
fn global_object(&self) -> P<JsObject>;
/// 读内核核共享指针(SAB 字节区构造用:`SharedBuffer` 随核的
/// `shared_buffer_bytes` 账目登记与释放)。
fn kernel_core(&self) -> Arc<KernelCore>;
// 属性解析
fn property_key_si(&mut self, val: JsValue) -> u32;
/// ToPropertyKey 完整路径:键值 → 内部属性键 si。对象经 ToPrimitive(string
/// hint),转换异常以 `Err` 返回(调用方须取 `take_uncaught_value` 传播原异常)。
/// 与 `property_key_si` 的区别:后者对转换失败退化为空键,不传播异常。
fn to_property_key_si(&mut self, val: JsValue) -> Result<u32, String>;
/// 字符串→键规范化:规范数字串(`"5"`)映射整数键,其余文本以 `encode_key`
/// 形态入键空间(无 FFFD 的良形文本恒等,含 FFFD 与运行时单元路径同形态,
/// 见 `string_key_units`)。
/// 供建键入口(fromEntries/json/rest excluded)与 `property_key_si` 的字符串分支统一口径。
fn string_key_si(&mut self, s: &str) -> u32;
fn resolve_property(&self, obj: &JsObject, prop_name_si: u32) -> Option<JsValue>;
/// 存在性判定(规范 HasProperty):自身与原型链任一层 P 为自有属性即存在;
/// 数组元素区 hole 视同缺失,TypedArray 整数索引按视图长度判在界。
///
/// deferred namespace 目标先触发 `EnsureDeferredNamespaceEvaluation`(cyclic
/// 守卫抛 TypeError / 失败缓存原值重抛),触发失败以 `Err` 返回。
fn has_property(&mut self, obj: &JsObject, prop_name_si: u32) -> Result<bool, String>;
fn get_own_property_slot(&self, obj: &JsObject, prop_name_si: u32) -> Option<u32>;
/// 判定 mapped arguments 映射是否存活:创建帧仍在帧栈上且帧身份匹配。
///
/// # 边界与前提
/// - `state` 为 arguments 对象 `native_data` 中的同步状态盒;`frame_depth`
/// 为创建帧下标,帧弹出后映射失效。
fn arguments_mapping_alive(&self, state: &oxide_types::arguments_map::ArgumentsMapState) -> bool;
// 属性访问
fn ordinary_get(&mut self, obj: &JsObject, prop_name_si: u32, receiver: JsValue) -> Result<JsValue, String>;
/// `strict` 为写方严格模式:写失败时严格抛错,sloppy 静默 no-op。内置调用方
/// 一律传 true(内置写语义恒抛错,与调用上下文模式无关)。
fn ordinary_set(
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, strict: bool,
) -> Result<(), String>;
// 属性定义
fn define_data_property(
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, attributes: PropAttributes,
) -> Result<(), String>;
fn define_accessor_property(
&mut self, obj: &mut JsObject, prop_name_si: u32, get: JsValue, set: JsValue, attributes: PropAttributes,
) -> Result<(), String>;
fn set_or_create_prop_value(&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue);
/// 全局 builtin 属性 A 侧写/删成功后,把当前帧对应镜像槽反向同步为 `val`
///(维护"槽 = A 侧原始存储"不变式)。
///
/// # 边界与前提
/// - `obj` 非会话全局对象时立即 no-op(接收者指针判等,热路径零额外成本)。
/// - 键未登记在活动模块 builtin 镜像名集时无槽可写,no-op。
/// # 副作用
/// - 写当前帧寄存器文件的镜像槽。
fn sync_global_builtin_mirror(&mut self, obj: &JsObject, key_si: u32, val: JsValue);
// 查找 / 强制转换
fn lookup_str(&self, val: JsValue) -> Option<String>;
fn coerce_primitive_bounded(&mut self, value: JsValue, prefer_string: bool) -> Result<JsValue, String>;
fn coerce_number_bounded(&mut self, value: JsValue) -> Result<f64, String>;
// 调用基础设施
fn call_function_sync(&mut self, callee: JsValue, receiver: JsValue, args: &[JsValue]) -> Result<JsValue, String>;
/// deferred namespace 求值触发(`EnsureDeferredNamespaceEvaluation`):
/// 对 deferred 且未求值的 module namespace 同步执行依赖模块函数,缓存结果
/// 命名空间或失败错误对象。
///
/// # 步骤
/// 1. 非 module namespace / 非 deferred / 无状态盒 → no-op(`Ok`)。
/// 2. symbol-like 键(Symbol 或 deferred 的 `"then"`)→ no-op(走 Ordinary* 路径)。
/// 3. 已求值:失败缓存原值重抛(`Err`),成功 no-op。
/// 4. cyclic 守卫:`[[Module]]` 为 undefined 哨兵且标记在场 → TypeError;
/// 标记等于 `[[Module]]` 函数(自求值中)→ TypeError。
/// 5. 求值:`call_function_sync([[Module]])`,成功缓存 `[[Namespace]]`,
/// 失败缓存原错误值(还原 uncaught 侧通道供调用方原值重抛)。
///
/// # 边界与前提
/// - `key_si` 为 `None` 表示 `[[OwnPropertyKeys]]` 触发(无键,恒触发)。
///
/// # 副作用
/// - 写状态盒 `[[Evaluated]]` / `[[Namespace]]` / 失败错误缓存;可能执行用户
/// 模块代码(含分配与 GC)。
fn ensure_deferred_ns_evaluation(&mut self, obj: &JsObject, key_si: Option<u32>) -> Result<(), String>;
/// 读「正在求值模块」cyclic 守卫标记(`None` = 无模块求值中)。
fn evaluating_module(&self) -> Option<JsValue>;
/// 置「正在求值模块」cyclic 守卫标记(save/restore 由调用方负责)。
fn set_evaluating_module(&mut self, val: Option<JsValue>);
/// 构造调用(Construct(C, args)):native 构造器以新对象为 receiver 值传递调用,
/// bytecode 构造器压构造帧执行(含 derived 构造器 super() 语义与 new.target
/// 传播),返回值非对象时回退到新对象。
///
/// # 边界与前提
/// - `ctor` 必须为可构造值(箭头 / 非构造 native / 普通值在入口处拒绝,
/// 返回 `Err`);`args` 为完整实参列表。
///
/// # 副作用
/// - bytecode 构造器压帧内嵌 dispatch:调用方执行状态在帧边界保存/恢复
/// (寄存器窗口 / 表代际 / spill)。
/// - 失败时已消费 `last_uncaught_value`,`Err` 直接携带原始抛出值
/// (保原值身份,不做文本降级);调用方不得再取槽。
fn construct_ctor(&mut self, ctor: JsValue, args: &[JsValue]) -> Result<JsValue, JsValue>;
/// 带 newTarget 覆写的构造调用(Construct(C, args, newTarget)):this 与
/// new.target 均按 `new_target` 推导;不覆写时调用方传构造器本身(与
/// `construct_ctor` 逐位等价)。
///
/// # 边界与前提
/// - `ctor` 必须为可构造值(入口拒绝,返回 `Err`);`new_target` 的可构造性
/// 由调用方入口校验;`args` 为完整实参列表。
///
/// # 副作用
/// - 同 `construct_ctor`:bytecode 构造器压帧内嵌 dispatch,失败时消费
/// `last_uncaught_value`,`Err` 直接携带原始抛出值(保原值身份,不做
/// 文本降级);调用方不得再取槽。
fn construct_ctor_nt(&mut self, ctor: JsValue, new_target: JsValue, args: &[JsValue]) -> Result<JsValue, JsValue>;
/// 取回在 String 展平调用边界上保留下来的原始抛出 JsValue,
/// 使迭代器包装器能重新抛出原错误而非二次包装。
fn take_uncaught_value(&mut self) -> Option<JsValue>;
/// 恢复被忽略调用暂存的原始抛出值(与 [`Self::take_uncaught_value`] 配对)。
///
/// # 注意事项
/// 忽略调用(如 IteratorClose 的 `return()`)抛错时不得让自身值覆盖槽——
/// 调用前暂存、调用后恢复,保证在途异常值跨忽略调用存活。
fn restore_uncaught_value(&mut self, value: Option<JsValue>);
/// 取回数组 length define 强转期用户代码抛出的原始异常。
///
/// # 注意事项
/// - 与 [`Self::take_uncaught_value`] 分离:后者可能残留其它操作忽略调用时
/// 写入的值,本槽仅由 length 强转失败写入,入口据此区分「强转异常」与
/// 「描述符收敛失败」。
fn take_pending_length_exception(&mut self) -> Option<JsValue>;
/// 清空 uncaught 槽。define 通道强转入口先清后转:强转失败后槽内值必为
/// 本次强转产生的原值,先前操作的残留不得被误转存为本次原值(与 length
/// 路径同纪律)。
fn clear_uncaught_value(&mut self);
/// 把 uncaught 槽移入 define 专用槽(强转期用户回调抛出的原值):
/// Object/Reflect define 入口失败时先取专用槽原值重抛,不投影为 false
/// 或改写成引擎错误。
fn move_uncaught_to_pending_length(&mut self);
// 错误处理
fn checked_object_ptr(&mut self, val: JsValue, error_msg: &str) -> Result<Option<*mut JsObject>, String>;
/// 读当前分派指令位置(pc)。供有界强转调用方在强转前后采样:深度 0
/// 用户回调抛错已就地展开时 pc 必已变化,调用方须立即停止执行后续步骤
/// (强转结果为残值,继续即假值写或二次抛错)。
fn pc(&self) -> usize;
fn raise_type_error(&mut self, msg: &str) -> Result<(), String>;
/// 恢复已捕获的原始异常值(强转失败载荷)并走异常展开,保原值 kind:
/// 深度 0 置原值入异常通道就地展开到外围 catch;深度 >0 返回 kind 前缀
/// 文本,由原生调用边界恢复为异常对象。
///
/// # 边界与前提
/// - `exc` 须为调用方已提取的原始异常值(如经 `take_uncaught_value`);
/// 本入口不重取 uncaught 槽。
///
/// # 副作用
/// - 深度 0 写 `exception_value`/`pending_error_kind`,pc 经展开改写。
fn raise_captured(&mut self, exc: JsValue) -> Result<(), String>;
fn error_message_text(&self, kind: &str, msg: &str) -> String;
fn call_stack_function_names(&self) -> Vec<String>;
/// 函数对象是否为严格模式函数(经子模块 `is_strict` 判定);native 函数
/// (无子模块)视为严格。供 caller/arguments 受限访问器按严格性分流抛错。
fn function_is_strict(&self, obj: &JsObject) -> bool;
/// caller/arguments 访问是否受限:严格函数对象,或生成器 / 异步 /
/// 异步生成器函数对象([[Prototype]] 为三个动态函数原型之一)。
fn function_is_restricted(&self, obj: &JsObject) -> bool;
fn step_rng(&mut self);
fn math_rng_value(&self) -> f64;
fn sub_module_function_name(&self, gen: u32, sub_idx: u16) -> String;
/// 取当前字节码帧 `cell_stack.last()[cell_idx]` 的共享 cell 指针。
///
/// # 边界与前提
/// - 仅在同一 VM 世代的字节码帧执行期读取:native 调用不压 `cell_stack`,故
/// builtin 内读到的是调用方模块帧;`cell_idx` 越界或槽为空返回 `None`。
fn module_frame_cell(&self, cell_idx: u32) -> Option<*mut Cell>;
/// 动态编译一个函数体(`Function` / `GeneratorFunction` / `AsyncFunction` /
/// `AsyncGeneratorFunction` 构造器用):把参数列表与函数体编译为可调用
/// 函数对象。`is_generator` / `is_async` 决定 wrap 源码的函数形态
/// (`function` / `function*` / `async function` / `async function*`),
/// 函数对象原型与 `prototype` 属性面按编译标志自动分流。
/// 编译或解析失败返回 `Err`,由调用方转为 `SyntaxError`。
fn create_dynamic_function(
&mut self, params: &[String], body: &str, is_generator: bool, is_async: bool,
) -> Result<JsValue, String>;
/// 动态编译脚本(`eval` 字符串模式):按脚本模式编译,var/函数声明落全局对象。
/// 编译或解析失败返回 `Err`,由调用方转为 `SyntaxError`。
fn create_dynamic_script(&mut self, code: &str) -> Result<JsValue, String>;
/// 读取本 VM 所属 realm 的编号(符号身份 = (realm 编号, 局部下标) 的 realm 维度)。
///
/// 供 `oxide_builtins` 侧构造 realm 感知符号键 / 符号值时取 realm 编号。
fn realm_id(&self) -> u32;
/// `None` 表示无描述(`Symbol()`/`Symbol(undefined)`),`Some(desc)` 为字符串描述。
fn symbol_intern(&mut self, desc: Option<String>) -> u32;
/// 符号描述字符串(符号表入 realm 后数据在 `RefCell` 内,返回克隆串免临时 `Ref` 悬垂)。
fn symbol_description(&self, idx: u32) -> Option<String>;
fn symbol_lookup_global(&self, key: &str) -> Option<u32>;
fn symbol_register_global(&mut self, key: String, idx: u32);
fn symbol_key_for_id(&self, idx: u32) -> Option<String>;
// Atomics waiter 面(waitAsync 登记 / notify 唤醒)
/// 新建 pending Promise,供 `Atomics.waitAsync` 异步臂的 value 槽;结算不
/// 经能力闭包,由 notify 唤醒直调引擎结算核。
fn atomics_new_waiter_promise(&mut self) -> JsValue;
/// 登记 waitAsync waiter:键 = (缓冲对象指针, 元素字节偏移),同键 FIFO 追加。
///
/// # 注意事项
/// `buffer` 须为登记时刻视图的 `buffer` 现指针(与 notify 侧同一读径),
/// 同 run 无 GC 时两侧指针恒匹配。
fn atomics_register_waiter(&mut self, buffer: *mut JsObject, offset: usize, promise: JsValue);
/// 唤醒 (缓冲, 偏移) 处登记的前 `count` 个 waiter(`<= 0` 不唤醒、`+Inf`
/// 全唤醒),逐个以 "ok" 结算(反应入队随 run 收尾 drain);返回唤醒数。
fn atomics_wake_waiters(&mut self, buffer: *mut JsObject, offset: usize, count: f64) -> usize;
// BroadcastChannel 注册表(per-realm 弱引用)
/// 把通道对象指针按通道名登记进 per-realm 注册表(弱引用,不保活)。
///
/// # 边界与前提
/// - `port` 为构造器登记后的 session 对象指针;同一指针的重复登记由
/// 调用方保证不发生。
/// # 副作用
/// - 写注册表(内部可变);同名通道追加到该名下。
fn bc_register(&self, name: &str, port: *mut JsObject);
/// 从注册表移除通道对象指针(close 注销);指针不在表内时 no-op。
///
/// # 副作用
/// - 写注册表(内部可变);幂等,重复注销不报错。
fn bc_unregister(&self, name: &str, port: *mut JsObject);
/// 查同名通道对象指针列表(返回克隆;无匹配为空列表)。
///
/// # 边界与前提
/// - 列表元素为弱引用裸指针,调用方不得跨用户调用持有(GC 可释放
/// 通道对象,须在下一次使用前重新查表校验)。
fn bc_lookup(&self, name: &str) -> Vec<*mut JsObject>;
}