//! `oxide_runtime_api::VmHost` 委托实现:宿主接口各项委托到 `Vm` 同名固有方法。 use std::ffi::c_void; use std::sync::Arc; use oxide_kernel::KernelCore; use oxide_runtime_api::{ProtoKind, ShapeNode}; use oxide_types::mem::P; use oxide_types::object::{Cell, JsObject, PropAttributes}; use oxide_types::value::JsValue; use super::Vm; impl oxide_runtime_api::VmHost for Vm { fn reg(&self, idx: u8) -> JsValue { self.reg(idx) } fn set_reg(&mut self, idx: u8, val: JsValue) { self.set_reg(idx, val); } fn native_overflow_count(&self) -> usize { self.native_overflow_count } fn native_overflow_at(&self, i: usize) -> JsValue { self.spill_stack[self.native_overflow_base + i] } fn constructing_native(&self) -> bool { self.constructing_native } fn alloc_object(&mut self, obj: JsObject) -> *mut JsObject { self.alloc_object(obj) } fn new_string(&mut self, s: &str) -> JsValue { self.new_string(s) } fn new_string_owned(&mut self, s: String) -> JsValue { Vm::new_string_owned(self, s) } fn number_to_string_cached(&mut self, d: f64) -> JsValue { Vm::number_to_string_cached(self, d) } fn new_bigint(&mut self, v: num_bigint::BigInt) -> JsValue { Vm::new_bigint(self, v) } fn bigint_value(&mut self, val: JsValue) -> &num_bigint::BigInt { Vm::bigint_value(self, val) } fn perm_intern(&self, s: &str) -> u32 { self.kernel_core.perm_interner().intern(s).0 } fn perm_lookup(&self, si: u32) -> Option<&str> { self.kernel_core.perm_interner().lookup(si) } fn make_shape(&self, parent: u32, prop_si: u32) -> u32 { self.kernel_core.shape_forge().make_shape(parent, prop_si) } fn lookup_position(&self, shape_id: u32, prop_si: u32) -> Option { self.kernel_core.shape_forge().lookup_position(shape_id, prop_si) } fn get_shape(&self, id: u32) -> Option { self.kernel_core.shape_forge().get_shape(id).map(|s| ShapeNode { id: s.id, property_name: s.property_name, parent: s.parent, depth: s.depth, }) } fn perm_interner_ptr(&self) -> *const c_void { Arc::as_ptr(self.kernel_core.perm_interner()) as *const c_void } fn shape_forge_ptr(&self) -> *const c_void { Arc::as_ptr(self.kernel_core.shape_forge()) as *const c_void } fn builtin_proto(&self, kind: ProtoKind) -> *mut JsObject { // session 守卫存活至方法返回:world 借用不跨语句长存。 let session = self.session(); let world = session.builtin_world(); let p = match kind { ProtoKind::ObjectProto => &world.object_proto, ProtoKind::ArrayProto => &world.array_proto, ProtoKind::FunctionProto => &world.function_proto, ProtoKind::StringProto => &world.string_proto, ProtoKind::NumberProto => &world.number_proto, ProtoKind::BooleanProto => &world.boolean_proto, ProtoKind::SymbolProto => &world.symbol_proto, ProtoKind::BigIntProto => &world.bigint_proto, ProtoKind::ErrorProto => &world.error_proto, ProtoKind::TypeErrorProto => &world.type_error_proto, ProtoKind::ReferenceErrorProto => &world.reference_error_proto, ProtoKind::RangeErrorProto => &world.range_error_proto, ProtoKind::SyntaxErrorProto => &world.syntax_error_proto, ProtoKind::UriErrorProto => &world.uri_error_proto, ProtoKind::EvalErrorProto => &world.eval_error_proto, ProtoKind::SuppressedErrorProto => &world.suppressed_error_proto, ProtoKind::DateProto => &world.date_proto, ProtoKind::SetProto => &world.set_proto, ProtoKind::MapProto => &world.map_proto, ProtoKind::RegExpProto => &world.regexp_proto, ProtoKind::ArrayBufferProto => &world.array_buffer_proto, ProtoKind::SharedArrayBufferProto => &world.shared_array_buffer_proto, ProtoKind::DataViewProto => &world.data_view_proto, ProtoKind::TypedArrayProto => &world.typed_array_proto, ProtoKind::Int8ArrayProto => &world.int8array_proto, ProtoKind::Uint8ArrayProto => &world.uint8array_proto, ProtoKind::Uint8ClampedArrayProto => &world.uint8clampedarray_proto, ProtoKind::Int16ArrayProto => &world.int16array_proto, ProtoKind::Uint16ArrayProto => &world.uint16array_proto, ProtoKind::Int32ArrayProto => &world.int32array_proto, ProtoKind::Uint32ArrayProto => &world.uint32array_proto, ProtoKind::Float32ArrayProto => &world.float32array_proto, ProtoKind::Float64ArrayProto => &world.float64array_proto, ProtoKind::BigInt64ArrayProto => &world.bigint64array_proto, ProtoKind::BigUint64ArrayProto => &world.biguint64array_proto, ProtoKind::InstantProto => &world.instant_proto, ProtoKind::PlainDateProto => &world.plain_date_proto, ProtoKind::PlainTimeProto => &world.plain_time_proto, ProtoKind::DurationProto => &world.duration_proto, ProtoKind::ZonedDateTimeProto => &world.zoned_date_time_proto, ProtoKind::PlainDateTimeProto => &world.plain_date_time_proto, ProtoKind::PlainMonthDayProto => &world.plain_month_day_proto, ProtoKind::PlainYearMonthProto => &world.plain_year_month_proto, ProtoKind::IteratorProto => &world.iterator_proto, ProtoKind::ArrayIteratorProto => &world.array_iterator_proto, ProtoKind::MapIteratorProto => &world.map_iterator_proto, ProtoKind::SetIteratorProto => &world.set_iterator_proto, ProtoKind::StringIteratorProto => &world.string_iterator_proto, ProtoKind::RegExpStringIteratorProto => &world.regexp_string_iterator_proto, ProtoKind::IteratorHelperProto => &world.iterator_helper_proto, ProtoKind::DisposableStackProto => &world.disposable_stack_proto, ProtoKind::AsyncDisposableStackProto => &world.async_disposable_stack_proto, ProtoKind::RegExpConstructor => &world.regexp_constructor, ProtoKind::ArrayBufferConstructor => &world.array_buffer_constructor, ProtoKind::SharedArrayBufferConstructor => &world.shared_array_buffer_constructor, ProtoKind::Int8ArrayConstructor => &world.int8array_constructor, ProtoKind::Uint8ArrayConstructor => &world.uint8array_constructor, ProtoKind::Uint8ClampedArrayConstructor => &world.uint8clampedarray_constructor, ProtoKind::Int16ArrayConstructor => &world.int16array_constructor, ProtoKind::Uint16ArrayConstructor => &world.uint16array_constructor, ProtoKind::Int32ArrayConstructor => &world.int32array_constructor, ProtoKind::Uint32ArrayConstructor => &world.uint32array_constructor, ProtoKind::Float32ArrayConstructor => &world.float32array_constructor, ProtoKind::Float64ArrayConstructor => &world.float64array_constructor, ProtoKind::BigInt64ArrayConstructor => &world.bigint64array_constructor, ProtoKind::BigUint64ArrayConstructor => &world.biguint64array_constructor, ProtoKind::MessagePortProto => &world.message_port_proto, ProtoKind::BroadcastChannelProto => &world.broadcast_channel_proto, }; P::as_ptr(p) as *mut JsObject } fn string_default_iterator(&self) -> *const JsObject { let session = self.session(); session.builtin_world().string_default_iterator.get() } fn global_object(&self) -> P { let session = self.session(); session.global_object().clone() } fn kernel_core(&self) -> Arc { Arc::clone(self.kernel_core()) } fn pc(&self) -> usize { self.pc } fn take_uncaught_value(&mut self) -> Option { self.last_uncaught_value.take() } fn restore_uncaught_value(&mut self, value: Option) { self.last_uncaught_value = value; } fn take_pending_length_exception(&mut self) -> Option { self.pending_length_exception.take() } fn clear_uncaught_value(&mut self) { self.last_uncaught_value = None; } fn move_uncaught_to_pending_length(&mut self) { self.pending_length_exception = self.last_uncaught_value.take(); } fn property_key_si(&mut self, val: JsValue) -> u32 { // 对象键转换(to_string_full)失败时降级为空键:本 trait 路径供不传播 // 键转换异常的内置站点(Object defineProperty/fromEntries/hasOwn、 // 数值串内部键等)使用;按规范须传播异常的站点用返回 Result 的 // `to_property_key_si`,转换异常原样保留。 self.property_key_si(val) .unwrap_or_else(|_| self.kernel_core.perm_interner().intern("").0) } fn to_property_key_si(&mut self, val: JsValue) -> Result { // ToPropertyKey 完整路径:转换异常(对象 ToPrimitive 抛错 / Symbol 处理) // 原样返回,供需传播异常的 builtins(groupBy / __defineGetter__ 等)使用。 self.property_key_si(val) } fn string_key_si(&mut self, s: &str) -> u32 { // 与运行时字符串键同口径:含 FFFD 的键文本按 encode_key 形态入键空间 // (FFFD 键的 JSON.parse 键与字面量/拼接构造的运行时键身份一致)。 self.string_key_text(s) } fn string_units(&self, val: JsValue) -> std::borrow::Cow<'_, [u16]> { // SAFETY: 调用方保证 val 为字符串值。perm 串由内核持有永不释放;session // 串仅经 &mut self 路径(new_string/GC)释放,&self 借用期间编译器强制 // 不存在 &mut 存续,字符串不会在借用期内回收。 unsafe { (*val.as_string_ptr()).units() } } fn new_string_units(&mut self, units: &[u16]) -> JsValue { Vm::new_string_units(self, units) } fn new_string_units_owned(&mut self, units: Vec) -> JsValue { Vm::new_string_units_owned(self, units) } fn resolve_property(&self, obj: &JsObject, prop_name_si: u32) -> Option { self.resolve_property(obj, prop_name_si) } fn has_property(&self, obj: &JsObject, prop_name_si: u32) -> bool { self.has_property(obj, prop_name_si) } fn get_own_property_slot(&self, obj: &JsObject, prop_name_si: u32) -> Option { self.get_own_property_slot(obj, prop_name_si) } fn ordinary_get(&mut self, obj: &JsObject, prop_name_si: u32, receiver: JsValue) -> Result { self.ordinary_get(obj, prop_name_si, receiver) } fn ordinary_set( &mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, strict: bool, ) -> Result<(), String> { // builtin 调用边界:写失败返回格式化 Err,不就地展开(见 ordinary_set_builtin)。 self.ordinary_set_builtin(obj, prop_name_si, val, receiver, strict) } fn define_data_property( &mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, attributes: PropAttributes, ) -> Result<(), String> { self.define_data_property(obj, prop_name_si, val, attributes) } fn define_accessor_property( &mut self, obj: &mut JsObject, prop_name_si: u32, get: JsValue, set: JsValue, attributes: PropAttributes, ) -> Result<(), String> { self.define_accessor_property(obj, prop_name_si, get, set, attributes) } fn set_or_create_prop_value(&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue) { self.set_or_create_prop_value(obj, prop_name_si, val) } fn sync_global_builtin_mirror(&mut self, obj: &JsObject, key_si: u32, val: JsValue) { self.sync_global_builtin_mirror(obj, key_si, val) } fn lookup_str(&self, val: JsValue) -> Option { self.lookup_str(val) } fn coerce_primitive_bounded(&mut self, value: JsValue, prefer_string: bool) -> Result { self.coerce_primitive_bounded(value, prefer_string) } fn coerce_number_bounded(&mut self, value: JsValue) -> Result { self.coerce_number_bounded(value) } fn call_function_sync(&mut self, callee: JsValue, receiver: JsValue, args: &[JsValue]) -> Result { self.call_function_sync(callee, receiver, args) } fn construct_ctor(&mut self, ctor: JsValue, args: &[JsValue]) -> Result { Vm::construct_ctor(self, ctor, args) } fn construct_ctor_nt(&mut self, ctor: JsValue, new_target: JsValue, args: &[JsValue]) -> Result { Vm::construct_with(self, ctor, new_target, args) } fn checked_object_ptr(&mut self, val: JsValue, error_msg: &str) -> Result, String> { self.checked_object_ptr(val, error_msg) } fn raise_type_error(&mut self, msg: &str) -> Result<(), String> { self.raise_type_error(msg) } fn raise_captured(&mut self, exc: JsValue) -> Result<(), String> { self.raise_captured(exc) } fn error_message_text(&self, kind: &str, msg: &str) -> String { self.error_message_text(kind, msg) } fn call_stack_function_names(&self) -> Vec { self.frames .iter() .rev() .map(|f| { self.kernel_core .perm_interner() .lookup(f.function_name) .unwrap_or("") .to_string() }) .collect() } fn function_is_strict(&self, obj: &JsObject) -> bool { // native 函数(sub_module_index == 0)无子模块,callee_module 返回 None, // 按严格处理(受限访问器对其抛错)。 self.callee_module(obj).map(|m| m.is_strict).unwrap_or(true) } fn function_is_restricted(&self, obj: &JsObject) -> bool { // 严格函数对象,或 [[Prototype]] 为三个动态函数原型之一(生成器 / // 异步 / 异步生成器函数):caller/arguments 访问一律受限。 if self.function_is_strict(obj) { return true; } let proto = obj.proto(); if !proto.is_object() { return false; } let p = proto.as_js_object_ptr() as *const JsObject; std::ptr::eq(p, self.realm.generator_function_proto.borrow().as_ptr()) || std::ptr::eq(p, self.realm.async_function_proto.borrow().as_ptr()) || std::ptr::eq(p, self.realm.async_generator_function_proto.borrow().as_ptr()) } fn step_rng(&mut self) { self.step_rng() } fn math_rng_value(&self) -> f64 { self.math_rng_value() } fn sub_module_function_name(&self, gen: u32, sub_idx: u16) -> String { self.tables .get(&gen) .and_then(|t| t.modules.get(sub_idx as usize)) .and_then(|m| m.function_name.clone()) .unwrap_or_default() } fn module_frame_cell(&self, cell_idx: u32) -> Option<*mut Cell> { self.cell_stack .last() .and_then(|cells| cells.get(cell_idx as usize).copied()) .filter(|p| !p.is_null()) } fn create_dynamic_function( &mut self, params: &[String], body: &str, is_generator: bool, is_async: bool, ) -> Result { self.create_dynamic_function(params, body, is_generator, is_async) } fn create_dynamic_script(&mut self, code: &str) -> Result { self.create_dynamic_script(code) } fn realm_id(&self) -> u32 { self.realm_id() } fn symbol_intern(&mut self, desc: Option) -> u32 { self.realm.symbols.borrow_mut().intern(desc) } fn symbol_description(&self, idx: u32) -> Option { self.realm.symbols.borrow().description(idx).map(|s| s.to_string()) } fn symbol_lookup_global(&self, key: &str) -> Option { self.realm.symbols.borrow().lookup_global(key) } fn symbol_register_global(&mut self, key: String, idx: u32) { self.realm.symbols.borrow_mut().register_global(key, idx) } fn symbol_key_for_id(&self, idx: u32) -> Option { self.realm.symbols.borrow().key_for_id(idx) } fn atomics_new_waiter_promise(&mut self) -> JsValue { self.atomics_new_waiter_promise() } fn atomics_register_waiter(&mut self, buffer: *mut JsObject, offset: usize, promise: JsValue) { self.atomics_register_waiter(buffer, offset, promise) } fn atomics_wake_waiters(&mut self, buffer: *mut JsObject, offset: usize, count: f64) -> usize { self.atomics_wake_waiters(buffer, offset, count) } }