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

173 lines
9.3 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::sync::Arc;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::mem::Epoch;
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
/// builtins 依赖的 `Vm` 能力集合。
///
/// 方法签名是 `Vm` 上同名固有方法的逐字节拷贝;`impl VmHost for Vm` 委托给
/// 它们。trait 刻意保持扁平且非对象安全——builtins 始终接受 `&mut impl VmHost`。
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)
}
}
// 对象分配 / 字符串创建
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;
/// 取 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_kernel::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_kernel::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;
// 内核访问器
fn kernel_core(&self) -> &Arc<KernelCore>;
fn session(&self) -> &KernelSession;
fn epoch(&self) -> &Epoch;
// 属性解析
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>;
fn get_own_property_slot(&self, obj: &JsObject, prop_name_si: u32) -> Option<u32>;
// 属性访问
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>;
/// 取回在 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>);
// 错误处理
fn checked_object_ptr(&mut self, val: JsValue, error_msg: &str) -> Result<Option<*mut JsObject>, String>;
fn raise_type_error(&mut self, msg: &str) -> Result<(), String>;
fn error_message_text(&self, kind: &str, msg: &str) -> String;
fn call_stack_function_names(&self) -> Vec<String>;
fn promote_if_needed_for_write_ptr(&mut self, target_ptr: *mut JsObject, value: JsValue) -> JsValue;
fn step_rng(&mut self);
fn math_rng_value(&self) -> f64;
fn sub_module_function_name(&self, gen: u32, sub_idx: u16) -> String;
/// 动态编译一个函数体(`Function` 构造器用):把参数列表与函数体编译为可调用
/// 函数对象。编译或解析失败返回 `Err`,由调用方转为 `SyntaxError`。
fn create_dynamic_function(&mut self, params: &[String], body: &str) -> Result<JsValue, String>;
/// 动态编译脚本(`eval` 字符串模式):按脚本模式编译,var/函数声明落全局对象。
/// 编译或解析失败返回 `Err`,由调用方转为 `SyntaxError`。
fn create_dynamic_script(&mut self, code: &str) -> Result<JsValue, String>;
/// `None` 表示无描述(`Symbol()`/`Symbol(undefined)`),`Some(desc)` 为字符串描述。
fn symbol_intern(&mut self, desc: Option<String>) -> u32;
fn symbol_description(&self, idx: u32) -> Option<&str>;
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>;
}