mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
refactor: 内置八文件内核访问器调用改经 VmHost 能力方法
This commit is contained in:
Generated
+19
-19
@@ -1160,7 +1160,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_builtins"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"fast-float",
|
||||
@@ -1185,7 +1185,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_bytecode"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"oxide_log",
|
||||
@@ -1193,7 +1193,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_cfg"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_emit",
|
||||
@@ -1204,7 +1204,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_cli"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"bumpalo",
|
||||
@@ -1226,7 +1226,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_code_cache"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"lru",
|
||||
"oxide_bytecode",
|
||||
@@ -1235,7 +1235,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_compiler"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_cfg",
|
||||
@@ -1255,7 +1255,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_dce"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_cfg",
|
||||
@@ -1269,7 +1269,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_emit"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"oxc_allocator",
|
||||
@@ -1284,7 +1284,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_engine"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_compiler",
|
||||
@@ -1296,7 +1296,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_ir"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_log",
|
||||
@@ -1305,7 +1305,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_kernel"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"dashmap",
|
||||
@@ -1319,7 +1319,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_liveness"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_cfg",
|
||||
@@ -1331,7 +1331,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_log"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
@@ -1340,7 +1340,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_parser"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
@@ -1355,7 +1355,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_regalloc"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_cfg",
|
||||
@@ -1371,7 +1371,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_runtime_api"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
@@ -1384,7 +1384,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_test262"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"oxide_bytecode",
|
||||
"oxide_compiler",
|
||||
@@ -1402,7 +1402,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_types"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"dashmap",
|
||||
@@ -1415,7 +1415,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxide_vm"
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"chrono",
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.8.72"
|
||||
version = "0.8.73"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
rust-version = "1.80"
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_runtime_api::{to_string_full, NativeResult, VmHost};
|
||||
use oxide_types::mem::P;
|
||||
use oxide_runtime_api::{to_string_full, NativeResult, ProtoKind, VmHost};
|
||||
use oxide_types::object::{JsObject, PropAttributes};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
@@ -25,10 +22,8 @@ fn set_own_message<H: VmHost>(host: &mut H, this: *mut JsObject, args: &[u8]) ->
|
||||
return NativeResult::Err(create_type_error(host, "Cannot convert value to a string"));
|
||||
}
|
||||
};
|
||||
let sf = Arc::clone(host.kernel_core().perm_interner());
|
||||
let sh = Arc::clone(host.kernel_core().shape_forge());
|
||||
let si = sf.intern("message").0;
|
||||
let new_shape = sh.make_shape(EMPTY_SHAPE_ID, si);
|
||||
let si = host.perm_intern("message");
|
||||
let new_shape = host.make_shape(EMPTY_SHAPE_ID, si);
|
||||
let perm_val = host.new_string(&msg_str);
|
||||
unsafe {
|
||||
(*this).set_shape_id(new_shape);
|
||||
@@ -43,20 +38,18 @@ fn set_own_message<H: VmHost>(host: &mut H, this: *mut JsObject, args: &[u8]) ->
|
||||
/// 这是引擎内部构造错误的统一入口,供 VM/native 层抛错使用。
|
||||
pub fn create_kind_error<H: VmHost>(host: &mut H, kind: &str, msg: &str) -> JsValue {
|
||||
let proto_ptr = match kind {
|
||||
"TypeError" => P::as_ptr(&host.session().builtin_world().type_error_proto) as *mut JsObject,
|
||||
"RangeError" => P::as_ptr(&host.session().builtin_world().range_error_proto) as *mut JsObject,
|
||||
"ReferenceError" => P::as_ptr(&host.session().builtin_world().reference_error_proto) as *mut JsObject,
|
||||
"SyntaxError" => P::as_ptr(&host.session().builtin_world().syntax_error_proto) as *mut JsObject,
|
||||
"URIError" => P::as_ptr(&host.session().builtin_world().uri_error_proto) as *mut JsObject,
|
||||
"EvalError" => P::as_ptr(&host.session().builtin_world().eval_error_proto) as *mut JsObject,
|
||||
_ => P::as_ptr(&host.session().builtin_world().error_proto) as *mut JsObject,
|
||||
"TypeError" => host.builtin_proto(ProtoKind::TypeErrorProto),
|
||||
"RangeError" => host.builtin_proto(ProtoKind::RangeErrorProto),
|
||||
"ReferenceError" => host.builtin_proto(ProtoKind::ReferenceErrorProto),
|
||||
"SyntaxError" => host.builtin_proto(ProtoKind::SyntaxErrorProto),
|
||||
"URIError" => host.builtin_proto(ProtoKind::UriErrorProto),
|
||||
"EvalError" => host.builtin_proto(ProtoKind::EvalErrorProto),
|
||||
_ => host.builtin_proto(ProtoKind::ErrorProto),
|
||||
};
|
||||
let obj = host.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto_ptr)));
|
||||
let sf = Arc::clone(host.kernel_core().perm_interner());
|
||||
let sh = Arc::clone(host.kernel_core().shape_forge());
|
||||
if !msg.is_empty() {
|
||||
let si_msg = sf.intern("message").0;
|
||||
let shape = sh.make_shape(EMPTY_SHAPE_ID, si_msg);
|
||||
let si_msg = host.perm_intern("message");
|
||||
let shape = host.make_shape(EMPTY_SHAPE_ID, si_msg);
|
||||
let msg_val = host.new_string(msg);
|
||||
unsafe {
|
||||
(*obj).set_shape_id(shape);
|
||||
@@ -160,7 +153,7 @@ pub fn create_uri_error<H: VmHost>(host: &mut H, msg: &str) -> JsValue {
|
||||
}
|
||||
|
||||
macro_rules! error_ctor {
|
||||
($name:ident, $proto_field:ident) => {
|
||||
($name:ident, $proto_kind:ident) => {
|
||||
/// 对应 Error 子类(如 `TypeError`)的构造函数:接收第一个实参作为 message,
|
||||
/// 返回携带 Error 家族标签(`[[ErrorData]]` 谓词)的实例。
|
||||
///
|
||||
@@ -172,7 +165,7 @@ macro_rules! error_ctor {
|
||||
pub fn $name<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = host.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let new_target = host.reg(255);
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().$proto_field) as *mut JsObject;
|
||||
let proto_ptr = host.builtin_proto(ProtoKind::$proto_kind);
|
||||
let this = if this_val.is_object() && new_target.is_object() {
|
||||
this_val.as_js_object_ptr()
|
||||
} else {
|
||||
@@ -195,21 +188,19 @@ macro_rules! error_ctor {
|
||||
};
|
||||
}
|
||||
|
||||
error_ctor!(error_constructor, error_proto);
|
||||
error_ctor!(type_error_constructor, type_error_proto);
|
||||
error_ctor!(reference_error_constructor, reference_error_proto);
|
||||
error_ctor!(range_error_constructor, range_error_proto);
|
||||
error_ctor!(syntax_error_constructor, syntax_error_proto);
|
||||
error_ctor!(uri_error_constructor, uri_error_proto);
|
||||
error_ctor!(eval_error_constructor, eval_error_proto);
|
||||
error_ctor!(error_constructor, ErrorProto);
|
||||
error_ctor!(type_error_constructor, TypeErrorProto);
|
||||
error_ctor!(reference_error_constructor, ReferenceErrorProto);
|
||||
error_ctor!(range_error_constructor, RangeErrorProto);
|
||||
error_ctor!(syntax_error_constructor, SyntaxErrorProto);
|
||||
error_ctor!(uri_error_constructor, UriErrorProto);
|
||||
error_ctor!(eval_error_constructor, EvalErrorProto);
|
||||
|
||||
/// 在对象上追加一个非枚举数据属性(writable/configurable=true,enumerable=false),
|
||||
/// 与 `CreateNonEnumerableDataPropertyOrThrow` 语义一致。
|
||||
fn set_own_data_prop<H: VmHost>(host: &mut H, obj: *mut JsObject, key: &str, val: JsValue) {
|
||||
let sf = Arc::clone(host.kernel_core().perm_interner());
|
||||
let sh = Arc::clone(host.kernel_core().shape_forge());
|
||||
let si = sf.intern(key).0;
|
||||
let new_shape = sh.make_shape(unsafe { (*obj).shape_id() }, si);
|
||||
let si = host.perm_intern(key);
|
||||
let new_shape = host.make_shape(unsafe { (*obj).shape_id() }, si);
|
||||
unsafe {
|
||||
(*obj).set_shape_id(new_shape);
|
||||
let pos = (*obj).push_prop(val);
|
||||
@@ -229,7 +220,7 @@ pub fn install_error_cause<H: VmHost>(host: &mut H, obj: *mut JsObject, options:
|
||||
}
|
||||
// SAFETY: is_object 保证指针非空且对象本 session 存活。
|
||||
let opts = unsafe { &*options.as_js_object_ptr() };
|
||||
let si = host.kernel_core().perm_interner().intern("cause").0;
|
||||
let si = host.perm_intern("cause");
|
||||
if host.resolve_property(opts, si).is_none() {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
@@ -257,7 +248,7 @@ pub fn install_error_cause<H: VmHost>(host: &mut H, obj: *mut JsObject, options:
|
||||
pub fn suppressed_error_constructor<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
let this_val = host.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let new_target = host.reg(255);
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().suppressed_error_proto) as *mut JsObject;
|
||||
let proto_ptr = host.builtin_proto(ProtoKind::SuppressedErrorProto);
|
||||
let obj = if this_val.is_object() && new_target.is_object() {
|
||||
this_val.as_js_object_ptr()
|
||||
} else {
|
||||
@@ -302,7 +293,7 @@ pub fn suppressed_error_constructor<H: VmHost>(host: &mut H, args: &[u8]) -> Nat
|
||||
/// - 错误值/suppressed 值原样存储,不做任何转换;
|
||||
/// - 返回对象 proto = suppressed_error_proto,标记 OBJ_TYPE_ERROR。
|
||||
pub fn create_suppressed_error<H: VmHost>(host: &mut H, error_val: JsValue, suppressed_val: JsValue) -> JsValue {
|
||||
let proto_ptr = P::as_ptr(&host.session().builtin_world().suppressed_error_proto) as *mut JsObject;
|
||||
let proto_ptr = host.builtin_proto(ProtoKind::SuppressedErrorProto);
|
||||
let obj = host.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto_ptr)));
|
||||
set_own_data_prop(host, obj, "error", error_val);
|
||||
set_own_data_prop(host, obj, "suppressed", suppressed_val);
|
||||
@@ -332,9 +323,8 @@ pub fn error_to_string<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Err(err);
|
||||
}
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let sf = Arc::clone(host.kernel_core().perm_interner());
|
||||
let si_name = sf.intern("name").0;
|
||||
let si_msg = sf.intern("message").0;
|
||||
let si_name = host.perm_intern("name");
|
||||
let si_msg = host.perm_intern("message");
|
||||
|
||||
let name_str = match host.ordinary_get(obj, si_name, this_val) {
|
||||
Ok(v) if v.is_undefined() => "Error".to_string(),
|
||||
@@ -383,9 +373,8 @@ pub fn error_stack_getter<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult
|
||||
if !obj.is_error_obj() {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
let sf = Arc::clone(host.kernel_core().perm_interner());
|
||||
let si_name = sf.intern("name").0;
|
||||
let si_msg = sf.intern("message").0;
|
||||
let si_name = host.perm_intern("name");
|
||||
let si_msg = host.perm_intern("message");
|
||||
let n = host
|
||||
.resolve_property(obj, si_name)
|
||||
.and_then(|v| host.lookup_str(v))
|
||||
@@ -421,7 +410,7 @@ pub fn error_stack_setter<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult
|
||||
if !this_val.is_object() {
|
||||
return NativeResult::Err(create_type_error(host, "Error.prototype.stack setter called on non-object"));
|
||||
}
|
||||
let home = P::as_ptr(&host.session().builtin_world().error_proto) as *mut JsObject;
|
||||
let home = host.builtin_proto(ProtoKind::ErrorProto);
|
||||
if std::ptr::eq(this_val.as_js_object_ptr(), home) {
|
||||
return NativeResult::Err(create_type_error(host, "cannot assign to read only property of Error prototype"));
|
||||
}
|
||||
@@ -431,7 +420,7 @@ pub fn error_stack_setter<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult
|
||||
}
|
||||
// SAFETY: is_object 保证指针非空且对象本 session 存活;写入路径对象不搬移。
|
||||
let this_obj = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
let si = host.kernel_core().perm_interner().intern("stack").0;
|
||||
let si = host.perm_intern("stack");
|
||||
match host.get_own_property_slot(this_obj, si) {
|
||||
None => match host.define_data_property(this_obj, si, val, PropAttributes::new(true, true, true)) {
|
||||
Ok(()) => NativeResult::Ok(JsValue::undefined()),
|
||||
@@ -477,9 +466,8 @@ pub fn error_to_json<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
// SAFETY: is_object 保证指针非空且对象本 session 存活;读取期间不搬移。
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let sf = Arc::clone(host.kernel_core().perm_interner());
|
||||
let si_name = sf.intern("name").0;
|
||||
let si_msg = sf.intern("message").0;
|
||||
let si_name = host.perm_intern("name");
|
||||
let si_msg = host.perm_intern("message");
|
||||
|
||||
let name_val = match host.ordinary_get(obj, si_name, this_val) {
|
||||
Ok(v) => v,
|
||||
@@ -517,16 +505,15 @@ pub fn error_to_json<H: VmHost>(host: &mut H, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
|
||||
// 新对象:proto = %Object.prototype%,name/message 为可枚举数据属性。
|
||||
let object_proto = P::as_ptr(&host.session().builtin_world().object_proto) as *mut JsObject;
|
||||
let object_proto = host.builtin_proto(ProtoKind::ObjectProto);
|
||||
let ptr = host.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto)));
|
||||
// SAFETY: ptr 由 alloc_object 新建,非空 arena 指针;后续 shape/属性分配不改对象地址,无别名。
|
||||
let obj_ref = unsafe { &mut *ptr };
|
||||
let sh = Arc::clone(host.kernel_core().shape_forge());
|
||||
let name_shape = sh.make_shape(EMPTY_SHAPE_ID, si_name);
|
||||
let name_shape = host.make_shape(EMPTY_SHAPE_ID, si_name);
|
||||
obj_ref.set_shape_id(name_shape);
|
||||
let name_pos = obj_ref.push_prop(host.new_string(&name_str));
|
||||
obj_ref.set_data_meta(name_pos, PropAttributes::new(true, true, true));
|
||||
let msg_shape = sh.make_shape(obj_ref.shape_id(), si_msg);
|
||||
let msg_shape = host.make_shape(obj_ref.shape_id(), si_msg);
|
||||
obj_ref.set_shape_id(msg_shape);
|
||||
let msg_pos = obj_ref.push_prop(host.new_string(&msg_str));
|
||||
obj_ref.set_data_meta(msg_pos, PropAttributes::new(true, true, true));
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::{JsObject, PropAttributes};
|
||||
use oxide_types::private_key::{encode_symbol_key, make_int_key};
|
||||
use oxide_types::string_forge::PermInterner;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use oxide_runtime_api::{to_object, NativeResult, VmHost};
|
||||
use oxide_runtime_api::{to_object, NativeResult, ProtoKind, VmHost};
|
||||
|
||||
const INNER_PROP: &str = "__inner__";
|
||||
const INDEX_PROP: &str = "__index__";
|
||||
@@ -47,7 +48,7 @@ pub fn iterator_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
if proto.is_object() {
|
||||
let proto_ptr = proto.as_js_object_ptr();
|
||||
if !proto_ptr.is_null() {
|
||||
let home = vm.session().builtin_world().iterator_proto.as_ptr() as *mut JsObject;
|
||||
let home = vm.builtin_proto(ProtoKind::IteratorProto);
|
||||
if std::ptr::eq(proto_ptr, home) {
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Iterator is not a constructor"));
|
||||
}
|
||||
@@ -68,12 +69,11 @@ pub fn iterator_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
/// lookup 失败(极端:global 无 `Iterator`)返回 undefined,不 panic。
|
||||
pub fn iterator_constructor_getter<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
let (shape_id, global_ptr) = {
|
||||
let session = vm.session();
|
||||
let global = session.global_object();
|
||||
let global = vm.global_object();
|
||||
(global.shape_id(), global.as_ptr() as *mut JsObject)
|
||||
};
|
||||
let si = vm.kernel_core().perm_interner().intern("Iterator").0;
|
||||
let Some(pos) = vm.kernel_core().shape_forge().lookup_position(shape_id, si) else {
|
||||
let si = vm.perm_intern("Iterator");
|
||||
let Some(pos) = vm.lookup_position(shape_id, si) else {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
};
|
||||
NativeResult::Ok(unsafe { &*global_ptr }.get_prop_at(pos))
|
||||
@@ -81,8 +81,9 @@ pub fn iterator_constructor_getter<H: VmHost>(vm: &mut H, _args: &[u8]) -> Nativ
|
||||
|
||||
/// `%IteratorPrototype%` 上 `Symbol.toStringTag` 访问器的 getter:返回 `"Iterator"`。
|
||||
pub fn iterator_to_string_tag_getter<H: VmHost>(vm: &mut H, _args: &[u8]) -> NativeResult {
|
||||
let sf = vm.kernel_core().perm_interner().as_ref();
|
||||
NativeResult::Ok(JsValue::perm_string(sf.string_ptr(sf.intern("Iterator").0)))
|
||||
// SAFETY: perm interner 随 VM 存活,本表达式内只读即时消费。
|
||||
let sf = vm.perm_interner_ptr() as *const PermInterner;
|
||||
NativeResult::Ok(JsValue::perm_string(unsafe { &*sf }.string_ptr(vm.perm_intern("Iterator"))))
|
||||
}
|
||||
|
||||
/// 忽略原型属性的 setter 的共享实现(对应规范 SetterThatIgnoresPrototypeProperties):
|
||||
@@ -100,7 +101,7 @@ fn iterator_setter_ignore_proto_props<H: VmHost>(vm: &mut H, args: &[u8], key: u
|
||||
if !this_val.is_object() {
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Iterator property setter called on non-object"));
|
||||
}
|
||||
let home = vm.session().builtin_world().iterator_proto.as_ptr() as *mut JsObject;
|
||||
let home = vm.builtin_proto(ProtoKind::IteratorProto);
|
||||
if std::ptr::eq(this_val.as_js_object_ptr(), home) {
|
||||
return NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
@@ -109,12 +110,7 @@ fn iterator_setter_ignore_proto_props<H: VmHost>(vm: &mut H, args: &[u8], key: u
|
||||
}
|
||||
let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let this_obj = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
if vm
|
||||
.kernel_core()
|
||||
.shape_forge()
|
||||
.lookup_position(this_obj.shape_id(), key)
|
||||
.is_none()
|
||||
{
|
||||
if vm.lookup_position(this_obj.shape_id(), key).is_none() {
|
||||
match vm.define_data_property(this_obj, key, val, PropAttributes::new(true, true, true)) {
|
||||
Ok(()) => NativeResult::Ok(JsValue::undefined()),
|
||||
Err(err) => NativeResult::Err(crate::error::create_type_error(vm, &err)),
|
||||
@@ -129,7 +125,7 @@ fn iterator_setter_ignore_proto_props<H: VmHost>(vm: &mut H, args: &[u8], key: u
|
||||
|
||||
/// `constructor` 访问器的 setter(键 = "constructor")。
|
||||
pub fn iterator_constructor_setter<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let key = vm.kernel_core().perm_interner().intern("constructor").0;
|
||||
let key = vm.perm_intern("constructor");
|
||||
iterator_setter_ignore_proto_props(vm, args, key)
|
||||
}
|
||||
|
||||
@@ -154,7 +150,7 @@ pub fn iterator_dispose<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
));
|
||||
}
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let return_si = vm.kernel_core().perm_interner().intern("return").0;
|
||||
let return_si = vm.perm_intern("return");
|
||||
let return_fn = match vm.ordinary_get(obj, return_si, this_val) {
|
||||
Ok(f) if is_callable(f) => f,
|
||||
Ok(_) => JsValue::undefined(),
|
||||
@@ -203,7 +199,7 @@ pub(crate) fn validate_terminal_and_get_direct<H: VmHost>(
|
||||
/// - `next` getter 抛错时透传原异常值。
|
||||
pub(crate) fn get_iterator_direct<H: VmHost>(vm: &mut H, this_val: JsValue) -> Result<(JsValue, JsValue), JsValue> {
|
||||
let iter_obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let next_si = vm.kernel_core().perm_interner().intern("next").0;
|
||||
let next_si = vm.perm_intern("next");
|
||||
let next = vm.ordinary_get(iter_obj, next_si, this_val).map_err(|e| engine_error(vm, &e))?;
|
||||
Ok((this_val, next))
|
||||
}
|
||||
@@ -222,12 +218,12 @@ pub(crate) fn iterator_record_step<H: VmHost>(
|
||||
return Err(crate::error::create_type_error(vm, "iterator result is not an object"));
|
||||
}
|
||||
let result_obj = unsafe { &*result.as_js_object_ptr() };
|
||||
let done_si = vm.kernel_core().perm_interner().intern("done").0;
|
||||
let done_si = vm.perm_intern("done");
|
||||
let done = vm.ordinary_get(result_obj, done_si, result).map_err(|e| engine_error(vm, &e))?;
|
||||
if oxide_runtime_api::to_boolean(done) {
|
||||
return Ok(None);
|
||||
}
|
||||
let value_si = vm.kernel_core().perm_interner().intern("value").0;
|
||||
let value_si = vm.perm_intern("value");
|
||||
let value = vm
|
||||
.ordinary_get(result_obj, value_si, result)
|
||||
.map_err(|e| engine_error(vm, &e))?;
|
||||
@@ -248,7 +244,7 @@ pub(crate) fn iterator_close_record<H: VmHost>(
|
||||
vm: &mut H, iterated: JsValue, completion_err: Option<JsValue>,
|
||||
) -> Result<(), JsValue> {
|
||||
let iter_obj = unsafe { &*iterated.as_js_object_ptr() };
|
||||
let return_si = vm.kernel_core().perm_interner().intern("return").0;
|
||||
let return_si = vm.perm_intern("return");
|
||||
let return_fn = match vm.ordinary_get(iter_obj, return_si, iterated) {
|
||||
Ok(f) if is_callable(f) => f,
|
||||
Ok(_) => {
|
||||
@@ -439,17 +435,17 @@ fn get_iterator_flattenable<H: VmHost>(vm: &mut H, value: JsValue) -> Result<(Js
|
||||
fn make_iterator_helper<H: VmHost>(
|
||||
vm: &mut H, inner: JsValue, next: JsValue, kind: IteratorHelperKind, callback: JsValue, counter: JsValue,
|
||||
) -> JsValue {
|
||||
let helper_proto = vm.session().builtin_world().iterator_helper_proto.as_ptr() as *mut JsObject;
|
||||
let helper_proto = vm.builtin_proto(ProtoKind::IteratorHelperProto);
|
||||
let wrapper = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(helper_proto)));
|
||||
let wrapper_obj = unsafe { &mut *wrapper };
|
||||
let inner_si = vm.kernel_core().perm_interner().intern(INNER_PROP).0;
|
||||
let next_si = vm.kernel_core().perm_interner().intern(NEXT_CACHE_PROP).0;
|
||||
let kind_si = vm.kernel_core().perm_interner().intern(KIND_PROP).0;
|
||||
let state_si = vm.kernel_core().perm_interner().intern(STATE_PROP).0;
|
||||
let counter_si = vm.kernel_core().perm_interner().intern(COUNTER_PROP).0;
|
||||
let callback_si = vm.kernel_core().perm_interner().intern(CALLBACK_PROP).0;
|
||||
let inner_iter_si = vm.kernel_core().perm_interner().intern(INNER_ITER_PROP).0;
|
||||
let inner_next_si = vm.kernel_core().perm_interner().intern(INNER_NEXT_PROP).0;
|
||||
let inner_si = vm.perm_intern(INNER_PROP);
|
||||
let next_si = vm.perm_intern(NEXT_CACHE_PROP);
|
||||
let kind_si = vm.perm_intern(KIND_PROP);
|
||||
let state_si = vm.perm_intern(STATE_PROP);
|
||||
let counter_si = vm.perm_intern(COUNTER_PROP);
|
||||
let callback_si = vm.perm_intern(CALLBACK_PROP);
|
||||
let inner_iter_si = vm.perm_intern(INNER_ITER_PROP);
|
||||
let inner_next_si = vm.perm_intern(INNER_NEXT_PROP);
|
||||
vm.set_or_create_prop_value(wrapper_obj, inner_si, inner);
|
||||
vm.set_or_create_prop_value(wrapper_obj, next_si, next);
|
||||
vm.set_or_create_prop_value(wrapper_obj, kind_si, JsValue::int(kind as i32));
|
||||
@@ -471,7 +467,7 @@ fn validate_helper_this<H: VmHost>(vm: &mut H, this_val: JsValue, method: &str)
|
||||
return Err(crate::error::create_type_error(vm, &format!("{method} called on non-object")));
|
||||
}
|
||||
let obj = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let inner_si = vm.kernel_core().perm_interner().intern(INNER_PROP).0;
|
||||
let inner_si = vm.perm_intern(INNER_PROP);
|
||||
let inner = vm.ordinary_get(obj, inner_si, this_val).map_err(|e| engine_error(vm, &e))?;
|
||||
if !inner.is_object() {
|
||||
return Err(crate::error::create_type_error(vm, &format!("{method} called on non-iterator-helper")));
|
||||
@@ -709,7 +705,7 @@ pub fn iterator_to_array<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
|
||||
/// 按元素列表构造普通数组,以 Array.prototype 为原型(对应规范 CreateArrayFromList)。
|
||||
fn make_array_from_list<H: VmHost>(vm: &mut H, items: &[JsValue]) -> JsValue {
|
||||
let array_proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let array_proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(
|
||||
EMPTY_SHAPE_ID,
|
||||
JsValue::from_js_object(array_proto),
|
||||
@@ -863,7 +859,7 @@ pub fn iterator_helper_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
Err(v) => return NativeResult::Err(v),
|
||||
};
|
||||
let helper = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
let state_si = vm.kernel_core().perm_interner().intern(STATE_PROP).0;
|
||||
let state_si = vm.perm_intern(STATE_PROP);
|
||||
let state = read_slot_int(vm, helper, state_si, 2);
|
||||
if state == 2 {
|
||||
return NativeResult::Ok(make_iter_result(vm, JsValue::undefined(), true));
|
||||
@@ -871,10 +867,10 @@ pub fn iterator_helper_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
if state == 1 {
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Iterator helper is already executing"));
|
||||
}
|
||||
let kind_si = vm.kernel_core().perm_interner().intern(KIND_PROP).0;
|
||||
let kind_si = vm.perm_intern(KIND_PROP);
|
||||
let kind = IteratorHelperKind::from_i32(read_slot_int(vm, helper, kind_si, 0));
|
||||
vm.set_or_create_prop_value(helper, state_si, JsValue::int(1));
|
||||
let next_si = vm.kernel_core().perm_interner().intern(NEXT_CACHE_PROP).0;
|
||||
let next_si = vm.perm_intern(NEXT_CACHE_PROP);
|
||||
let next = vm.ordinary_get(helper, next_si, this_val).unwrap_or(JsValue::undefined());
|
||||
let step = match kind {
|
||||
IteratorHelperKind::Map => helper_step_map(vm, this_val, helper, inner, next),
|
||||
@@ -914,7 +910,7 @@ pub fn iterator_helper_return<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResul
|
||||
Err(v) => return NativeResult::Err(v),
|
||||
};
|
||||
let helper = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
let state_si = vm.kernel_core().perm_interner().intern(STATE_PROP).0;
|
||||
let state_si = vm.perm_intern(STATE_PROP);
|
||||
let state = read_slot_int(vm, helper, state_si, 2);
|
||||
if state == 2 {
|
||||
return NativeResult::Ok(make_iter_result(vm, JsValue::undefined(), true));
|
||||
@@ -923,9 +919,9 @@ pub fn iterator_helper_return<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResul
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Iterator helper is already executing"));
|
||||
}
|
||||
vm.set_or_create_prop_value(helper, state_si, JsValue::int(2));
|
||||
let kind_si = vm.kernel_core().perm_interner().intern(KIND_PROP).0;
|
||||
let kind_si = vm.perm_intern(KIND_PROP);
|
||||
if IteratorHelperKind::from_i32(read_slot_int(vm, helper, kind_si, 0)) == IteratorHelperKind::FlatMap {
|
||||
let inner_iter_si = vm.kernel_core().perm_interner().intern(INNER_ITER_PROP).0;
|
||||
let inner_iter_si = vm.perm_intern(INNER_ITER_PROP);
|
||||
if let Ok(inner_iter) = vm.ordinary_get(helper, inner_iter_si, this_val) {
|
||||
if inner_iter.is_object() {
|
||||
// 内层关闭出错:以该错误关外层(外层 return 错误被吞),传播内层错误。
|
||||
@@ -956,7 +952,7 @@ pub fn iterator_helper_throw<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
Err(v) => return NativeResult::Err(v),
|
||||
};
|
||||
let helper = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
let state_si = vm.kernel_core().perm_interner().intern(STATE_PROP).0;
|
||||
let state_si = vm.perm_intern(STATE_PROP);
|
||||
let state = read_slot_int(vm, helper, state_si, 2);
|
||||
if state == 2 {
|
||||
return NativeResult::Err(value);
|
||||
@@ -965,9 +961,9 @@ pub fn iterator_helper_throw<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Iterator helper is already executing"));
|
||||
}
|
||||
vm.set_or_create_prop_value(helper, state_si, JsValue::int(2));
|
||||
let kind_si = vm.kernel_core().perm_interner().intern(KIND_PROP).0;
|
||||
let kind_si = vm.perm_intern(KIND_PROP);
|
||||
if IteratorHelperKind::from_i32(read_slot_int(vm, helper, kind_si, 0)) == IteratorHelperKind::FlatMap {
|
||||
let inner_iter_si = vm.kernel_core().perm_interner().intern(INNER_ITER_PROP).0;
|
||||
let inner_iter_si = vm.perm_intern(INNER_ITER_PROP);
|
||||
if let Ok(inner_iter) = vm.ordinary_get(helper, inner_iter_si, this_val) {
|
||||
if inner_iter.is_object() {
|
||||
// throw 语义:原值胜出,内层/外层关闭错误均被吞。
|
||||
@@ -984,8 +980,8 @@ pub fn iterator_helper_throw<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
fn helper_step_map<H: VmHost>(
|
||||
vm: &mut H, this_val: JsValue, helper: &mut JsObject, inner: JsValue, next: JsValue,
|
||||
) -> Result<Option<JsValue>, JsValue> {
|
||||
let counter_si = vm.kernel_core().perm_interner().intern(COUNTER_PROP).0;
|
||||
let callback_si = vm.kernel_core().perm_interner().intern(CALLBACK_PROP).0;
|
||||
let counter_si = vm.perm_intern(COUNTER_PROP);
|
||||
let callback_si = vm.perm_intern(CALLBACK_PROP);
|
||||
let mapper = vm.ordinary_get(helper, callback_si, this_val).unwrap_or(JsValue::undefined());
|
||||
let counter = read_counter(vm, helper, counter_si);
|
||||
let value = match iterator_record_step(vm, next, inner) {
|
||||
@@ -1012,8 +1008,8 @@ fn helper_step_map<H: VmHost>(
|
||||
fn helper_step_filter<H: VmHost>(
|
||||
vm: &mut H, this_val: JsValue, helper: &mut JsObject, inner: JsValue, next: JsValue,
|
||||
) -> Result<Option<JsValue>, JsValue> {
|
||||
let counter_si = vm.kernel_core().perm_interner().intern(COUNTER_PROP).0;
|
||||
let callback_si = vm.kernel_core().perm_interner().intern(CALLBACK_PROP).0;
|
||||
let counter_si = vm.perm_intern(COUNTER_PROP);
|
||||
let callback_si = vm.perm_intern(CALLBACK_PROP);
|
||||
let predicate = vm.ordinary_get(helper, callback_si, this_val).unwrap_or(JsValue::undefined());
|
||||
let mut counter = read_counter(vm, helper, counter_si);
|
||||
loop {
|
||||
@@ -1045,7 +1041,7 @@ fn helper_step_filter<H: VmHost>(
|
||||
fn helper_step_take<H: VmHost>(
|
||||
vm: &mut H, helper: &mut JsObject, inner: JsValue, next: JsValue,
|
||||
) -> Result<Option<JsValue>, JsValue> {
|
||||
let counter_si = vm.kernel_core().perm_interner().intern(COUNTER_PROP).0;
|
||||
let counter_si = vm.perm_intern(COUNTER_PROP);
|
||||
let remaining = read_slot_double(vm, helper, counter_si, f64::INFINITY);
|
||||
if remaining == 0.0 {
|
||||
// remaining 归零:正常完成形态关底层(return 错误胜出)。
|
||||
@@ -1068,7 +1064,7 @@ fn helper_step_take<H: VmHost>(
|
||||
fn helper_step_drop<H: VmHost>(
|
||||
vm: &mut H, helper: &mut JsObject, inner: JsValue, next: JsValue,
|
||||
) -> Result<Option<JsValue>, JsValue> {
|
||||
let counter_si = vm.kernel_core().perm_interner().intern(COUNTER_PROP).0;
|
||||
let counter_si = vm.perm_intern(COUNTER_PROP);
|
||||
let mut remaining = read_slot_double(vm, helper, counter_si, 0.0);
|
||||
while remaining > 0.0 {
|
||||
if remaining != f64::INFINITY {
|
||||
@@ -1096,10 +1092,10 @@ fn helper_step_drop<H: VmHost>(
|
||||
fn helper_step_flat_map<H: VmHost>(
|
||||
vm: &mut H, this_val: JsValue, helper: &mut JsObject, outer: JsValue, outer_next: JsValue,
|
||||
) -> Result<Option<JsValue>, JsValue> {
|
||||
let counter_si = vm.kernel_core().perm_interner().intern(COUNTER_PROP).0;
|
||||
let callback_si = vm.kernel_core().perm_interner().intern(CALLBACK_PROP).0;
|
||||
let inner_iter_si = vm.kernel_core().perm_interner().intern(INNER_ITER_PROP).0;
|
||||
let inner_next_si = vm.kernel_core().perm_interner().intern(INNER_NEXT_PROP).0;
|
||||
let counter_si = vm.perm_intern(COUNTER_PROP);
|
||||
let callback_si = vm.perm_intern(CALLBACK_PROP);
|
||||
let inner_iter_si = vm.perm_intern(INNER_ITER_PROP);
|
||||
let inner_next_si = vm.perm_intern(INNER_NEXT_PROP);
|
||||
let mapper = vm.ordinary_get(helper, callback_si, this_val).unwrap_or(JsValue::undefined());
|
||||
let mut counter = read_counter(vm, helper, counter_si);
|
||||
loop {
|
||||
@@ -1246,13 +1242,13 @@ pub(crate) fn build_iterator_wrapper<H: VmHost>(
|
||||
) -> JsValue {
|
||||
let iterator_proto = match wrapper_proto {
|
||||
Some(proto) => proto,
|
||||
None => vm.session().builtin_world().iterator_proto.as_ptr() as *mut JsObject,
|
||||
None => vm.builtin_proto(ProtoKind::IteratorProto),
|
||||
};
|
||||
let wrapper = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(iterator_proto)));
|
||||
|
||||
let inner_si = vm.kernel_core().perm_interner().intern(INNER_PROP).0;
|
||||
let index_si = vm.kernel_core().perm_interner().intern(INDEX_PROP).0;
|
||||
let next_si = vm.kernel_core().perm_interner().intern("next").0;
|
||||
let inner_si = vm.perm_intern(INNER_PROP);
|
||||
let index_si = vm.perm_intern(INDEX_PROP);
|
||||
let next_si = vm.perm_intern("next");
|
||||
let wrapper_obj = unsafe { &mut *wrapper };
|
||||
vm.set_or_create_prop_value(wrapper_obj, inner_si, inner);
|
||||
vm.set_or_create_prop_value(wrapper_obj, index_si, JsValue::int(0));
|
||||
@@ -1261,7 +1257,7 @@ pub(crate) fn build_iterator_wrapper<H: VmHost>(
|
||||
// "只读一次"同模式),消费期直读槽不重触发 getter;非鸭子路径无槽,wrapper next
|
||||
// 回退重读内层 next(既有行为)。
|
||||
if let Some(next_fn) = cached_next {
|
||||
let next_cache_si = vm.kernel_core().perm_interner().intern(NEXT_CACHE_PROP).0;
|
||||
let next_cache_si = vm.perm_intern(NEXT_CACHE_PROP);
|
||||
vm.set_or_create_prop_value(wrapper_obj, next_cache_si, next_fn);
|
||||
}
|
||||
|
||||
@@ -1270,7 +1266,7 @@ pub(crate) fn build_iterator_wrapper<H: VmHost>(
|
||||
|
||||
// for-of/解构的 IteratorClose 需要 return 方法:条件暴露(内层有可调用 return 时)。
|
||||
// `yield*` 委托(bind_return=false)不绑定,转发时对内层延迟 GetMethod。
|
||||
let return_si = vm.kernel_core().perm_interner().intern("return").0;
|
||||
let return_si = vm.perm_intern("return");
|
||||
if bind_return && inner.is_object() {
|
||||
let inner_obj = unsafe { &*inner.as_js_object_ptr() };
|
||||
if let Ok(return_fn) = vm.ordinary_get(inner_obj, return_si, inner) {
|
||||
@@ -1290,14 +1286,14 @@ fn iterator_wrapper_return<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
let wrapper = unsafe { &*this_val.as_js_object_ptr() };
|
||||
let inner_si = vm.kernel_core().perm_interner().intern(INNER_PROP).0;
|
||||
let inner_si = vm.perm_intern(INNER_PROP);
|
||||
let inner = match vm.ordinary_get(wrapper, inner_si, this_val) {
|
||||
Ok(inner) if inner.is_object() => inner,
|
||||
_ => return NativeResult::Ok(JsValue::undefined()),
|
||||
};
|
||||
// 延迟 GetMethod:内层无 return 方法时返回 undefined(IteratorClose 跳过)。
|
||||
let inner_obj = unsafe { &*inner.as_js_object_ptr() };
|
||||
let return_si = vm.kernel_core().perm_interner().intern("return").0;
|
||||
let return_si = vm.perm_intern("return");
|
||||
let return_fn = match vm.ordinary_get(inner_obj, return_si, inner) {
|
||||
Ok(f) if is_callable(f) => f,
|
||||
_ => return NativeResult::Ok(JsValue::undefined()),
|
||||
@@ -1323,8 +1319,8 @@ pub fn iterator_wrapper_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
}
|
||||
|
||||
let wrapper = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
let inner_si = vm.kernel_core().perm_interner().intern(INNER_PROP).0;
|
||||
let index_si = vm.kernel_core().perm_interner().intern(INDEX_PROP).0;
|
||||
let inner_si = vm.perm_intern(INNER_PROP);
|
||||
let index_si = vm.perm_intern(INDEX_PROP);
|
||||
let inner = match vm.ordinary_get(wrapper, inner_si, this_val) {
|
||||
Ok(inner) if !inner.is_undefined() => inner,
|
||||
_ => return NativeResult::Err(crate::error::create_type_error(vm, "Iterator wrapper has no inner iterator")),
|
||||
@@ -1340,7 +1336,7 @@ pub fn iterator_wrapper_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
// 鸭子回退包装器优先读 `__next__` 槽(from() 时只读一次的缓存闭包,
|
||||
// 消费期不重触发 getter);槽缺失或不可调用时回退重读内层 next
|
||||
// (非鸭子路径既有行为)。
|
||||
let next_cache_si = vm.kernel_core().perm_interner().intern(NEXT_CACHE_PROP).0;
|
||||
let next_cache_si = vm.perm_intern(NEXT_CACHE_PROP);
|
||||
let cached = match vm.ordinary_get(wrapper, next_cache_si, this_val) {
|
||||
Ok(c) => c,
|
||||
Err(err) => {
|
||||
@@ -1355,7 +1351,7 @@ pub fn iterator_wrapper_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
cached
|
||||
} else {
|
||||
let inner_obj = unsafe { &*inner.as_js_object_ptr() };
|
||||
let next_si = vm.kernel_core().perm_interner().intern("next").0;
|
||||
let next_si = vm.perm_intern("next");
|
||||
match vm.ordinary_get(inner_obj, next_si, inner) {
|
||||
Ok(n) => n,
|
||||
Err(err) => {
|
||||
@@ -1405,7 +1401,7 @@ pub(crate) fn peek_iterator_method<H: VmHost>(vm: &mut H, value: JsValue) -> Res
|
||||
// (与 get_iterator 的 String 臂同口径)。默认迭代器被删除/置 null 时须落
|
||||
// array-like,而非按"String 恒可迭代"放行迭代路径。
|
||||
if value.is_string() {
|
||||
let proto_ptr = vm.session().builtin_world().string_proto.as_ptr() as *mut JsObject;
|
||||
let proto_ptr = vm.builtin_proto(ProtoKind::StringProto);
|
||||
// SAFETY: string_proto 是 BuiltinWorld 长驻原型对象,进程内有效且不被 GC 搬移。
|
||||
let proto_obj = unsafe { &*proto_ptr };
|
||||
let sym_iter_si = encode_symbol_key(vm.realm_id(), 0);
|
||||
@@ -1465,7 +1461,7 @@ pub(crate) fn peek_iterator_method<H: VmHost>(vm: &mut H, value: JsValue) -> Res
|
||||
// 装箱串不套用:get_iterator 的 String 臂无 duck-next 回退,规范也只看
|
||||
// @@iterator(Array.from/%TypedArray%.from 应落 array-like)。
|
||||
if !obj.is_string_obj() {
|
||||
let next_si = vm.kernel_core().perm_interner().intern("next").0;
|
||||
let next_si = vm.perm_intern("next");
|
||||
if let Ok(next) = vm.ordinary_get(obj, next_si, value) {
|
||||
if is_callable(next) {
|
||||
return Ok(true);
|
||||
@@ -1490,21 +1486,17 @@ fn builtin_iterator_default_intact<H: VmHost>(vm: &mut H, value: JsValue, method
|
||||
if !method.is_object() {
|
||||
return false;
|
||||
}
|
||||
let (anchor_ptr, anchor_name) = {
|
||||
let session = vm.session();
|
||||
let world = session.builtin_world();
|
||||
if is_array_value(value) {
|
||||
(world.array_proto.as_ptr() as *mut JsObject, "values")
|
||||
} else if is_typed_array_value(value) {
|
||||
(world.typed_array_proto.as_ptr() as *mut JsObject, "values")
|
||||
} else if is_map_value(value) {
|
||||
(world.map_proto.as_ptr() as *mut JsObject, "entries")
|
||||
} else {
|
||||
(world.set_proto.as_ptr() as *mut JsObject, "values")
|
||||
}
|
||||
let (anchor_ptr, anchor_name) = if is_array_value(value) {
|
||||
(vm.builtin_proto(ProtoKind::ArrayProto), "values")
|
||||
} else if is_typed_array_value(value) {
|
||||
(vm.builtin_proto(ProtoKind::TypedArrayProto), "values")
|
||||
} else if is_map_value(value) {
|
||||
(vm.builtin_proto(ProtoKind::MapProto), "entries")
|
||||
} else {
|
||||
(vm.builtin_proto(ProtoKind::SetProto), "values")
|
||||
};
|
||||
let anchor_obj = unsafe { &*anchor_ptr };
|
||||
let anchor_si = vm.kernel_core().perm_interner().intern(anchor_name).0;
|
||||
let anchor_si = vm.perm_intern(anchor_name);
|
||||
let Ok(anchor) = vm.ordinary_get(anchor_obj, anchor_si, JsValue::from_js_object(anchor_ptr)) else {
|
||||
return false;
|
||||
};
|
||||
@@ -1539,7 +1531,7 @@ fn get_iterator<H: VmHost>(vm: &mut H, value: JsValue) -> Result<Option<(JsValue
|
||||
let read_ptr = if value_is_string_box {
|
||||
value.as_js_object_ptr()
|
||||
} else {
|
||||
vm.session().builtin_world().string_proto.as_ptr() as *mut JsObject
|
||||
vm.builtin_proto(ProtoKind::StringProto)
|
||||
};
|
||||
let read_obj = unsafe { &*read_ptr };
|
||||
let sym_iter_si = encode_symbol_key(vm.realm_id(), 0);
|
||||
@@ -1567,7 +1559,7 @@ fn get_iterator<H: VmHost>(vm: &mut H, value: JsValue) -> Result<Option<(JsValue
|
||||
};
|
||||
// 默认迭代器(自别名:即 @@iterator 槽本身)走码元快速路径、不调方法——
|
||||
// 调默认函数会递归回本 String 臂。指针未捕获(绑定前瞬时)亦回退快速路径。
|
||||
let default_ptr = vm.session().builtin_world().string_default_iterator.get();
|
||||
let default_ptr = vm.string_default_iterator();
|
||||
if !default_ptr.is_null()
|
||||
&& is_callable(method)
|
||||
&& std::ptr::eq(method.as_js_object_ptr() as *const JsObject, default_ptr)
|
||||
@@ -1657,7 +1649,7 @@ fn get_iterator<H: VmHost>(vm: &mut H, value: JsValue) -> Result<Option<(JsValue
|
||||
}
|
||||
// 鸭子回退:对象自身有可调用 next(Map/Set 迭代器包装等既有用法)。
|
||||
// getter 抛错透传原值(不落入"不可迭代"),读到的闭包随 inner 回传供缓存。
|
||||
let next_si = vm.kernel_core().perm_interner().intern("next").0;
|
||||
let next_si = vm.perm_intern("next");
|
||||
let next = match vm.ordinary_get(obj, next_si, value) {
|
||||
Ok(n) => n,
|
||||
Err(err) => {
|
||||
@@ -1743,7 +1735,7 @@ pub fn builtin_iter_kind<H: VmHost>(vm: &mut H, wrapper: JsValue) -> Option<(Bui
|
||||
}
|
||||
// SAFETY: wrapper 刚判定为对象。
|
||||
let wrapper_obj = unsafe { &*wrapper.as_js_object_ptr() };
|
||||
let inner_si = vm.kernel_core().perm_interner().intern(INNER_PROP).0;
|
||||
let inner_si = vm.perm_intern(INNER_PROP);
|
||||
let inner = match vm.ordinary_get(wrapper_obj, inner_si, wrapper) {
|
||||
Ok(inner) if !inner.is_undefined() => inner,
|
||||
_ => return None,
|
||||
@@ -1900,10 +1892,10 @@ fn current_index<H: VmHost>(vm: &mut H, wrapper: &JsObject, index_si: u32) -> us
|
||||
|
||||
/// 构造迭代器结果对象 `{value, done}`(生成器 next/return 结果复用)。
|
||||
pub fn make_iter_result<H: VmHost>(vm: &mut H, value: JsValue, done: bool) -> JsValue {
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let object_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto)));
|
||||
let value_si = vm.kernel_core().perm_interner().intern("value").0;
|
||||
let done_si = vm.kernel_core().perm_interner().intern("done").0;
|
||||
let value_si = vm.perm_intern("value");
|
||||
let done_si = vm.perm_intern("done");
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
vm.set_or_create_prop_value(obj_ref, value_si, value);
|
||||
vm.set_or_create_prop_value(obj_ref, done_si, JsValue::bool(done));
|
||||
@@ -1913,14 +1905,14 @@ pub fn make_iter_result<H: VmHost>(vm: &mut H, value: JsValue, done: bool) -> Js
|
||||
/// 构造 native 函数对象并返回:设置函数标记、native 函数项、参数个数与 `name`
|
||||
/// 属性。供迭代器包装器把自己的 next/return 方法装到包装对象上,不经绑定层注册。
|
||||
pub(crate) fn make_native_function<H: VmHost>(vm: &mut H, name: &str, native_fn: *const (), arg_count: u8) -> JsValue {
|
||||
let function_proto = vm.session().builtin_world().function_proto.as_ptr() as *mut JsObject;
|
||||
let function_proto = vm.builtin_proto(ProtoKind::FunctionProto);
|
||||
let mut func = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(function_proto));
|
||||
func.set_function(true);
|
||||
// SAFETY: native_fn 来自 NativeFn 函数项。
|
||||
func.set_native_fn(Some(unsafe { oxide_types::object::NativeFnPtr::from_raw(native_fn) }));
|
||||
func.set_native_arg_count(arg_count);
|
||||
let func = vm.alloc_object(func);
|
||||
let name_si = vm.kernel_core().perm_interner().intern("name").0;
|
||||
let name_si = vm.perm_intern("name");
|
||||
let value = vm.new_string(name);
|
||||
let func_ref = unsafe { &mut *func };
|
||||
vm.set_or_create_prop_value(func_ref, name_si, value);
|
||||
@@ -1966,7 +1958,7 @@ pub(crate) fn close_iterator<H: VmHost>(vm: &mut H, iterator: JsValue) {
|
||||
return;
|
||||
}
|
||||
let iter_obj = unsafe { &*iterator.as_js_object_ptr() };
|
||||
let return_si = vm.kernel_core().perm_interner().intern("return").0;
|
||||
let return_si = vm.perm_intern("return");
|
||||
if let Ok(ret) = vm.ordinary_get(iter_obj, return_si, iterator) {
|
||||
if is_callable(ret) {
|
||||
// return() 的抛错被忽略,其值不得外泄进槽覆盖在途异常。
|
||||
@@ -2004,9 +1996,9 @@ pub fn iterate_iterator<H: VmHost, F>(vm: &mut H, iterator: JsValue, mut on_elem
|
||||
where
|
||||
F: FnMut(&mut H, JsValue) -> Result<(), JsValue>,
|
||||
{
|
||||
let next_si = vm.kernel_core().perm_interner().intern("next").0;
|
||||
let done_si = vm.kernel_core().perm_interner().intern("done").0;
|
||||
let value_si = vm.kernel_core().perm_interner().intern("value").0;
|
||||
let next_si = vm.perm_intern("next");
|
||||
let done_si = vm.perm_intern("done");
|
||||
let value_si = vm.perm_intern("value");
|
||||
let run: Result<(), JsValue> = (|| {
|
||||
loop {
|
||||
let iter_obj = unsafe { &*iterator.as_js_object_ptr() };
|
||||
@@ -2052,7 +2044,7 @@ fn is_set_value(value: JsValue) -> bool {
|
||||
}
|
||||
|
||||
fn make_map_set_pair<H: VmHost>(vm: &mut H, a: JsValue, b: JsValue) -> JsValue {
|
||||
let array_proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let array_proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let pair = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), 2));
|
||||
// SAFETY: pair 是刚经统一入口分配的数组 JsObject。
|
||||
unsafe {
|
||||
@@ -2176,9 +2168,9 @@ pub fn map_set_iterator_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "iterator next called on non-object"));
|
||||
}
|
||||
let wrapper = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
let inner_si = vm.kernel_core().perm_interner().intern(INNER_PROP).0;
|
||||
let index_si = vm.kernel_core().perm_interner().intern(INDEX_PROP).0;
|
||||
let mode_si = vm.kernel_core().perm_interner().intern(MODE_PROP).0;
|
||||
let inner_si = vm.perm_intern(INNER_PROP);
|
||||
let index_si = vm.perm_intern(INDEX_PROP);
|
||||
let mode_si = vm.perm_intern(MODE_PROP);
|
||||
let inner = match vm.ordinary_get(wrapper, inner_si, this_val) {
|
||||
Ok(inner) if !inner.is_undefined() => inner,
|
||||
_ => return NativeResult::Err(crate::error::create_type_error(vm, "iterator has no inner collection")),
|
||||
@@ -2204,9 +2196,9 @@ pub(crate) fn make_collection_iterator<H: VmHost>(
|
||||
std::ptr::null_mut()
|
||||
};
|
||||
let wrapper = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto_ptr)));
|
||||
let inner_si = vm.kernel_core().perm_interner().intern(INNER_PROP).0;
|
||||
let index_si = vm.kernel_core().perm_interner().intern(INDEX_PROP).0;
|
||||
let mode_si = vm.kernel_core().perm_interner().intern(MODE_PROP).0;
|
||||
let inner_si = vm.perm_intern(INNER_PROP);
|
||||
let index_si = vm.perm_intern(INDEX_PROP);
|
||||
let mode_si = vm.perm_intern(MODE_PROP);
|
||||
let wrapper_obj = unsafe { &mut *wrapper };
|
||||
vm.set_or_create_prop_value(wrapper_obj, inner_si, inner);
|
||||
vm.set_or_create_prop_value(wrapper_obj, index_si, JsValue::int(0));
|
||||
|
||||
@@ -7,7 +7,7 @@ use oxide_types::value::JsValue;
|
||||
|
||||
use crate::object::walk_own_keys;
|
||||
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
use oxide_runtime_api::{NativeResult, ProtoKind, VmHost};
|
||||
|
||||
/// `JSON.parse(text, reviver)`:解析 JSON 文本为 JS 值(递归下降解析器,
|
||||
/// 逐原始值记录精确源文本切片)。提供 reviver 时以后序遍历逐属性调用
|
||||
@@ -49,7 +49,7 @@ pub fn json_parse<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if reviver_val.is_object() {
|
||||
let rptr = reviver_val.as_js_object_ptr();
|
||||
if !rptr.is_null() && unsafe { (*rptr).is_function() } {
|
||||
let empty_si = vm.kernel_core().perm_interner().intern("").0;
|
||||
let empty_si = vm.perm_intern("");
|
||||
let holder = create_wrapper(vm, result);
|
||||
let holder_ptr = holder.as_js_object_ptr();
|
||||
result = match walk_reviver(vm, holder_ptr, empty_si, reviver_val, Some(&parsed)) {
|
||||
@@ -121,8 +121,8 @@ pub fn json_raw_json<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
// 建 null 原型对象:rawJSON 属性为唯一自身属性,frozen 形态收尾。
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
obj.type_tag = JsObject::OBJ_TYPE_RAW_JSON;
|
||||
let raw_si = vm.kernel_core().perm_interner().intern("rawJSON").0;
|
||||
let new_shape = vm.kernel_core().shape_forge().make_shape(obj.shape_id(), raw_si);
|
||||
let raw_si = vm.perm_intern("rawJSON");
|
||||
let new_shape = vm.make_shape(obj.shape_id(), raw_si);
|
||||
obj.set_shape_id(new_shape);
|
||||
obj.ensure_hash_props().push(text_val);
|
||||
let obj_ptr = vm.alloc_object(obj);
|
||||
@@ -576,13 +576,13 @@ fn walk_reviver<H: VmHost>(
|
||||
/// 属性(w/e/c 全 true)——被 reviver 前向替换的值、array/object 节点
|
||||
/// 与无节点处一律空 context。
|
||||
fn build_context<H: VmHost>(vm: &mut H, val: JsValue, node: Option<&JsonNode>) -> JsValue {
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let object_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto));
|
||||
if let Some(n) = node {
|
||||
if let Some(src) = n.source.as_ref() {
|
||||
if same_value_as(vm, val, n) {
|
||||
let source_si = vm.kernel_core().perm_interner().intern("source").0;
|
||||
let new_shape = vm.kernel_core().shape_forge().make_shape(obj.shape_id(), source_si);
|
||||
let source_si = vm.perm_intern("source");
|
||||
let new_shape = vm.make_shape(obj.shape_id(), source_si);
|
||||
obj.set_shape_id(new_shape);
|
||||
obj.ensure_hash_props().push(vm.new_string(src));
|
||||
}
|
||||
@@ -647,7 +647,7 @@ fn build_js_value<H: VmHost>(vm: &mut H, node: &JsonNode) -> JsValue {
|
||||
JsonKind::Number(n) => JsValue::float(*n),
|
||||
JsonKind::String(s) => vm.new_string(s),
|
||||
JsonKind::Array(items) => {
|
||||
let array_proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let array_proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let n = items.len();
|
||||
let array_obj =
|
||||
vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), n));
|
||||
@@ -670,13 +670,13 @@ fn build_js_value<H: VmHost>(vm: &mut H, node: &JsonNode) -> JsValue {
|
||||
}
|
||||
unique.sort_by(|a, b| a.0.cmp(b.0));
|
||||
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let object_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto));
|
||||
for (key, val) in unique {
|
||||
// 键经字符串规范化:规范数字串("0"/"5")映射整数键,与属性访问统一。
|
||||
let si = vm.string_key_si(key);
|
||||
let jsv = build_js_value(vm, val);
|
||||
let new_shape = vm.kernel_core().shape_forge().make_shape(obj.shape_id(), si);
|
||||
let new_shape = vm.make_shape(obj.shape_id(), si);
|
||||
obj.set_shape_id(new_shape);
|
||||
obj.ensure_hash_props().push(jsv);
|
||||
}
|
||||
@@ -687,10 +687,10 @@ fn build_js_value<H: VmHost>(vm: &mut H, node: &JsonNode) -> JsValue {
|
||||
}
|
||||
|
||||
fn create_wrapper<H: VmHost>(vm: &mut H, value: JsValue) -> JsValue {
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let empty_si = vm.kernel_core().perm_interner().intern("").0;
|
||||
let object_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
let empty_si = vm.perm_intern("");
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto));
|
||||
let new_shape = vm.kernel_core().shape_forge().make_shape(obj.shape_id(), empty_si);
|
||||
let new_shape = vm.make_shape(obj.shape_id(), empty_si);
|
||||
obj.set_shape_id(new_shape);
|
||||
obj.ensure_hash_props().push(value);
|
||||
let obj_ptr = vm.alloc_object(obj);
|
||||
@@ -764,9 +764,7 @@ fn key_si_to_units<H: VmHost>(vm: &H, si: u32) -> Vec<u16> {
|
||||
if is_int_key(si) {
|
||||
int_key_value(si).to_string().encode_utf16().collect()
|
||||
} else {
|
||||
vm.kernel_core()
|
||||
.perm_interner()
|
||||
.lookup(si)
|
||||
vm.perm_lookup(si)
|
||||
.map(oxide_kernel::string_forge::decode_key)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
@@ -797,8 +795,8 @@ fn whitelist_element_name<H: VmHost>(vm: &mut H, elem: JsValue) -> Result<Option
|
||||
}
|
||||
|
||||
// ToPrimitive string hint:toString 优先,valueOf 兜底。
|
||||
let to_string_si = vm.kernel_core().perm_interner().intern("toString").0;
|
||||
let value_of_si = vm.kernel_core().perm_interner().intern("valueOf").0;
|
||||
let to_string_si = vm.perm_intern("toString");
|
||||
let value_of_si = vm.perm_intern("valueOf");
|
||||
for m_si in [to_string_si, value_of_si] {
|
||||
let m = vm.ordinary_get(obj, m_si, elem).map_err(|msg| {
|
||||
vm.take_uncaught_value()
|
||||
@@ -835,9 +833,9 @@ fn call_to_json<H: VmHost>(vm: &mut H, obj_val: JsValue, key: &[u16]) -> Result<
|
||||
}
|
||||
p
|
||||
} else {
|
||||
vm.session().builtin_world().bigint_proto.as_ptr() as *mut JsObject
|
||||
vm.builtin_proto(ProtoKind::BigIntProto)
|
||||
};
|
||||
let tojson_si = vm.kernel_core().perm_interner().intern("toJSON").0;
|
||||
let tojson_si = vm.perm_intern("toJSON");
|
||||
// Get 语义查表:访问器形 toJSON 触发 getter(receiver = 原值,BigInt 原语
|
||||
// 以自身作 this),getter 异常传播原始抛出值。
|
||||
let fn_val = match vm.ordinary_get(unsafe { &*obj_ptr }, tojson_si, obj_val) {
|
||||
|
||||
@@ -7,7 +7,7 @@ use oxide_types::private_key::{
|
||||
};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
use oxide_runtime_api::{NativeResult, ProtoKind, VmHost};
|
||||
|
||||
use crate::builtins_debug;
|
||||
|
||||
@@ -53,7 +53,7 @@ pub fn walk_own_keys<H: VmHost>(vm: &H, obj: &JsObject) -> Vec<(u32, u32)> {
|
||||
if id == EMPTY_SHAPE_ID {
|
||||
break;
|
||||
}
|
||||
if let Some(shape) = vm.kernel_core().shape_forge().get_shape(id) {
|
||||
if let Some(shape) = vm.get_shape(id) {
|
||||
cursor = shape.parent;
|
||||
// Symbol 键/私有名键非字符串属性名,排除在字符串枚举之外(但仍占 shape
|
||||
// 槽位,pos 计数须含它们才能与物理存储对齐)。
|
||||
@@ -65,7 +65,7 @@ pub fn walk_own_keys<H: VmHost>(vm: &H, obj: &JsObject) -> Vec<(u32, u32)> {
|
||||
}
|
||||
}
|
||||
for id in shape_ids.iter().rev() {
|
||||
if let Some(shape) = vm.kernel_core().shape_forge().get_shape(*id) {
|
||||
if let Some(shape) = vm.get_shape(*id) {
|
||||
if !is_symbol_key(shape.property_name) && !is_private_name_key(shape.property_name) {
|
||||
// 绝对存储索引:数组命名属性位于元素区之后。
|
||||
let store = if obj.is_array() { obj.array_prop_count + pos } else { pos };
|
||||
@@ -77,7 +77,6 @@ pub fn walk_own_keys<H: VmHost>(vm: &H, obj: &JsObject) -> Vec<(u32, u32)> {
|
||||
// 类构造器属性序修正:shape 链构建序为 prototype→length→name(叶→根),
|
||||
// 规范要求的插入序为 length→name→prototype。按规范重排字符串键。
|
||||
if obj.is_class_constructor() {
|
||||
let perm = vm.kernel_core().perm_interner();
|
||||
let canonical = ["length", "name", "prototype"];
|
||||
let mut canonical_map: std::collections::HashMap<&str, usize> = std::collections::HashMap::new();
|
||||
for (i, &name) in canonical.iter().enumerate() {
|
||||
@@ -93,8 +92,8 @@ pub fn walk_own_keys<H: VmHost>(vm: &H, obj: &JsObject) -> Vec<(u32, u32)> {
|
||||
(None, Some(_)) => std::cmp::Ordering::Greater,
|
||||
(None, None) => {
|
||||
// 两者均为字符串键:查规范序。
|
||||
let a_name = perm.lookup(*a_si).unwrap_or("");
|
||||
let b_name = perm.lookup(*b_si).unwrap_or("");
|
||||
let a_name = vm.perm_lookup(*a_si).unwrap_or("");
|
||||
let b_name = vm.perm_lookup(*b_si).unwrap_or("");
|
||||
let a_rank = canonical_map.get(a_name).copied().unwrap_or(usize::MAX);
|
||||
let b_rank = canonical_map.get(b_name).copied().unwrap_or(usize::MAX);
|
||||
// 规范键按序排,其余保持原序。
|
||||
@@ -124,7 +123,7 @@ fn int_or_string_index<H: VmHost>(vm: &H, si: u32) -> Option<u32> {
|
||||
if is_int_key(si) {
|
||||
return Some(int_key_value(si));
|
||||
}
|
||||
let key = vm.kernel_core().perm_interner().lookup(si)?;
|
||||
let key = vm.perm_lookup(si)?;
|
||||
is_integer_index(key).then(|| key.parse::<u32>().ok()).flatten()
|
||||
}
|
||||
|
||||
@@ -136,9 +135,7 @@ pub fn key_si_to_js_value<H: VmHost>(vm: &mut H, si: u32) -> JsValue {
|
||||
return vm.new_string(&int_key_value(si).to_string());
|
||||
}
|
||||
let units = vm
|
||||
.kernel_core()
|
||||
.perm_interner()
|
||||
.lookup(si)
|
||||
.perm_lookup(si)
|
||||
.map(oxide_kernel::string_forge::decode_key)
|
||||
.unwrap_or_default();
|
||||
vm.new_string_units_owned(units)
|
||||
@@ -157,7 +154,7 @@ pub(crate) fn walk_own_symbol_keys<H: VmHost>(vm: &H, obj: &JsObject) -> Vec<(u3
|
||||
if id == EMPTY_SHAPE_ID {
|
||||
break;
|
||||
}
|
||||
if let Some(shape) = vm.kernel_core().shape_forge().get_shape(id) {
|
||||
if let Some(shape) = vm.get_shape(id) {
|
||||
cursor = shape.parent;
|
||||
if shape.property_name != u32::MAX {
|
||||
shape_ids.push(id);
|
||||
@@ -167,7 +164,7 @@ pub(crate) fn walk_own_symbol_keys<H: VmHost>(vm: &H, obj: &JsObject) -> Vec<(u3
|
||||
}
|
||||
}
|
||||
for (pos, id) in (0_u32..).zip(shape_ids.iter().rev()) {
|
||||
if let Some(shape) = vm.kernel_core().shape_forge().get_shape(*id) {
|
||||
if let Some(shape) = vm.get_shape(*id) {
|
||||
// Symbol 键节点按绝对槽位回传(数组命名属性位于元素区之后)。
|
||||
let store = if obj.is_array() { obj.array_prop_count + pos } else { pos };
|
||||
if is_symbol_key(shape.property_name) {
|
||||
@@ -233,7 +230,7 @@ pub fn sort_namespace_exports<H: VmHost>(vm: &mut H, obj: &mut JsObject) {
|
||||
obj.set_shape_id(EMPTY_SHAPE_ID);
|
||||
obj.clear_props();
|
||||
for (si, value, meta) in entries.into_iter().chain(symbols) {
|
||||
let shape = vm.kernel_core().shape_forge().make_shape(obj.shape_id(), si);
|
||||
let shape = vm.make_shape(obj.shape_id(), si);
|
||||
obj.set_shape_id(shape);
|
||||
let pos = obj.push_prop(value);
|
||||
if let Some(meta) = meta {
|
||||
@@ -252,11 +249,7 @@ fn namespace_key_units<H: VmHost>(vm: &H, si: u32) -> Vec<u16> {
|
||||
if is_int_key(si) {
|
||||
return int_key_value(si).to_string().encode_utf16().collect();
|
||||
}
|
||||
vm.kernel_core()
|
||||
.perm_interner()
|
||||
.lookup(si)
|
||||
.map(|key| key.encode_utf16().collect())
|
||||
.unwrap_or_default()
|
||||
vm.perm_lookup(si).map(|key| key.encode_utf16().collect()).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// `Object.getOwnPropertySymbols(obj)`:返回全部自身 Symbol 键数组。
|
||||
@@ -272,7 +265,7 @@ pub fn object_get_own_property_symbols<H: VmHost>(vm: &mut H, args: &[u8]) -> Na
|
||||
};
|
||||
|
||||
let n = symbols.len();
|
||||
let array_proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let array_proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), n));
|
||||
for (i, v) in symbols.iter().enumerate() {
|
||||
unsafe {
|
||||
@@ -290,7 +283,7 @@ fn array_index_of<H: VmHost>(vm: &H, key_si: u32) -> Option<u32> {
|
||||
if is_int_key(key_si) {
|
||||
return Some(int_key_value(key_si));
|
||||
}
|
||||
let key = vm.kernel_core().perm_interner().lookup(key_si)?;
|
||||
let key = vm.perm_lookup(key_si)?;
|
||||
if key.is_empty() || (key.len() > 1 && key.starts_with('0')) {
|
||||
return None;
|
||||
}
|
||||
@@ -375,7 +368,7 @@ pub fn delete_own_property_outcome<H: VmHost>(vm: &mut H, obj: &mut JsObject, ke
|
||||
}
|
||||
// 非下标键:length 是虚拟属性(无 shape 槽、不在元素区),但描述符声明
|
||||
// configurable:false,删除恒失败。
|
||||
if key_si == vm.kernel_core().perm_interner().intern("length").0 {
|
||||
if key_si == vm.perm_intern("length") {
|
||||
return DeleteOutcome::NonConfigurable;
|
||||
}
|
||||
}
|
||||
@@ -430,7 +423,7 @@ pub fn delete_own_property_outcome<H: VmHost>(vm: &mut H, obj: &mut JsObject, ke
|
||||
obj.set_shape_id(EMPTY_SHAPE_ID);
|
||||
obj.clear_props();
|
||||
for (si, value, meta) in retained {
|
||||
let shape = vm.kernel_core().shape_forge().make_shape(obj.shape_id(), si);
|
||||
let shape = vm.make_shape(obj.shape_id(), si);
|
||||
obj.set_shape_id(shape);
|
||||
let pos = obj.push_prop(value);
|
||||
if let Some(meta) = meta {
|
||||
@@ -475,7 +468,7 @@ pub fn delete_own_property<H: VmHost>(vm: &mut H, obj: &mut JsObject, key_si: u3
|
||||
/// JS `Object()` 构造逻辑:创建空对象(prototype 为 null,由 VM 补装内置原型)。
|
||||
pub fn object_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let object_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
// 对象参数原样返回;原始值参数创建对应 boxed 对象(规范 ToObject)。
|
||||
if val.is_object() {
|
||||
return NativeResult::Ok(val);
|
||||
@@ -485,7 +478,7 @@ pub fn object_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Ok(JsValue::from_js_object(obj));
|
||||
}
|
||||
if val.is_int() || val.is_double() {
|
||||
let proto = vm.session().builtin_world().number_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::NumberProto);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto)));
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
obj_ref.type_tag = JsObject::OBJ_TYPE_NUMBER_OBJ;
|
||||
@@ -493,7 +486,7 @@ pub fn object_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Ok(JsValue::from_js_object(obj));
|
||||
}
|
||||
if val.is_string() {
|
||||
let proto = vm.session().builtin_world().string_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::StringProto);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto)));
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
obj_ref.type_tag = JsObject::OBJ_TYPE_STRING_OBJ;
|
||||
@@ -502,7 +495,7 @@ pub fn object_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Ok(JsValue::from_js_object(obj));
|
||||
}
|
||||
if val.is_bool() {
|
||||
let proto = vm.session().builtin_world().boolean_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::BooleanProto);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto)));
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
obj_ref.type_tag = JsObject::OBJ_TYPE_BOOLEAN_OBJ;
|
||||
@@ -510,7 +503,7 @@ pub fn object_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Ok(JsValue::from_js_object(obj));
|
||||
}
|
||||
if val.is_symbol() {
|
||||
let proto = vm.session().builtin_world().symbol_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::SymbolProto);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto)));
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
obj_ref.type_tag = JsObject::OBJ_TYPE_SYMBOL_OBJ;
|
||||
@@ -518,7 +511,7 @@ pub fn object_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Ok(JsValue::from_js_object(obj));
|
||||
}
|
||||
if val.is_bigint() {
|
||||
let proto = vm.session().builtin_world().bigint_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::BigIntProto);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto)));
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
obj_ref.set_boxed_value(val);
|
||||
@@ -602,7 +595,7 @@ pub fn object_keys<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
}
|
||||
let n = owned_keys.len();
|
||||
let array_proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let array_proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), n));
|
||||
for (i, (si, _offset)) in owned_keys.iter().enumerate() {
|
||||
let key_val = key_si_to_js_value(vm, *si);
|
||||
@@ -780,12 +773,12 @@ pub(crate) fn define_from_descriptor<H: VmHost>(
|
||||
return Err(DefineDescFailure::Engine("Property description must be an object".to_string()));
|
||||
}
|
||||
|
||||
let value_si = vm.kernel_core().perm_interner().intern("value").0;
|
||||
let get_si = vm.kernel_core().perm_interner().intern("get").0;
|
||||
let set_si = vm.kernel_core().perm_interner().intern("set").0;
|
||||
let writable_si = vm.kernel_core().perm_interner().intern("writable").0;
|
||||
let enumerable_si = vm.kernel_core().perm_interner().intern("enumerable").0;
|
||||
let configurable_si = vm.kernel_core().perm_interner().intern("configurable").0;
|
||||
let value_si = vm.perm_intern("value");
|
||||
let get_si = vm.perm_intern("get");
|
||||
let set_si = vm.perm_intern("set");
|
||||
let writable_si = vm.perm_intern("writable");
|
||||
let enumerable_si = vm.perm_intern("enumerable");
|
||||
let configurable_si = vm.perm_intern("configurable");
|
||||
|
||||
// 六字段按规范序逐个 GetV,读取期异常原值传播(ReturnIfAbrupt)。
|
||||
let value_field = own_field(vm, desc_val, value_si)?;
|
||||
@@ -798,7 +791,7 @@ pub(crate) fn define_from_descriptor<H: VmHost>(
|
||||
// 数组 length 是无 shape 槽的虚拟数据属性:需与普通已有属性一样参与描述符
|
||||
// 缺省回填(writable 保持当前值、value 保持当前长度),其当前描述符由元素
|
||||
// 计数与独立可写位虚拟构造;enumerable/configurable 恒为 false。
|
||||
let length_si = vm.kernel_core().perm_interner().intern("length").0;
|
||||
let length_si = vm.perm_intern("length");
|
||||
let is_array_length = unsafe { &*obj_ptr }.is_array() && key_si == length_si;
|
||||
|
||||
let existing_pos = if is_array_length {
|
||||
@@ -1075,8 +1068,8 @@ fn own_descriptor_of<H: VmHost>(vm: &mut H, obj: &JsObject, key_si: u32) -> Resu
|
||||
{
|
||||
let value = crate::typed_array::typed_array_element_get(vm, obj, index).unwrap_or(JsValue::undefined());
|
||||
let desc = alloc_desc_object(vm);
|
||||
let sh_ptr = vm.kernel_core().shape_forge().as_ref() as *const ShapeForge;
|
||||
let sf_ptr = vm.kernel_core().perm_interner().as_ref() as *const PermInterner;
|
||||
let sh_ptr = vm.shape_forge_ptr() as *const ShapeForge;
|
||||
let sf_ptr = vm.perm_interner_ptr() as *const PermInterner;
|
||||
// SAFETY: desc 为本函数刚分配的 epoch 对象;sh/sf 为 kernel 永久引用。
|
||||
let d: &mut JsObject = unsafe { &mut *desc };
|
||||
let sh = unsafe { &*sh_ptr };
|
||||
@@ -1092,11 +1085,11 @@ fn own_descriptor_of<H: VmHost>(vm: &mut H, obj: &JsObject, key_si: u32) -> Resu
|
||||
// 数组 length 是虚拟属性(无 shape 槽,ordinary_get 直接返回逻辑长度):
|
||||
// 描述符 {value: len, writable: !frozen && 非显式收窄, enumerable: false,
|
||||
// configurable: false}。冻结数组与经 defineProperty 收窄的数组 writable=false。
|
||||
let length_si = vm.kernel_core().perm_interner().intern("length").0;
|
||||
let length_si = vm.perm_intern("length");
|
||||
if obj.is_array() && key_si == length_si {
|
||||
let desc = alloc_desc_object(vm);
|
||||
let sh_ptr = vm.kernel_core().shape_forge().as_ref() as *const ShapeForge;
|
||||
let sf_ptr = vm.kernel_core().perm_interner().as_ref() as *const PermInterner;
|
||||
let sh_ptr = vm.shape_forge_ptr() as *const ShapeForge;
|
||||
let sf_ptr = vm.perm_interner_ptr() as *const PermInterner;
|
||||
let d: &mut JsObject = unsafe { &mut *desc };
|
||||
let sh = unsafe { &*sh_ptr };
|
||||
let sf = unsafe { &*sf_ptr };
|
||||
@@ -1119,8 +1112,8 @@ fn own_descriptor_of<H: VmHost>(vm: &mut H, obj: &JsObject, key_si: u32) -> Resu
|
||||
let found_meta = obj.prop_meta_at(offset);
|
||||
|
||||
let desc = alloc_desc_object(vm);
|
||||
let sh_ptr = vm.kernel_core().shape_forge().as_ref() as *const ShapeForge;
|
||||
let sf_ptr = vm.kernel_core().perm_interner().as_ref() as *const PermInterner;
|
||||
let sh_ptr = vm.shape_forge_ptr() as *const ShapeForge;
|
||||
let sf_ptr = vm.perm_interner_ptr() as *const PermInterner;
|
||||
let d: &mut JsObject = unsafe { &mut *desc };
|
||||
let sh = unsafe { &*sh_ptr };
|
||||
let sf = unsafe { &*sf_ptr };
|
||||
@@ -1141,7 +1134,7 @@ fn own_descriptor_of<H: VmHost>(vm: &mut H, obj: &JsObject, key_si: u32) -> Resu
|
||||
|
||||
/// 分配空描述符对象(proto = %Object.prototype%)。
|
||||
fn alloc_desc_object<H: VmHost>(vm: &mut H) -> *mut JsObject {
|
||||
let desc_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let desc_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(desc_proto)))
|
||||
}
|
||||
|
||||
@@ -1207,7 +1200,7 @@ pub fn object_get_own_property_descriptors<H: VmHost>(vm: &mut H, args: &[u8]) -
|
||||
keys.extend(walk_own_symbol_keys(vm, obj));
|
||||
|
||||
// 结果对象:proto = %Object.prototype%。
|
||||
let desc_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let desc_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
let result = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(desc_proto)));
|
||||
let result_val = JsValue::from_js_object(result);
|
||||
|
||||
@@ -1509,7 +1502,7 @@ pub fn object_get_own_property_names<H: VmHost>(vm: &mut H, args: &[u8]) -> Nati
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
let keys = walk_own_keys(vm, obj);
|
||||
let n = keys.len();
|
||||
let array_proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let array_proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), n));
|
||||
for (i, (si, _)) in keys.iter().enumerate() {
|
||||
let key_val = key_si_to_js_value(vm, *si);
|
||||
@@ -1566,7 +1559,7 @@ pub fn object_from_entries<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if entries_ptr.is_null() {
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Object.fromEntries: argument must be iterable"));
|
||||
}
|
||||
let proto_ptr = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let proto_ptr = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto_ptr)));
|
||||
let target_val = JsValue::from_js_object(obj);
|
||||
// entry 数组的元素存元素区(元素区之外才是命名属性区),按元素区长度迭代。
|
||||
@@ -1740,7 +1733,7 @@ pub fn object_proto_to_locale_string<H: VmHost>(vm: &mut H, args: &[u8]) -> Nati
|
||||
Err(msg) => return NativeResult::Err(crate::error::create_type_error(vm, &msg)),
|
||||
};
|
||||
let obj = unsafe { &*obj_val.as_js_object_ptr() };
|
||||
let si_to_string = vm.kernel_core().perm_interner().intern("toString").0;
|
||||
let si_to_string = vm.perm_intern("toString");
|
||||
let to_str = match vm.ordinary_get(obj, si_to_string, this_val) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return NativeResult::Err(crate::iterator::engine_error(vm, &e)),
|
||||
@@ -2138,7 +2131,7 @@ pub fn object_entries<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
})
|
||||
.collect();
|
||||
let n = owned_keys.len();
|
||||
let array_proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let array_proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), n));
|
||||
let obj_val = JsValue::from_js_object(obj_ptr);
|
||||
for (i, (si, offset)) in owned_keys.iter().enumerate() {
|
||||
@@ -2205,7 +2198,7 @@ pub fn object_group_by<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Object.groupBy: iterator is not an object"));
|
||||
}
|
||||
let iter_obj = unsafe { &*iter_val.as_js_object_ptr() };
|
||||
let next_si = vm.kernel_core().perm_interner().intern("next").0;
|
||||
let next_si = vm.perm_intern("next");
|
||||
let next_fn = match vm.ordinary_get(iter_obj, next_si, iter_val) {
|
||||
Ok(f) => f,
|
||||
Err(e) => return NativeResult::Err(crate::iterator::engine_error(vm, &e)),
|
||||
@@ -2231,7 +2224,7 @@ pub fn object_group_by<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
));
|
||||
}
|
||||
let nr = unsafe { &*next_result.as_js_object_ptr() };
|
||||
let done_si = vm.kernel_core().perm_interner().intern("done").0;
|
||||
let done_si = vm.perm_intern("done");
|
||||
let done = match vm.ordinary_get(nr, done_si, next_result) {
|
||||
Ok(v) => oxide_runtime_api::to_boolean(v),
|
||||
Err(e) => return NativeResult::Err(crate::iterator::engine_error(vm, &e)),
|
||||
@@ -2239,7 +2232,7 @@ pub fn object_group_by<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if done {
|
||||
break;
|
||||
}
|
||||
let value_si = vm.kernel_core().perm_interner().intern("value").0;
|
||||
let value_si = vm.perm_intern("value");
|
||||
let element = match vm.ordinary_get(nr, value_si, next_result) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return NativeResult::Err(crate::iterator::engine_error(vm, &e)),
|
||||
@@ -2280,7 +2273,7 @@ pub fn object_group_by<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let arr_val = if let Some(existing) = existing {
|
||||
existing
|
||||
} else {
|
||||
let arr_proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let arr_proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(arr_proto), 0));
|
||||
let new_arr_val = JsValue::from_js_object(arr);
|
||||
let result_ref_mut = unsafe { &mut *result };
|
||||
@@ -2313,7 +2306,7 @@ pub fn object_values<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
})
|
||||
.collect();
|
||||
let n = owned_keys.len();
|
||||
let array_proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let array_proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), n));
|
||||
let obj_val = JsValue::from_js_object(obj_ptr);
|
||||
for (i, (si, offset)) in owned_keys.iter().enumerate() {
|
||||
|
||||
@@ -2,7 +2,7 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::{JsObject, NativeFnPtr};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
use oxide_runtime_api::{NativeResult, ProtoKind, VmHost};
|
||||
|
||||
use crate::string::{make_units_array, MatchText, OwnedText};
|
||||
|
||||
@@ -20,7 +20,7 @@ pub(crate) fn build_groups_object<H: VmHost>(vm: &mut H, m: ®ress::Match, tex
|
||||
|
||||
// 遍历所有命名捕获组,按名称设置属性(重复名称取首个已定义的出现)。
|
||||
for (name, range) in named {
|
||||
let name_si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let name_si = vm.perm_intern(name);
|
||||
let value = match range {
|
||||
Some(r) => vm.new_string_units_owned(text.slice(r.start, r.end).into_owned()),
|
||||
None => JsValue::undefined(),
|
||||
@@ -37,7 +37,7 @@ pub(crate) fn build_groups_object<H: VmHost>(vm: &mut H, m: ®ress::Match, tex
|
||||
pub(crate) fn build_indices_array<H: VmHost>(vm: &mut H, m: ®ress::Match, text: &MatchText) -> JsValue {
|
||||
let group_count = m.captures.len();
|
||||
let n = 1 + group_count;
|
||||
let proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(proto), n));
|
||||
unsafe {
|
||||
let range = m.range();
|
||||
@@ -52,14 +52,14 @@ pub(crate) fn build_indices_array<H: VmHost>(vm: &mut H, m: ®ress::Match, tex
|
||||
(*arr).set_prop_count(n);
|
||||
}
|
||||
let groups_val = build_indices_groups_object(vm, m, text);
|
||||
let groups_si = vm.kernel_core().perm_interner().intern("groups").0;
|
||||
let groups_si = vm.perm_intern("groups");
|
||||
vm.set_or_create_prop_value(unsafe { &mut *arr }, groups_si, groups_val);
|
||||
JsValue::from_js_object(arr)
|
||||
}
|
||||
|
||||
/// 单个 [start, end] 码元对数组(数组原型,两个自身元素)。
|
||||
fn index_pair<H: VmHost>(vm: &mut H, start: usize, end: usize) -> JsValue {
|
||||
let proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(proto), 2));
|
||||
unsafe {
|
||||
(*arr).set_prop_at(0, JsValue::int(start as i32));
|
||||
@@ -79,7 +79,7 @@ fn build_indices_groups_object<H: VmHost>(vm: &mut H, m: ®ress::Match, text:
|
||||
let groups_obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let groups_ptr = unsafe { &mut *groups_obj };
|
||||
for (name, range) in named {
|
||||
let name_si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let name_si = vm.perm_intern(name);
|
||||
let value = match range {
|
||||
Some(r) => index_pair(vm, text.unit_pos(r.start), text.unit_pos(r.end)),
|
||||
None => JsValue::undefined(),
|
||||
@@ -145,7 +145,7 @@ pub(crate) fn to_length_value<H: VmHost>(vm: &mut H, val: JsValue) -> Result<usi
|
||||
fn set_last_index<H: VmHost>(
|
||||
vm: &mut H, re_ptr: *mut JsObject, this_val: JsValue, index: usize,
|
||||
) -> Result<(), JsValue> {
|
||||
let li_si = vm.kernel_core().perm_interner().intern("lastIndex").0;
|
||||
let li_si = vm.perm_intern("lastIndex");
|
||||
// setter 抛错优先恢复 uncaught 原异常值(与 rx_set_prop 同口径)。
|
||||
match vm.ordinary_set(unsafe { &mut *re_ptr }, li_si, JsValue::int(index as i32), this_val, true) {
|
||||
Ok(()) => Ok(()),
|
||||
@@ -158,7 +158,7 @@ fn set_last_index<H: VmHost>(
|
||||
pub(crate) fn rx_get_prop<H: VmHost>(
|
||||
vm: &mut H, obj: *mut JsObject, name: &str, this_val: JsValue,
|
||||
) -> Result<JsValue, JsValue> {
|
||||
let si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let si = vm.perm_intern(name);
|
||||
match vm.ordinary_get(unsafe { &*obj }, si, this_val) {
|
||||
Ok(v) => Ok(v),
|
||||
Err(_) => Err(crate::iterator::engine_error(vm, "cannot read property")),
|
||||
@@ -181,7 +181,7 @@ pub(crate) fn rx_get_index<H: VmHost>(
|
||||
pub(crate) fn rx_set_prop<H: VmHost>(
|
||||
vm: &mut H, obj: *mut JsObject, name: &str, val: JsValue, this_val: JsValue,
|
||||
) -> Result<(), JsValue> {
|
||||
let si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let si = vm.perm_intern(name);
|
||||
// setter 抛错时原异常值留在 uncaught 槽(优先恢复);写保护失败无
|
||||
// uncaught,经格式化文本的 "TypeError: " 前缀恢复种类。
|
||||
match vm.ordinary_set(unsafe { &mut *obj }, si, val, this_val, true) {
|
||||
@@ -311,7 +311,7 @@ pub(crate) fn get_substitution_units<H: VmHost>(
|
||||
(Some(end), Some(obj)) => {
|
||||
let name_units = &rest[2..2 + end];
|
||||
let name_str = String::from_utf16_lossy(name_units);
|
||||
let si = vm.kernel_core().perm_interner().intern(&name_str).0;
|
||||
let si = vm.perm_intern(&name_str);
|
||||
// 真 Get 走完整原型链;getter 抛错恢复原异常上抛。
|
||||
let cap = match vm.ordinary_get(
|
||||
obj,
|
||||
@@ -372,12 +372,12 @@ pub(crate) fn get_substitution_units<H: VmHost>(
|
||||
}
|
||||
|
||||
fn set_prop<H: VmHost>(obj: &mut JsObject, name: &str, val: JsValue, vm: &H) {
|
||||
let si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let si = vm.perm_intern(name);
|
||||
set_prop_by_si(obj, si, val, vm);
|
||||
}
|
||||
|
||||
fn set_prop_by_si<H: VmHost>(obj: &mut JsObject, prop_name_si: u32, val: JsValue, vm: &H) {
|
||||
let shape_id = vm.kernel_core().shape_forge().make_shape(obj.shape_id(), prop_name_si);
|
||||
let shape_id = vm.make_shape(obj.shape_id(), prop_name_si);
|
||||
obj.set_shape_id(shape_id);
|
||||
obj.ensure_hash_props().push(val);
|
||||
}
|
||||
@@ -490,10 +490,8 @@ pub fn regexp_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
));
|
||||
}
|
||||
|
||||
let mut obj = JsObject::new_empty(
|
||||
EMPTY_SHAPE_ID,
|
||||
JsValue::from_js_object(vm.session().builtin_world().regexp_proto.as_ptr() as *mut JsObject),
|
||||
);
|
||||
let mut obj =
|
||||
JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(vm.builtin_proto(ProtoKind::RegExpProto)));
|
||||
|
||||
// regress 用 JS flag 字符串编译:g/i/m/s/y/u/v 原样透传(vendored fork
|
||||
// 原生识别 v 标志,u/v 互斥已在上方前置校验)。
|
||||
@@ -632,7 +630,7 @@ pub(crate) fn rx_search<H: VmHost>(
|
||||
// lastIndex 读无条件执行(规范先读后在非 global/sticky 臂丢弃);
|
||||
// 读走 Get + ToLength:完整属性解析,读异常传播原异常。
|
||||
let last_index = {
|
||||
let li_si = vm.kernel_core().perm_interner().intern("lastIndex").0;
|
||||
let li_si = vm.perm_intern("lastIndex");
|
||||
match vm.ordinary_get(unsafe { &*re_ptr }, li_si, this_val) {
|
||||
Ok(val) => to_length_value(vm, val)?,
|
||||
Err(_) => {
|
||||
@@ -746,7 +744,7 @@ pub fn regexp_exec<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let range = m.range();
|
||||
let group_count = m.captures.len();
|
||||
let n = 1 + group_count;
|
||||
let proto = vm.session().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::ArrayProto);
|
||||
let arr = vm.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(proto), n));
|
||||
unsafe {
|
||||
(*arr).set_prop_at(0, vm.new_string_units_owned(text.slice(range.start, range.end).into_owned()));
|
||||
@@ -760,19 +758,19 @@ pub fn regexp_exec<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
(*arr).set_prop_count(n);
|
||||
}
|
||||
|
||||
let index_si = vm.kernel_core().perm_interner().intern("index").0;
|
||||
let index_si = vm.perm_intern("index");
|
||||
vm.set_or_create_prop_value(unsafe { &mut *arr }, index_si, JsValue::int(text.unit_pos(range.start) as i32));
|
||||
let input_val = haystack.to_value(vm);
|
||||
let input_si = vm.kernel_core().perm_interner().intern("input").0;
|
||||
let input_si = vm.perm_intern("input");
|
||||
vm.set_or_create_prop_value(unsafe { &mut *arr }, input_si, input_val);
|
||||
let groups_val = build_groups_object(vm, &m, &text);
|
||||
let groups_si = vm.kernel_core().perm_interner().intern("groups").0;
|
||||
let groups_si = vm.perm_intern("groups");
|
||||
vm.set_or_create_prop_value(unsafe { &mut *arr }, groups_si, groups_val);
|
||||
|
||||
// d 标志:挂 indices 属性(逐组 [start, end] 码元对 + indices.groups 同构对象)。
|
||||
if has_indices {
|
||||
let indices_val = build_indices_array(vm, &m, &text);
|
||||
let indices_si = vm.kernel_core().perm_interner().intern("indices").0;
|
||||
let indices_si = vm.perm_intern("indices");
|
||||
vm.set_or_create_prop_value(unsafe { &mut *arr }, indices_si, indices_val);
|
||||
}
|
||||
|
||||
@@ -921,7 +919,7 @@ fn regexp_flag_of<H: VmHost>(vm: &mut H, args: &[u8], unit: char) -> NativeResul
|
||||
let this_val = vm.reg(args[0]);
|
||||
if this_val.is_object() {
|
||||
let this_ptr = this_val.as_js_object_ptr();
|
||||
let proto_ptr = vm.session().builtin_world().regexp_proto.as_ptr() as *mut JsObject;
|
||||
let proto_ptr = vm.builtin_proto(ProtoKind::RegExpProto);
|
||||
if !this_ptr.is_null() && this_ptr == proto_ptr {
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
@@ -1027,7 +1025,7 @@ pub fn regexp_get_source<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
// proto 恒等判定:规范对 prototype 本身返回 "(?:)"(无 [[OriginalFlags]] 槽时)。
|
||||
if this_val.is_object() {
|
||||
let this_ptr = this_val.as_js_object_ptr();
|
||||
let proto_ptr = vm.session().builtin_world().regexp_proto.as_ptr() as *mut JsObject;
|
||||
let proto_ptr = vm.builtin_proto(ProtoKind::RegExpProto);
|
||||
if !this_ptr.is_null() && this_ptr == proto_ptr {
|
||||
return NativeResult::Ok(vm.new_string_units_owned(vec!['(' as u16, '?' as u16, ':' as u16, ')' as u16]));
|
||||
}
|
||||
@@ -1684,7 +1682,7 @@ pub fn regexp_symbol_split<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
|
||||
// 物种构造 + y 标志:splitter 是后续唯一匹配面。
|
||||
let regexp_ctor = vm.session().builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
|
||||
let regexp_ctor = vm.builtin_proto(ProtoKind::RegExpConstructor);
|
||||
let regexp_ctor_val = JsValue::from_js_object(regexp_ctor);
|
||||
let c = match species_constructor(vm, re_ptr, this_val, regexp_ctor_val) {
|
||||
Ok(c) => c,
|
||||
@@ -1841,7 +1839,7 @@ pub fn regexp_symbol_match_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResu
|
||||
_ => true,
|
||||
};
|
||||
|
||||
let regexp_ctor = vm.session().builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
|
||||
let regexp_ctor = vm.builtin_proto(ProtoKind::RegExpConstructor);
|
||||
let regexp_ctor_val = JsValue::from_js_object(regexp_ctor);
|
||||
let matcher_val = if is_regexp {
|
||||
let c = match species_constructor(vm, re_ptr, this_val, regexp_ctor_val) {
|
||||
@@ -1879,14 +1877,14 @@ pub fn regexp_symbol_match_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResu
|
||||
}
|
||||
|
||||
// 迭代器包装:五槽(input/re/done/global/unicode),next 由原型提供。
|
||||
let regexp_iter_proto = vm.session().builtin_world().regexp_string_iterator_proto.as_ptr() as *mut JsObject;
|
||||
let regexp_iter_proto = vm.builtin_proto(ProtoKind::RegExpStringIteratorProto);
|
||||
let wrapper = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(regexp_iter_proto)));
|
||||
let wrapper_obj = unsafe { &mut *wrapper };
|
||||
let input_si = vm.kernel_core().perm_interner().intern(crate::string::MALL_INPUT).0;
|
||||
let re_si = vm.kernel_core().perm_interner().intern(crate::string::MALL_RE).0;
|
||||
let done_si = vm.kernel_core().perm_interner().intern(crate::string::MALL_DONE).0;
|
||||
let global_si = vm.kernel_core().perm_interner().intern(crate::string::MALL_GLOBAL).0;
|
||||
let unicode_si = vm.kernel_core().perm_interner().intern(crate::string::MALL_UNICODE).0;
|
||||
let input_si = vm.perm_intern(crate::string::MALL_INPUT);
|
||||
let re_si = vm.perm_intern(crate::string::MALL_RE);
|
||||
let done_si = vm.perm_intern(crate::string::MALL_DONE);
|
||||
let global_si = vm.perm_intern(crate::string::MALL_GLOBAL);
|
||||
let unicode_si = vm.perm_intern(crate::string::MALL_UNICODE);
|
||||
// [[Global]]/[[Unicode]] 由 flags 串判定(u/v 均码点口径);input 属性存
|
||||
// 完整转换后的字符串值(单元保真),游标归匹配器 lastIndex(已写入)。
|
||||
vm.set_or_create_prop_value(wrapper_obj, input_si, s_val);
|
||||
|
||||
@@ -2,7 +2,7 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
use oxide_runtime_api::{NativeResult, ProtoKind, VmHost};
|
||||
|
||||
use crate::builtins_debug;
|
||||
use crate::builtins_error;
|
||||
@@ -54,7 +54,7 @@ fn is_regexp_obj<H: VmHost>(val: JsValue, vm: &H) -> bool {
|
||||
if proto_ptr.is_null() {
|
||||
return false;
|
||||
}
|
||||
let rp = vm.session().builtin_world().regexp_proto.as_ptr() as *mut JsObject;
|
||||
let rp = vm.builtin_proto(ProtoKind::RegExpProto);
|
||||
std::ptr::eq(proto_ptr, rp)
|
||||
}
|
||||
|
||||
@@ -347,11 +347,7 @@ fn string_replace_impl<H: VmHost>(vm: &mut H, args: &[u8], all: bool) -> NativeR
|
||||
// ToString 须含 "g"(转换异常传播)。
|
||||
let re_ptr = pattern_val.as_js_object_ptr();
|
||||
// SAFETY: pattern_val 已校验为非空对象值。
|
||||
let flags_val = match vm.ordinary_get(
|
||||
unsafe { &*re_ptr },
|
||||
vm.kernel_core().perm_interner().intern("flags").0,
|
||||
pattern_val,
|
||||
) {
|
||||
let flags_val = match vm.ordinary_get(unsafe { &*re_ptr }, vm.perm_intern("flags"), pattern_val) {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
if let Some(exc) = vm.take_uncaught_value() {
|
||||
@@ -545,7 +541,7 @@ pub fn string_match_fn<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
// 非对象 / matcher undefined:Construct %RegExp%(undefined → 空模式、其余
|
||||
// 经 ToString),再 GetMethod(rx, @@match) + Invoke;转换抛错(含 Symbol)
|
||||
// 原样传播。
|
||||
let regexp_ctor = vm.session().builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
|
||||
let regexp_ctor = vm.builtin_proto(ProtoKind::RegExpConstructor);
|
||||
let rx_val = match vm.construct_ctor(JsValue::from_js_object(regexp_ctor), &[pattern_val]) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return NativeResult::Err(e),
|
||||
@@ -656,7 +652,7 @@ pub fn string_search<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
|
||||
// 非对象 / searcher undefined:Construct %RegExp% + GetMethod(rx, @@search)
|
||||
// + Invoke(rx, «string»);转换抛错(含 Symbol)原样传播。
|
||||
let regexp_ctor = vm.session().builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
|
||||
let regexp_ctor = vm.builtin_proto(ProtoKind::RegExpConstructor);
|
||||
let rx_val = match vm.construct_ctor(JsValue::from_js_object(regexp_ctor), &[pattern_val]) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return NativeResult::Err(e),
|
||||
@@ -814,7 +810,7 @@ pub fn string_match_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let re_ptr = pattern_val.as_js_object_ptr();
|
||||
// SAFETY: pattern_val 已校验为非空对象值。
|
||||
let re_obj = unsafe { &*re_ptr };
|
||||
let flags_si = vm.kernel_core().perm_interner().intern("flags").0;
|
||||
let flags_si = vm.perm_intern("flags");
|
||||
let flags_val = match vm.ordinary_get(re_obj, flags_si, pattern_val) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return NativeResult::err(crate::iterator::engine_error(vm, &e)),
|
||||
@@ -883,7 +879,7 @@ pub fn string_match_all<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
return NativeResult::Err(crate::error::create_syntax_error(vm, &format!("Invalid regex: {}", e)));
|
||||
}
|
||||
};
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let object_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
let mut stub = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto));
|
||||
// 载体专型标签:native_fn 槽的 Box 经 RegExp 同一守卫释放/深拷贝,
|
||||
// 避免每次 matchAll 泄漏一个已编译正则。
|
||||
@@ -931,7 +927,7 @@ fn match_all_construct_invoke<H: VmHost>(vm: &mut H, this_val: JsValue, pattern_
|
||||
|
||||
// regexp = RegExpCreate(pattern, "g")。
|
||||
let g_str = vm.new_string("g");
|
||||
let ctor_ptr = vm.session().builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
|
||||
let ctor_ptr = vm.builtin_proto(ProtoKind::RegExpConstructor);
|
||||
let rx_val = match vm.construct_ctor(JsValue::from_js_object(ctor_ptr), &[pattern_val, g_str]) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return NativeResult::Err(e),
|
||||
@@ -973,15 +969,15 @@ fn match_all_construct_invoke<H: VmHost>(vm: &mut H, this_val: JsValue, pattern_
|
||||
fn builder_wrapper<H: VmHost>(vm: &mut H, input_val: JsValue, re_obj: JsValue) -> NativeResult {
|
||||
// matchAll 迭代器挂 %RegExpStringIteratorPrototype%(链到 %IteratorPrototype%),
|
||||
// next 由原型提供(不挂实例 own)。
|
||||
let regexp_iter_proto = vm.session().builtin_world().regexp_string_iterator_proto.as_ptr() as *mut JsObject;
|
||||
let regexp_iter_proto = vm.builtin_proto(ProtoKind::RegExpStringIteratorProto);
|
||||
let wrapper = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(regexp_iter_proto)));
|
||||
|
||||
let wrapper_obj = unsafe { &mut *wrapper };
|
||||
let input_si = vm.kernel_core().perm_interner().intern(MALL_INPUT).0;
|
||||
let re_si = vm.kernel_core().perm_interner().intern(MALL_RE).0;
|
||||
let done_si = vm.kernel_core().perm_interner().intern(MALL_DONE).0;
|
||||
let global_si = vm.kernel_core().perm_interner().intern(MALL_GLOBAL).0;
|
||||
let unicode_si = vm.kernel_core().perm_interner().intern(MALL_UNICODE).0;
|
||||
let input_si = vm.perm_intern(MALL_INPUT);
|
||||
let re_si = vm.perm_intern(MALL_RE);
|
||||
let done_si = vm.perm_intern(MALL_DONE);
|
||||
let global_si = vm.perm_intern(MALL_GLOBAL);
|
||||
let unicode_si = vm.perm_intern(MALL_UNICODE);
|
||||
|
||||
vm.set_or_create_prop_value(wrapper_obj, input_si, input_val);
|
||||
vm.set_or_create_prop_value(wrapper_obj, re_si, re_obj);
|
||||
@@ -1023,7 +1019,7 @@ pub fn string_symbol_iterator<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResul
|
||||
// 直构 String 迭代器:内层即 ToString 结果,不再回读 @@iterator。本函数语义
|
||||
// 只由 this 决定,属性表被删除/置 null/被覆盖均不影响已保存引用的直调。
|
||||
// 迭代器挂 %StringIteratorPrototype%(链到 %IteratorPrototype%);串内层不暴露 return。
|
||||
let string_iter_proto = vm.session().builtin_world().string_iterator_proto.as_ptr() as *mut JsObject;
|
||||
let string_iter_proto = vm.builtin_proto(ProtoKind::StringIteratorProto);
|
||||
NativeResult::Ok(crate::iterator::build_iterator_wrapper(vm, s_val, None, true, Some(string_iter_proto)))
|
||||
}
|
||||
|
||||
@@ -1057,11 +1053,11 @@ pub fn string_match_all_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "matchAll next called on non-object"));
|
||||
}
|
||||
let wrapper = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||
let input_si = vm.kernel_core().perm_interner().intern(MALL_INPUT).0;
|
||||
let re_si = vm.kernel_core().perm_interner().intern(MALL_RE).0;
|
||||
let done_si = vm.kernel_core().perm_interner().intern(MALL_DONE).0;
|
||||
let global_si = vm.kernel_core().perm_interner().intern(MALL_GLOBAL).0;
|
||||
let unicode_si = vm.kernel_core().perm_interner().intern(MALL_UNICODE).0;
|
||||
let input_si = vm.perm_intern(MALL_INPUT);
|
||||
let re_si = vm.perm_intern(MALL_RE);
|
||||
let done_si = vm.perm_intern(MALL_DONE);
|
||||
let global_si = vm.perm_intern(MALL_GLOBAL);
|
||||
let unicode_si = vm.perm_intern(MALL_UNICODE);
|
||||
|
||||
// 内部槽守卫:五槽同批写入,查一槽即全查;缺失即 TypeError。
|
||||
if vm.get_own_property_slot(wrapper, done_si).is_none() {
|
||||
@@ -1221,21 +1217,21 @@ fn make_match_result_array<H: VmHost>(
|
||||
let arr = make_string_array_values(vm, parts);
|
||||
let arr_ptr = arr.as_js_object_ptr();
|
||||
let arr_obj = unsafe { &mut *arr_ptr };
|
||||
let index_si = vm.kernel_core().perm_interner().intern("index").0;
|
||||
let index_si = vm.perm_intern("index");
|
||||
vm.set_or_create_prop_value(arr_obj, index_si, JsValue::int(match_index));
|
||||
let input_si = vm.kernel_core().perm_interner().intern("input").0;
|
||||
let input_si = vm.perm_intern("input");
|
||||
vm.set_or_create_prop_value(arr_obj, input_si, input_val);
|
||||
let groups_val = match m {
|
||||
Some(m) => build_groups_object(vm, m, text),
|
||||
None => JsValue::undefined(),
|
||||
};
|
||||
let groups_si = vm.kernel_core().perm_interner().intern("groups").0;
|
||||
let groups_si = vm.perm_intern("groups");
|
||||
vm.set_or_create_prop_value(arr_obj, groups_si, groups_val);
|
||||
// d 标志:挂 indices 属性(与 exec 结果同口径的码元对数组族)。
|
||||
if has_indices {
|
||||
if let Some(m) = m {
|
||||
let indices_val = crate::regexp::build_indices_array(vm, m, text);
|
||||
let indices_si = vm.kernel_core().perm_interner().intern("indices").0;
|
||||
let indices_si = vm.perm_intern("indices");
|
||||
vm.set_or_create_prop_value(arr_obj, indices_si, indices_val);
|
||||
}
|
||||
}
|
||||
@@ -1245,10 +1241,10 @@ fn make_match_result_array<H: VmHost>(
|
||||
/// 构造迭代器结果对象 `{value, done}`(done 仅在 value 为 undefined 时为 true)。
|
||||
fn make_match_done_result<H: VmHost>(vm: &mut H, value: JsValue) -> NativeResult {
|
||||
let done = value.is_undefined();
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let object_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto)));
|
||||
let value_si = vm.kernel_core().perm_interner().intern("value").0;
|
||||
let done_si = vm.kernel_core().perm_interner().intern("done").0;
|
||||
let value_si = vm.perm_intern("value");
|
||||
let done_si = vm.perm_intern("done");
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
vm.set_or_create_prop_value(obj_ref, value_si, value);
|
||||
vm.set_or_create_prop_value(obj_ref, done_si, JsValue::bool(done));
|
||||
@@ -1286,7 +1282,7 @@ pub fn string_raw<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let template_ptr = template_val.as_js_object_ptr();
|
||||
|
||||
// Step 2: 取 template.raw 属性。
|
||||
let raw_si = vm.kernel_core().perm_interner().intern("raw").0;
|
||||
let raw_si = vm.perm_intern("raw");
|
||||
let template_obj = unsafe { &*template_ptr };
|
||||
let raw_val = match vm.ordinary_get(template_obj, raw_si, template_val) {
|
||||
Ok(v) => v,
|
||||
@@ -1303,7 +1299,7 @@ pub fn string_raw<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let raw_ptr = raw_val.as_js_object_ptr();
|
||||
|
||||
// Step 3: 取 raw.length(ToLength,Symbol 抛 TypeError)。
|
||||
let length_si = vm.kernel_core().perm_interner().intern("length").0;
|
||||
let length_si = vm.perm_intern("length");
|
||||
let raw_obj = unsafe { &*raw_ptr };
|
||||
let raw_len = match vm.ordinary_get(raw_obj, length_si, raw_val) {
|
||||
Ok(v) => {
|
||||
|
||||
@@ -26,11 +26,10 @@ use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::mem::P;
|
||||
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use oxide_runtime_api::{to_string_full, NativeResult, VmHost};
|
||||
use oxide_runtime_api::{to_string_full, NativeResult, ProtoKind, VmHost};
|
||||
|
||||
use crate::array::create_new_array;
|
||||
use crate::map::MapInner;
|
||||
@@ -111,7 +110,7 @@ fn parse_transfer_list<H: VmHost>(vm: &mut H, options: JsValue, state: &mut Clon
|
||||
let opt_ptr = options.as_js_object_ptr();
|
||||
// SAFETY: is_object 保证非空指针(入口已过滤);对象在 native 执行期间被根保持、不被回收。
|
||||
let opt = unsafe { &*opt_ptr };
|
||||
let si_transfer = vm.kernel_core().perm_interner().intern("transfer").0;
|
||||
let si_transfer = vm.perm_intern("transfer");
|
||||
let transfer_val = match vm.ordinary_get(opt, si_transfer, options) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
@@ -289,7 +288,7 @@ fn fill_error<H: VmHost>(
|
||||
vm: &mut H, state: &mut CloneState, src: &JsObject, clone_ptr: *mut JsObject,
|
||||
) -> Result<(), JsValue> {
|
||||
let src_val = JsValue::from_js_object(src as *const JsObject as *mut JsObject);
|
||||
let si_msg = vm.kernel_core().perm_interner().intern("message").0;
|
||||
let si_msg = vm.perm_intern("message");
|
||||
if let Some(store) = vm.get_own_property_slot(src, si_msg) {
|
||||
// message 仅数据描述符复制:访问器不触发 getter、不复制。
|
||||
let is_accessor = src.prop_meta_at(store).is_some_and(|m| m.is_accessor);
|
||||
@@ -308,7 +307,7 @@ fn fill_error<H: VmHost>(
|
||||
define_on_clone(vm, clone_ptr, si_msg, msg_val, PropAttributes::new(true, false, true))?;
|
||||
}
|
||||
}
|
||||
let si_cause = vm.kernel_core().perm_interner().intern("cause").0;
|
||||
let si_cause = vm.perm_intern("cause");
|
||||
if let Some(store) = vm.get_own_property_slot(src, si_cause) {
|
||||
let val = read_own_value(vm, src, src_val, si_cause, store)?;
|
||||
let cloned = clone_value(vm, state, val)?;
|
||||
@@ -443,7 +442,7 @@ fn fill_set<H: VmHost>(
|
||||
|
||||
/// 分配 plain 对象克隆(proto = %Object.prototype%)。
|
||||
fn alloc_plain_clone<H: VmHost>(vm: &mut H) -> *mut JsObject {
|
||||
let proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto)))
|
||||
}
|
||||
|
||||
@@ -468,7 +467,7 @@ fn alloc_array_clone<H: VmHost>(vm: &mut H, src: &JsObject) -> *mut JsObject {
|
||||
|
||||
/// 分配 Map 克隆(空 `MapInner`,proto = %Map.prototype%)。
|
||||
fn alloc_map_clone<H: VmHost>(vm: &mut H) -> *mut JsObject {
|
||||
let map_proto = vm.session().builtin_world().map_proto.as_ptr() as *mut JsObject;
|
||||
let map_proto = vm.builtin_proto(ProtoKind::MapProto);
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(map_proto));
|
||||
obj.set_map(true);
|
||||
let inner = Box::into_raw(Box::new(MapInner::new()));
|
||||
@@ -478,7 +477,7 @@ fn alloc_map_clone<H: VmHost>(vm: &mut H) -> *mut JsObject {
|
||||
|
||||
/// 分配 Set 克隆(空 `SetInner`,proto = %Set.prototype%)。
|
||||
fn alloc_set_clone<H: VmHost>(vm: &mut H) -> *mut JsObject {
|
||||
let set_proto = vm.session().builtin_world().set_proto.as_ptr() as *mut JsObject;
|
||||
let set_proto = vm.builtin_proto(ProtoKind::SetProto);
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(set_proto));
|
||||
obj.set_set(true);
|
||||
let inner = Box::into_raw(Box::new(SetInner::new()));
|
||||
@@ -488,7 +487,7 @@ fn alloc_set_clone<H: VmHost>(vm: &mut H) -> *mut JsObject {
|
||||
|
||||
/// 分配 Date 克隆(同时间戳,proto = %Date.prototype%)。
|
||||
fn alloc_date_clone<H: VmHost>(vm: &mut H, src: &JsObject) -> *mut JsObject {
|
||||
let proto = vm.session().builtin_world().date_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::DateProto);
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto));
|
||||
obj.type_tag = JsObject::OBJ_TYPE_DATE;
|
||||
obj.set_prop_at(0, src.get_prop_at(0));
|
||||
@@ -501,7 +500,7 @@ fn alloc_date_clone<H: VmHost>(vm: &mut H, src: &JsObject) -> *mut JsObject {
|
||||
/// - 源模式非法(理论上不发生,源已是合法 RegExp)时抛 SyntaxError;
|
||||
/// - lastIndex 初始化为 0(writable / 非枚举 / 非可配置)。
|
||||
fn alloc_regexp_clone<H: VmHost>(vm: &mut H, src: &JsObject) -> Result<*mut JsObject, JsValue> {
|
||||
let proto = vm.session().builtin_world().regexp_proto.as_ptr() as *mut JsObject;
|
||||
let proto = vm.builtin_proto(ProtoKind::RegExpProto);
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto));
|
||||
let source_val = src.get_regexp_source();
|
||||
let flags_val = src.get_regexp_flags();
|
||||
@@ -521,7 +520,7 @@ fn alloc_regexp_clone<H: VmHost>(vm: &mut H, src: &JsObject) -> Result<*mut JsOb
|
||||
obj.type_tag = JsObject::OBJ_TYPE_REGEXP;
|
||||
obj.set_regexp_source(source_val);
|
||||
obj.set_regexp_flags(flags_val);
|
||||
let si_lastindex = vm.kernel_core().perm_interner().intern("lastIndex").0;
|
||||
let si_lastindex = vm.perm_intern("lastIndex");
|
||||
let _ = vm.define_data_property(&mut obj, si_lastindex, JsValue::int(0), PropAttributes::new(true, false, false));
|
||||
Ok(vm.alloc_object(obj))
|
||||
}
|
||||
@@ -534,7 +533,7 @@ fn alloc_regexp_clone<H: VmHost>(vm: &mut H, src: &JsObject) -> Result<*mut JsOb
|
||||
/// - 克隆原型与源原型解耦(源子类原型丢弃,按规范反序列化口径回落标准原型)。
|
||||
fn alloc_error_clone<H: VmHost>(vm: &mut H, src: &JsObject) -> Result<*mut JsObject, JsValue> {
|
||||
let src_val = JsValue::from_js_object(src as *const JsObject as *mut JsObject);
|
||||
let si_name = vm.kernel_core().perm_interner().intern("name").0;
|
||||
let si_name = vm.perm_intern("name");
|
||||
let name_val = match vm.ordinary_get(src, si_name, src_val) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
@@ -546,13 +545,13 @@ fn alloc_error_clone<H: VmHost>(vm: &mut H, src: &JsObject) -> Result<*mut JsObj
|
||||
};
|
||||
// 归一化:七标准名取对应标准原型,其余(非字符串或自定义名)取 %Error.prototype%。
|
||||
let proto = match vm.lookup_str(name_val).as_deref() {
|
||||
Some("EvalError") => P::as_ptr(&vm.session().builtin_world().eval_error_proto) as *mut JsObject,
|
||||
Some("RangeError") => P::as_ptr(&vm.session().builtin_world().range_error_proto) as *mut JsObject,
|
||||
Some("ReferenceError") => P::as_ptr(&vm.session().builtin_world().reference_error_proto) as *mut JsObject,
|
||||
Some("SyntaxError") => P::as_ptr(&vm.session().builtin_world().syntax_error_proto) as *mut JsObject,
|
||||
Some("TypeError") => P::as_ptr(&vm.session().builtin_world().type_error_proto) as *mut JsObject,
|
||||
Some("URIError") => P::as_ptr(&vm.session().builtin_world().uri_error_proto) as *mut JsObject,
|
||||
_ => P::as_ptr(&vm.session().builtin_world().error_proto) as *mut JsObject,
|
||||
Some("EvalError") => vm.builtin_proto(ProtoKind::EvalErrorProto),
|
||||
Some("RangeError") => vm.builtin_proto(ProtoKind::RangeErrorProto),
|
||||
Some("ReferenceError") => vm.builtin_proto(ProtoKind::ReferenceErrorProto),
|
||||
Some("SyntaxError") => vm.builtin_proto(ProtoKind::SyntaxErrorProto),
|
||||
Some("TypeError") => vm.builtin_proto(ProtoKind::TypeErrorProto),
|
||||
Some("URIError") => vm.builtin_proto(ProtoKind::UriErrorProto),
|
||||
_ => vm.builtin_proto(ProtoKind::ErrorProto),
|
||||
};
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto));
|
||||
obj.type_tag = JsObject::OBJ_TYPE_ERROR;
|
||||
@@ -659,7 +658,7 @@ fn alloc_data_view_clone<H: VmHost>(
|
||||
// SAFETY: data_ptr 经对象类型标签校验为存活状态盒;Copy 语义,不跨 JS 调用持借用。
|
||||
let data = unsafe { *data_ptr };
|
||||
let cloned_buffer = clone_value(vm, state, data.buffer)?;
|
||||
let proto = JsValue::from_js_object(vm.session().builtin_world().data_view_proto.as_ptr() as *mut JsObject);
|
||||
let proto = JsValue::from_js_object(vm.builtin_proto(ProtoKind::DataViewProto));
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, proto);
|
||||
obj.type_tag = JsObject::OBJ_TYPE_DATA_VIEW;
|
||||
let new_data = Box::into_raw(Box::new(crate::data_view::DataViewData {
|
||||
@@ -701,7 +700,7 @@ fn is_boxed_cloneable(src: &JsObject) -> bool {
|
||||
/// 供同 crate 的跨 realm 值传递抽象(`message_value`)复用。
|
||||
pub(crate) fn data_clone_error<H: VmHost>(vm: &mut H, msg: &str) -> JsValue {
|
||||
let err = crate::error::create_kind_error(vm, "DataCloneError", msg);
|
||||
let si_name = vm.kernel_core().perm_interner().intern("name").0;
|
||||
let si_name = vm.perm_intern("name");
|
||||
let name_val = vm.new_string("DataCloneError");
|
||||
// 新建错误对象形状为空,define 恒成功;失败忽略(不影响异常值身份)。
|
||||
let _ = vm.define_data_property(
|
||||
@@ -745,7 +744,7 @@ mod tests {
|
||||
|
||||
/// 读对象自身属性值(按名称),无则 undefined。
|
||||
fn obj_prop(vm: &Vm, obj: &JsObject, name: &str) -> JsValue {
|
||||
let si = vm.kernel_core().perm_interner().intern(name).0;
|
||||
let si = vm.perm_intern(name);
|
||||
match vm.get_own_property_slot(obj, si) {
|
||||
Some(idx) => obj.get_prop_at(idx),
|
||||
None => JsValue::undefined(),
|
||||
@@ -860,8 +859,8 @@ mod tests {
|
||||
let (mut vm, v) = eval("var a = {x: 1}; var b = {ref: a, ref2: a}; b").unwrap();
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
let si_ref = vm.kernel_core().perm_interner().intern("ref").0;
|
||||
let si_ref2 = vm.kernel_core().perm_interner().intern("ref2").0;
|
||||
let si_ref = vm.perm_intern("ref");
|
||||
let si_ref2 = vm.perm_intern("ref2");
|
||||
let ref1 = cl.get_prop_at(vm.get_own_property_slot(cl, si_ref).unwrap());
|
||||
let ref2 = cl.get_prop_at(vm.get_own_property_slot(cl, si_ref2).unwrap());
|
||||
assert!(ref1.is_object() && ref2.is_object());
|
||||
@@ -873,7 +872,7 @@ mod tests {
|
||||
let (mut vm, v) = eval("var a = {}; a.self = a; a").unwrap();
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
let si_self = vm.kernel_core().perm_interner().intern("self").0;
|
||||
let si_self = vm.perm_intern("self");
|
||||
let self_ref = cl.get_prop_at(vm.get_own_property_slot(cl, si_self).unwrap());
|
||||
assert!(std::ptr::eq(self_ref.as_js_object_ptr(), c.as_js_object_ptr()), "循环引用应指向克隆自身");
|
||||
}
|
||||
@@ -935,8 +934,8 @@ mod tests {
|
||||
eval("var ab = new Uint8Array([9, 8, 7]).buffer; var opts = {transfer: [ab]}; ({ab: ab, opts: opts})")
|
||||
.unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_ab = vm.kernel_core().perm_interner().intern("ab").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_ab = vm.perm_intern("ab");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let ab = holder.get_prop_at(vm.get_own_property_slot(holder, si_ab).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let c = clone_with_options(&mut vm, ab, opts).unwrap();
|
||||
@@ -971,8 +970,8 @@ mod tests {
|
||||
eval("var ta = new Uint8Array([1, 2, 3]); var opts = {transfer: [ta.buffer]}; ({ta: ta, opts: opts})")
|
||||
.unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_ta = vm.kernel_core().perm_interner().intern("ta").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_ta = vm.perm_intern("ta");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let ta = holder.get_prop_at(vm.get_own_property_slot(holder, si_ta).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let c = clone_with_options(&mut vm, ta, opts).unwrap();
|
||||
@@ -1026,8 +1025,8 @@ mod tests {
|
||||
let (mut vm, v) =
|
||||
eval("var sab = new SharedArrayBuffer(4); var opts = {transfer: [sab]}; ({v: sab, opts: opts})").unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_v = vm.kernel_core().perm_interner().intern("v").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_v = vm.perm_intern("v");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let val = holder.get_prop_at(vm.get_own_property_slot(holder, si_v).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let e = clone_with_options(&mut vm, val, opts).unwrap_err();
|
||||
@@ -1040,8 +1039,8 @@ mod tests {
|
||||
let (mut vm, v) =
|
||||
eval("var ab = new ArrayBuffer(4); var opts = {transfer: [ab, ab]}; ({v: ab, opts: opts})").unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_v = vm.kernel_core().perm_interner().intern("v").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_v = vm.perm_intern("v");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let val = holder.get_prop_at(vm.get_own_property_slot(holder, si_v).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let e = clone_with_options(&mut vm, val, opts).unwrap_err();
|
||||
@@ -1075,8 +1074,8 @@ mod tests {
|
||||
// 字符串经 ToList 逐字符迭代,'x' 非 ArrayBuffer → DataCloneError。
|
||||
let (mut vm, v) = eval("var opts = {transfer: 'x'}; ({v: 1, opts: opts})").unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_v = vm.kernel_core().perm_interner().intern("v").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_v = vm.perm_intern("v");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let val = holder.get_prop_at(vm.get_own_property_slot(holder, si_v).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let e = clone_with_options(&mut vm, val, opts).unwrap_err();
|
||||
@@ -1090,8 +1089,8 @@ mod tests {
|
||||
// 不可迭代对象经 GetIterator 抛 TypeError。
|
||||
let (mut vm, v) = eval("var opts = {transfer: {}}; ({v: 1, opts: opts})").unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_v = vm.kernel_core().perm_interner().intern("v").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_v = vm.perm_intern("v");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let val = holder.get_prop_at(vm.get_own_property_slot(holder, si_v).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let e = clone_with_options(&mut vm, val, opts).unwrap_err();
|
||||
@@ -1110,8 +1109,8 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_ab = vm.kernel_core().perm_interner().intern("ab").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_ab = vm.perm_intern("ab");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let ab = holder.get_prop_at(vm.get_own_property_slot(holder, si_ab).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let c = clone_with_options(&mut vm, ab, opts).unwrap();
|
||||
@@ -1197,7 +1196,7 @@ mod tests {
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
// 克隆是 plain 对象:原型链丢弃,回落 Object 原型,自有属性带过。
|
||||
assert_eq!(cl.type_tag, JsObject::OBJ_TYPE_PLAIN);
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *const u8;
|
||||
let object_proto = vm.builtin_proto(ProtoKind::ObjectProto) as *const u8;
|
||||
assert!(std::ptr::eq(cl.proto().as_ptr(), object_proto));
|
||||
assert_eq!(obj_prop(&vm, cl, "x"), JsValue::int(1));
|
||||
}
|
||||
@@ -1231,7 +1230,7 @@ mod tests {
|
||||
let (mut vm, v) = eval("var o = {a: 1}; Object.freeze(o); o").unwrap();
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
let si = vm.kernel_core().perm_interner().intern("a").0;
|
||||
let si = vm.perm_intern("a");
|
||||
let store = vm.get_own_property_slot(cl, si).unwrap();
|
||||
let meta = cl.prop_meta_at(store).unwrap();
|
||||
assert_eq!(meta.attributes, PropAttributes::DEFAULT_DATA, "克隆侧描述符应 w/e/c 全真");
|
||||
@@ -1245,7 +1244,7 @@ mod tests {
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
assert_eq!(obj_prop(&vm, cl, "a"), JsValue::int(1));
|
||||
let si_b = vm.kernel_core().perm_interner().intern("b").0;
|
||||
let si_b = vm.perm_intern("b");
|
||||
assert!(vm.get_own_property_slot(cl, si_b).is_none(), "不可枚举自有属性不应复制");
|
||||
}
|
||||
|
||||
@@ -1265,7 +1264,7 @@ mod tests {
|
||||
let (mut vm, v) = eval("var e = new Error('boom'); e.cause = {x: 1}; e").unwrap();
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
let si_cause = vm.kernel_core().perm_interner().intern("cause").0;
|
||||
let si_cause = vm.perm_intern("cause");
|
||||
let store = vm.get_own_property_slot(cl, si_cause).unwrap();
|
||||
let meta = cl.prop_meta_at(store).unwrap();
|
||||
assert_eq!(meta.attributes, PropAttributes::DEFAULT_DATA, "克隆侧 cause 应全真数据属性");
|
||||
@@ -1279,7 +1278,7 @@ mod tests {
|
||||
// 引擎给 Error 子类实例打 Error 家族标签,克隆走 Error 臂;name 归一
|
||||
// "Error",原型回落 %Error.prototype%(源子类原型丢弃),message 带过。
|
||||
assert!(cl.is_error_obj());
|
||||
let error_proto = vm.session().builtin_world().error_proto.as_ptr() as *const u8;
|
||||
let error_proto = vm.builtin_proto(ProtoKind::ErrorProto) as *const u8;
|
||||
assert!(std::ptr::eq(cl.proto().as_ptr(), error_proto), "克隆原型应回落 %Error.prototype%");
|
||||
assert_eq!(vm.lookup_str(obj_prop(&vm, cl, "message")).unwrap(), "msg");
|
||||
}
|
||||
@@ -1290,7 +1289,7 @@ mod tests {
|
||||
let (mut vm, v) = eval("var e = new TypeError('boom'); e").unwrap();
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
let type_proto = vm.session().builtin_world().type_error_proto.as_ptr() as *const u8;
|
||||
let type_proto = vm.builtin_proto(ProtoKind::TypeErrorProto) as *const u8;
|
||||
assert!(std::ptr::eq(cl.proto().as_ptr(), type_proto), "克隆原型应为 %TypeError.prototype%");
|
||||
assert_eq!(vm.lookup_str(obj_prop(&vm, cl, "message")).unwrap(), "boom");
|
||||
}
|
||||
@@ -1318,8 +1317,8 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_ab = vm.kernel_core().perm_interner().intern("ab").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_ab = vm.perm_intern("ab");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let ab = holder.get_prop_at(vm.get_own_property_slot(holder, si_ab).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
// 克隆持有者对象(含函数值,不可克隆)→ DataCloneError。
|
||||
@@ -1338,9 +1337,9 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_v = vm.kernel_core().perm_interner().intern("v").0;
|
||||
let si_ab = vm.kernel_core().perm_interner().intern("ab").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_v = vm.perm_intern("v");
|
||||
let si_ab = vm.perm_intern("ab");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let val = holder.get_prop_at(vm.get_own_property_slot(holder, si_v).unwrap());
|
||||
let ab = holder.get_prop_at(vm.get_own_property_slot(holder, si_ab).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
@@ -1366,8 +1365,8 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_v = vm.kernel_core().perm_interner().intern("v").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_v = vm.perm_intern("v");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let val = holder.get_prop_at(vm.get_own_property_slot(holder, si_v).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let e = clone_with_options(&mut vm, val, opts).unwrap_err();
|
||||
@@ -1387,7 +1386,7 @@ mod tests {
|
||||
let key = &entries[0].0;
|
||||
assert!(key.0.is_object());
|
||||
let key_obj = unsafe { &*key.0.as_js_object_ptr() };
|
||||
let si_m = vm.kernel_core().perm_interner().intern("m").0;
|
||||
let si_m = vm.perm_intern("m");
|
||||
let key_m = key_obj.get_prop_at(vm.get_own_property_slot(key_obj, si_m).unwrap());
|
||||
assert!(std::ptr::eq(key_m.as_js_object_ptr(), c.as_js_object_ptr()), "克隆键应引用克隆的 map");
|
||||
}
|
||||
@@ -1408,10 +1407,10 @@ mod tests {
|
||||
let (mut vm, v) = eval("var a = {}; var b = {}; a.b = b; b.a = a; a").unwrap();
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
let si_b = vm.kernel_core().perm_interner().intern("b").0;
|
||||
let si_b = vm.perm_intern("b");
|
||||
let b_clone = cl.get_prop_at(vm.get_own_property_slot(cl, si_b).unwrap());
|
||||
let b_obj = unsafe { &*b_clone.as_js_object_ptr() };
|
||||
let si_a = vm.kernel_core().perm_interner().intern("a").0;
|
||||
let si_a = vm.perm_intern("a");
|
||||
let a_back = b_obj.get_prop_at(vm.get_own_property_slot(b_obj, si_a).unwrap());
|
||||
assert!(std::ptr::eq(a_back.as_js_object_ptr(), c.as_js_object_ptr()), "深循环应指回克隆的 a");
|
||||
}
|
||||
@@ -1421,9 +1420,9 @@ mod tests {
|
||||
let (mut vm, v) = eval("var a = {x: 1}; var b = {ref: a, ref2: a}; b.self = b; b").unwrap();
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
let si_ref = vm.kernel_core().perm_interner().intern("ref").0;
|
||||
let si_ref2 = vm.kernel_core().perm_interner().intern("ref2").0;
|
||||
let si_self = vm.kernel_core().perm_interner().intern("self").0;
|
||||
let si_ref = vm.perm_intern("ref");
|
||||
let si_ref2 = vm.perm_intern("ref2");
|
||||
let si_self = vm.perm_intern("self");
|
||||
let ref1 = cl.get_prop_at(vm.get_own_property_slot(cl, si_ref).unwrap());
|
||||
let ref2 = cl.get_prop_at(vm.get_own_property_slot(cl, si_ref2).unwrap());
|
||||
let self_ref = cl.get_prop_at(vm.get_own_property_slot(cl, si_self).unwrap());
|
||||
@@ -1439,8 +1438,8 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_ab = vm.kernel_core().perm_interner().intern("ab").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_ab = vm.perm_intern("ab");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let ab = holder.get_prop_at(vm.get_own_property_slot(holder, si_ab).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let c = clone_with_options(&mut vm, ab, opts).unwrap();
|
||||
@@ -1460,8 +1459,8 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_ab = vm.kernel_core().perm_interner().intern("ab").0;
|
||||
let si_opts = vm.kernel_core().perm_interner().intern("opts").0;
|
||||
let si_ab = vm.perm_intern("ab");
|
||||
let si_opts = vm.perm_intern("opts");
|
||||
let ab = holder.get_prop_at(vm.get_own_property_slot(holder, si_ab).unwrap());
|
||||
let opts = holder.get_prop_at(vm.get_own_property_slot(holder, si_opts).unwrap());
|
||||
let c = clone_with_options(&mut vm, ab, opts).unwrap();
|
||||
@@ -1493,7 +1492,7 @@ mod tests {
|
||||
.unwrap();
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
let si_msg = vm.kernel_core().perm_interner().intern("message").0;
|
||||
let si_msg = vm.perm_intern("message");
|
||||
assert!(vm.get_own_property_slot(cl, si_msg).is_none(), "访问器 message 不应复制");
|
||||
}
|
||||
|
||||
@@ -1512,7 +1511,7 @@ mod tests {
|
||||
let (mut vm, v) = eval("var e = new Error('base'); delete e.message; e").unwrap();
|
||||
let c = clone(&mut vm, v).unwrap();
|
||||
let cl = unsafe { &*c.as_js_object_ptr() };
|
||||
let si_msg = vm.kernel_core().perm_interner().intern("message").0;
|
||||
let si_msg = vm.perm_intern("message");
|
||||
assert!(vm.get_own_property_slot(cl, si_msg).is_none());
|
||||
}
|
||||
|
||||
@@ -1532,8 +1531,8 @@ mod tests {
|
||||
// 全局绑定面:length 为 1、name 为 "structuredClone"(防绑定面回归)。
|
||||
let (vm, v) = eval("({len: structuredClone.length, name: structuredClone.name})").unwrap();
|
||||
let holder = unsafe { &*v.as_js_object_ptr() };
|
||||
let si_len = vm.kernel_core().perm_interner().intern("len").0;
|
||||
let si_name = vm.kernel_core().perm_interner().intern("name").0;
|
||||
let si_len = vm.perm_intern("len");
|
||||
let si_name = vm.perm_intern("name");
|
||||
let len = holder.get_prop_at(vm.get_own_property_slot(holder, si_len).unwrap());
|
||||
let name = holder.get_prop_at(vm.get_own_property_slot(holder, si_name).unwrap());
|
||||
assert_eq!(len, JsValue::int(1));
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::array_buffer::{
|
||||
buffer_payload, buffer_payload_ptr, default_array_buffer_proto, new_array_buffer, MAX_ARRAY_BUFFER_LENGTH,
|
||||
};
|
||||
|
||||
use oxide_runtime_api::{NativeResult, VmHost};
|
||||
use oxide_runtime_api::{NativeResult, ProtoKind, VmHost};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct TypedArrayData {
|
||||
@@ -58,23 +58,20 @@ fn to_index<H: VmHost>(vm: &mut H, value: JsValue, msg: &str) -> Result<usize, J
|
||||
}
|
||||
|
||||
pub(crate) fn typed_array_proto_ptr<H: VmHost>(vm: &mut H, kind: TypedArrayKind) -> *mut JsObject {
|
||||
{
|
||||
let session = vm.session();
|
||||
let world = session.builtin_world();
|
||||
match kind {
|
||||
TypedArrayKind::Int8 => world.int8array_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::Uint8 => world.uint8array_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::Uint8Clamped => world.uint8clampedarray_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::Int16 => world.int16array_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::Uint16 => world.uint16array_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::Int32 => world.int32array_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::Uint32 => world.uint32array_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::Float32 => world.float32array_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::Float64 => world.float64array_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::BigInt64 => world.bigint64array_proto.as_ptr() as *mut JsObject,
|
||||
TypedArrayKind::BigUint64 => world.biguint64array_proto.as_ptr() as *mut JsObject,
|
||||
}
|
||||
}
|
||||
let kind = match kind {
|
||||
TypedArrayKind::Int8 => ProtoKind::Int8ArrayProto,
|
||||
TypedArrayKind::Uint8 => ProtoKind::Uint8ArrayProto,
|
||||
TypedArrayKind::Uint8Clamped => ProtoKind::Uint8ClampedArrayProto,
|
||||
TypedArrayKind::Int16 => ProtoKind::Int16ArrayProto,
|
||||
TypedArrayKind::Uint16 => ProtoKind::Uint16ArrayProto,
|
||||
TypedArrayKind::Int32 => ProtoKind::Int32ArrayProto,
|
||||
TypedArrayKind::Uint32 => ProtoKind::Uint32ArrayProto,
|
||||
TypedArrayKind::Float32 => ProtoKind::Float32ArrayProto,
|
||||
TypedArrayKind::Float64 => ProtoKind::Float64ArrayProto,
|
||||
TypedArrayKind::BigInt64 => ProtoKind::BigInt64ArrayProto,
|
||||
TypedArrayKind::BigUint64 => ProtoKind::BigUint64ArrayProto,
|
||||
};
|
||||
vm.builtin_proto(kind)
|
||||
}
|
||||
|
||||
/// 取指定类型的内建构造器值(`[[TypedArrayName]]` → world 槽),species 默认臂
|
||||
@@ -95,7 +92,7 @@ fn ta_gpf_proto<H: VmHost>(vm: &mut H, kind: TypedArrayKind) -> Result<JsValue,
|
||||
let nt_ptr = new_target.as_js_object_ptr();
|
||||
// SAFETY: is_object 保证指针非空且对象本 session 存活。
|
||||
let nt_obj = unsafe { &*nt_ptr };
|
||||
let proto_si = vm.kernel_core().perm_interner().intern("prototype").0;
|
||||
let proto_si = vm.perm_intern("prototype");
|
||||
match vm.ordinary_get(nt_obj, proto_si, new_target) {
|
||||
Ok(v) => Ok(if v.is_object() { v } else { default_proto }),
|
||||
Err(err) => Err(crate::iterator::engine_error(vm, &err)),
|
||||
@@ -103,24 +100,20 @@ fn ta_gpf_proto<H: VmHost>(vm: &mut H, kind: TypedArrayKind) -> Result<JsValue,
|
||||
}
|
||||
|
||||
fn typed_array_ctor_value<H: VmHost>(vm: &mut H, kind: TypedArrayKind) -> JsValue {
|
||||
let ctor = {
|
||||
let session = vm.session();
|
||||
let world = session.builtin_world();
|
||||
match kind {
|
||||
TypedArrayKind::Int8 => world.int8array_constructor.clone(),
|
||||
TypedArrayKind::Uint8 => world.uint8array_constructor.clone(),
|
||||
TypedArrayKind::Uint8Clamped => world.uint8clampedarray_constructor.clone(),
|
||||
TypedArrayKind::Int16 => world.int16array_constructor.clone(),
|
||||
TypedArrayKind::Uint16 => world.uint16array_constructor.clone(),
|
||||
TypedArrayKind::Int32 => world.int32array_constructor.clone(),
|
||||
TypedArrayKind::Uint32 => world.uint32array_constructor.clone(),
|
||||
TypedArrayKind::Float32 => world.float32array_constructor.clone(),
|
||||
TypedArrayKind::Float64 => world.float64array_constructor.clone(),
|
||||
TypedArrayKind::BigInt64 => world.bigint64array_constructor.clone(),
|
||||
TypedArrayKind::BigUint64 => world.biguint64array_constructor.clone(),
|
||||
}
|
||||
let kind = match kind {
|
||||
TypedArrayKind::Int8 => ProtoKind::Int8ArrayConstructor,
|
||||
TypedArrayKind::Uint8 => ProtoKind::Uint8ArrayConstructor,
|
||||
TypedArrayKind::Uint8Clamped => ProtoKind::Uint8ClampedArrayConstructor,
|
||||
TypedArrayKind::Int16 => ProtoKind::Int16ArrayConstructor,
|
||||
TypedArrayKind::Uint16 => ProtoKind::Uint16ArrayConstructor,
|
||||
TypedArrayKind::Int32 => ProtoKind::Int32ArrayConstructor,
|
||||
TypedArrayKind::Uint32 => ProtoKind::Uint32ArrayConstructor,
|
||||
TypedArrayKind::Float32 => ProtoKind::Float32ArrayConstructor,
|
||||
TypedArrayKind::Float64 => ProtoKind::Float64ArrayConstructor,
|
||||
TypedArrayKind::BigInt64 => ProtoKind::BigInt64ArrayConstructor,
|
||||
TypedArrayKind::BigUint64 => ProtoKind::BigUint64ArrayConstructor,
|
||||
};
|
||||
JsValue::from_js_object(ctor.as_ptr() as *mut JsObject)
|
||||
JsValue::from_js_object(vm.builtin_proto(kind))
|
||||
}
|
||||
|
||||
/// 把 TypedArray 实例数据(类型标签 + 视图内部槽)写入指定对象;构造调用与
|
||||
@@ -402,7 +395,7 @@ pub fn ta_index_gate<H: VmHost>(vm: &H, obj: &JsObject, key_si: u32) -> TaIndexG
|
||||
if is_int_key(key_si) {
|
||||
return ta_index_gate_int(int_key_value(key_si), length);
|
||||
}
|
||||
let Some(key) = vm.kernel_core().perm_interner().lookup(key_si) else {
|
||||
let Some(key) = vm.perm_lookup(key_si) else {
|
||||
return TaIndexGate::Ordinary;
|
||||
};
|
||||
ta_index_gate_from_text(key, length)
|
||||
@@ -699,8 +692,8 @@ pub fn element_error_text<H: VmHost>(vm: &mut H, err: JsValue) -> String {
|
||||
}
|
||||
if err.is_object() {
|
||||
let obj = unsafe { &*err.as_js_object_ptr() };
|
||||
let name_si = vm.kernel_core().perm_interner().intern("name").0;
|
||||
let message_si = vm.kernel_core().perm_interner().intern("message").0;
|
||||
let name_si = vm.perm_intern("name");
|
||||
let message_si = vm.perm_intern("message");
|
||||
let name = vm
|
||||
.resolve_property(obj, name_si)
|
||||
.and_then(|v| vm.lookup_str(v))
|
||||
@@ -825,7 +818,7 @@ fn collect_array_like<H: VmHost>(
|
||||
return Ok(values);
|
||||
}
|
||||
|
||||
let length_si = vm.kernel_core().perm_interner().intern("length").0;
|
||||
let length_si = vm.perm_intern("length");
|
||||
let len_val = vm
|
||||
.ordinary_get(obj, length_si, value)
|
||||
.map_err(|e| crate::iterator::engine_error(vm, &e))?;
|
||||
@@ -1141,7 +1134,7 @@ fn typed_array_species_create<H: VmHost>(
|
||||
) -> Result<JsValue, JsValue> {
|
||||
let o_ptr = o_val.as_js_object_ptr();
|
||||
let o_obj = unsafe { &*o_ptr };
|
||||
let ctor_key = vm.kernel_core().perm_interner().intern("constructor").0;
|
||||
let ctor_key = vm.perm_intern("constructor");
|
||||
let c = match vm.ordinary_get(o_obj, ctor_key, o_val) {
|
||||
Ok(v) => v,
|
||||
Err(msg) => return Err(crate::iterator::engine_error(vm, &msg)),
|
||||
@@ -1371,7 +1364,7 @@ enum SetSourceKind {
|
||||
|
||||
/// array-like 源的 `length` 属性读 + ToLength 收敛(NaN/负取 0,上限 2^53-1)。
|
||||
fn set_array_like_length<H: VmHost>(vm: &mut H, source: JsValue) -> Result<usize, JsValue> {
|
||||
let si = vm.kernel_core().perm_interner().intern("length").0;
|
||||
let si = vm.perm_intern("length");
|
||||
let ptr = source.as_js_object_ptr();
|
||||
let len_val = unsafe { vm.ordinary_get(&*ptr, si, source) }.map_err(|e| crate::iterator::engine_error(vm, &e))?;
|
||||
let n = oxide_runtime_api::to_number_full(len_val, vm).map_err(|e| crate::iterator::engine_error(vm, &e))?;
|
||||
@@ -2229,7 +2222,7 @@ pub fn typed_array_copy_within<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResu
|
||||
fn invoke_element_to_locale_string<H: VmHost>(vm: &mut H, element: JsValue) -> Result<JsValue, JsValue> {
|
||||
let obj_val = oxide_runtime_api::to_object(element, vm).map_err(|e| crate::iterator::engine_error(vm, &e))?;
|
||||
let obj = unsafe { &*obj_val.as_js_object_ptr() };
|
||||
let method_si = vm.kernel_core().perm_interner().intern("toLocaleString").0;
|
||||
let method_si = vm.perm_intern("toLocaleString");
|
||||
let method = vm
|
||||
.ordinary_get(obj, method_si, element)
|
||||
.map_err(|e| crate::iterator::engine_error(vm, &e))?;
|
||||
@@ -2446,7 +2439,7 @@ pub fn typed_array_from<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
Err(err) => return NativeResult::Err(crate::error::create_type_error(vm, &err)),
|
||||
};
|
||||
let obj = unsafe { &*obj_val.as_js_object_ptr() };
|
||||
let length_si = vm.kernel_core().perm_interner().intern("length").0;
|
||||
let length_si = vm.perm_intern("length");
|
||||
let len_val = match vm.ordinary_get(obj, length_si, obj_val) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return NativeResult::Err(crate::iterator::engine_error(vm, &e)),
|
||||
@@ -2604,10 +2597,10 @@ fn ta_decode_base64<H: VmHost>(
|
||||
|
||||
/// setFrom* 结果对象 `{ read, written }`:普通对象 + 两数据属性。
|
||||
fn ta_read_written_result<H: VmHost>(vm: &mut H, read: usize, written: usize) -> JsValue {
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let object_proto = vm.builtin_proto(ProtoKind::ObjectProto);
|
||||
let obj = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto)));
|
||||
let read_si = vm.kernel_core().perm_interner().intern("read").0;
|
||||
let written_si = vm.kernel_core().perm_interner().intern("written").0;
|
||||
let read_si = vm.perm_intern("read");
|
||||
let written_si = vm.perm_intern("written");
|
||||
let obj_ref = unsafe { &mut *obj };
|
||||
vm.set_or_create_prop_value(obj_ref, read_si, JsValue::int(read as i32));
|
||||
vm.set_or_create_prop_value(obj_ref, written_si, JsValue::int(written as i32));
|
||||
|
||||
Reference in New Issue
Block a user