mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: 原型面四方法补不变量并改四入口路由
This commit is contained in:
@@ -1579,7 +1579,7 @@ fn desc_field_bool<H: VmHost>(vm: &mut H, desc: JsValue, prop_si: u32) -> Result
|
||||
/// [[IsExtensible]](代理感知):代理经 isExtensible trap 路由(实参 target,
|
||||
/// 结果经 ToBoolean 投影,trap 报告须与 target 实际可扩展状态一致,不一致抛
|
||||
/// TypeError),trap 缺失落穿 target;普通对象读自身标志。
|
||||
fn proxy_is_extensible<H: VmHost>(vm: &mut H, obj: &JsObject) -> Result<bool, String> {
|
||||
pub fn proxy_is_extensible<H: VmHost>(vm: &mut H, obj: &JsObject) -> Result<bool, String> {
|
||||
if !obj.is_proxy_obj() {
|
||||
return Ok(obj.is_extensible());
|
||||
}
|
||||
@@ -1943,9 +1943,10 @@ fn seal_own_prop_meta(obj: &mut JsObject, store: u32) {
|
||||
}
|
||||
|
||||
/// 代理 [[PreventExtensions]](规范 ProxyPreventExtensions):preventExtensions
|
||||
/// trap 以(target)调用,结果经 ToBoolean 投影后须与 target 实际可扩展状态
|
||||
/// 一致(不一致抛 TypeError);trap 缺失落穿 target 的普通 preventExtensions
|
||||
/// (置不可扩展标志,返 true)。
|
||||
/// trap 以(target)调用,结果经 ToBoolean 投影;trap 报 true 而 target 可扩展
|
||||
/// 时抛 TypeError(报 false 无论 target 状态均原样返回);trap 缺失落穿
|
||||
/// target 的 [[PreventExtensions]](target 自身为代理时递归再路由,普通对象
|
||||
/// 置不可扩展标志)。
|
||||
pub fn proxy_prevent_extensions<H: VmHost>(vm: &mut H, obj: &JsObject) -> Result<bool, JsValue> {
|
||||
let target = crate::proxy::proxy_state_ref(obj).expect("状态盒").target;
|
||||
// SAFETY: target 由构造器校验为非空对象指针。
|
||||
@@ -1955,32 +1956,45 @@ pub fn proxy_prevent_extensions<H: VmHost>(vm: &mut H, obj: &JsObject) -> Result
|
||||
Err(msg) => return Err(own_keys_trap_exc(vm, msg)),
|
||||
};
|
||||
let Some(r) = trap_result else {
|
||||
// OrdinaryPreventExtensions(target):置不可扩展标志。
|
||||
// 落穿 target 的 [[PreventExtensions]]:target 自身为代理时递归再路由
|
||||
// (其 trap 与落穿语义对 target 生效);普通对象置不可扩展标志。
|
||||
if target_obj.is_proxy_obj() {
|
||||
return proxy_prevent_extensions(vm, target_obj);
|
||||
}
|
||||
// SAFETY: target 由构造器校验为非空对象指针。
|
||||
unsafe { &mut *target.as_js_object_ptr() }.set_extensible(false);
|
||||
return Ok(true);
|
||||
};
|
||||
let result = oxide_runtime_api::to_boolean(r);
|
||||
let target_extensible =
|
||||
proxy_is_extensible(vm, target_obj).map_err(|msg| crate::error::create_from_text(vm, &msg))?;
|
||||
if result != target_extensible {
|
||||
return Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Proxy preventExtensions trap result is inconsistent with target",
|
||||
));
|
||||
if result {
|
||||
let target_extensible =
|
||||
proxy_is_extensible(vm, target_obj).map_err(|msg| crate::error::create_from_text(vm, &msg))?;
|
||||
if target_extensible {
|
||||
return Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Proxy preventExtensions trap returned true for an extensible target",
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// 代理完整性级别(规范 SetIntegrityLevel):[[PreventExtensions]](代理感知)
|
||||
/// 后 [[OwnPropertyKeys]](代理感知),逐键 DefinePropertyOrThrow(经
|
||||
/// defineProperty trap 路由,trap 缺失落穿 target)。seal 仅置 configurable:
|
||||
/// false;freeze 对数据属性额外置 writable: false(规范步 7b 先读 currentDesc
|
||||
/// 区分数据/访问器,访问器不写 writable 字段)。
|
||||
/// 代理完整性级别(规范 SetIntegrityLevel):[[PreventExtensions]](代理感知,
|
||||
/// 报 false 时按规范抛 TypeError)后 [[OwnPropertyKeys]](代理感知),逐键
|
||||
/// DefinePropertyOrThrow(经 defineProperty trap 路由,trap 缺失落穿 target)。
|
||||
/// seal 仅置 configurable: false;freeze 对数据属性额外置 writable: false
|
||||
/// (规范步 7b 先读 currentDesc 区分数据/访问器,访问器不写 writable 字段)。
|
||||
fn proxy_set_integrity_level<H: VmHost>(vm: &mut H, obj_ptr: *mut JsObject, frozen: bool) -> Result<(), JsValue> {
|
||||
// SAFETY: obj_ptr 为存活对象指针。
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
proxy_prevent_extensions(vm, obj)?;
|
||||
// SetIntegrityLevel 步 3:[[PreventExtensions]] 报 false 时完整性级别
|
||||
// 返回 false,Object.freeze/seal 按规范抛 TypeError。
|
||||
if !proxy_prevent_extensions(vm, obj)? {
|
||||
return Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"SetIntegrityLevel: [[PreventExtensions]] returned false",
|
||||
));
|
||||
}
|
||||
let (keys, _storage) = own_keys_proxy_aware(vm, obj)?;
|
||||
let cfg_si = vm.perm_intern("configurable");
|
||||
let writable_si = vm.perm_intern("writable");
|
||||
@@ -2138,6 +2152,10 @@ pub fn object_seal<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
|
||||
/// `Object.preventExtensions(obj)`:禁止添加新属性,返回原对象。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 代理经 preventExtensions trap 路由(缺失落穿 target);`[[PreventExtensions]]`
|
||||
/// 报 false 时按规范抛 TypeError。
|
||||
pub fn object_prevent_extensions<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Object.preventExtensions called on non-object"));
|
||||
@@ -2147,10 +2165,16 @@ pub fn object_prevent_extensions<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeRe
|
||||
return NativeResult::Ok(val);
|
||||
}
|
||||
let obj_ptr = val.as_js_object_ptr();
|
||||
unsafe {
|
||||
(*obj_ptr).set_extensible(false);
|
||||
match vm.prevent_extensions(unsafe { &mut *obj_ptr }) {
|
||||
Ok(true) => NativeResult::Ok(val),
|
||||
// [[PreventExtensions]] 报 false:规范 20.1.2.20 步 3 抛 TypeError。
|
||||
Ok(false) => NativeResult::Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Object.preventExtensions: [[PreventExtensions]] returned false",
|
||||
)),
|
||||
// 代理 trap 异常原值传播(ReturnIfAbrupt)。
|
||||
Err(err) => NativeResult::Err(crate::array::from_engine_error(vm, &err)),
|
||||
}
|
||||
NativeResult::Ok(val)
|
||||
}
|
||||
|
||||
/// `Object.isFrozen(obj)`:对象是否冻结(检查 extensible 及全部属性 writable/configurable)。
|
||||
@@ -2236,6 +2260,10 @@ pub fn object_is_sealed<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
|
||||
/// `Object.isExtensible(obj)`:对象是否可扩展。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 代理经 isExtensible trap 路由(缺失落穿 target,报告与 target 状态
|
||||
/// 不一致抛 TypeError);普通对象读自身标志。
|
||||
pub fn object_is_extensible<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if args.len() < 2 {
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Object.isExtensible called on non-object"));
|
||||
@@ -2248,8 +2276,11 @@ pub fn object_is_extensible<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
|
||||
if obj_ptr.is_null() {
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
NativeResult::Ok(JsValue::bool(obj.is_extensible()))
|
||||
match vm.is_extensible(unsafe { &*obj_ptr }) {
|
||||
Ok(extensible) => NativeResult::Ok(JsValue::bool(extensible)),
|
||||
// 代理 trap 异常原值传播(ReturnIfAbrupt)。
|
||||
Err(err) => NativeResult::Err(crate::array::from_engine_error(vm, &err)),
|
||||
}
|
||||
}
|
||||
|
||||
/// `Object.getOwnPropertyNames(obj)`:返回全部自身属性名(含不可枚举)。
|
||||
|
||||
@@ -70,54 +70,17 @@ fn check_target_and_handler(target: JsValue, handler: JsValue) -> Result<(), &'s
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 不变量检查(规范 10.2.4 步骤 1、4-5):target 可调用时须可扩展,handler
|
||||
/// 的 isExtensible 与 setPrototypeOf trap 若存在,其布尔值须与 target 实际
|
||||
/// 状态一致,否则抛 TypeError。
|
||||
/// 不变量检查(规范 10.5.15 ProxyCreate 步 1-2):target 可调用且不可扩展时
|
||||
/// 抛 TypeError。构造器不读 handler 的 trap 属性(现代规范无构造期 trap 一致性
|
||||
/// 检查,不变量在内部方法调用期执行,getter 抛错不得在构造期触发)。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 仅当 handler 自有对应 trap 属性时检查(继承属性不触发)。
|
||||
/// - trap 读为传播读,getter 抛错原值上抛。
|
||||
fn proxy_create_invariants<H: VmHost>(
|
||||
vm: &mut H, target: JsValue, target_obj: &JsObject, handler_obj: &JsObject, handler: JsValue,
|
||||
) -> Result<(), JsValue> {
|
||||
/// - 仅当 target 可调用时检查可扩展性。
|
||||
fn proxy_create_invariants<H: VmHost>(vm: &mut H, target: JsValue, target_obj: &JsObject) -> Result<(), JsValue> {
|
||||
// target 可调用且不可扩展:函数代理的不变量无法满足,抛 TypeError。
|
||||
if crate::iterator::is_callable(target) && !target_obj.is_extensible() {
|
||||
return Err(crate::error::create_type_error(vm, "Proxy target must be extensible if it is callable"));
|
||||
}
|
||||
// isExtensible trap:handler 报 true 时 target 须可扩展,报 false 时须不可扩展。
|
||||
let si_is_extensible = vm.perm_intern("isExtensible");
|
||||
if vm.get_own_property_slot(handler_obj, si_is_extensible).is_some() {
|
||||
let trap_val = vm
|
||||
.ordinary_get(handler_obj, si_is_extensible, handler)
|
||||
.map_err(|e| crate::iterator::engine_error(vm, &e))?;
|
||||
let target_extensible = target_obj.is_extensible();
|
||||
let trap_is_true = trap_val.is_bool() && trap_val.as_bool();
|
||||
let trap_is_false = trap_val.is_bool() && !trap_val.as_bool();
|
||||
if (trap_is_true && !target_extensible) || (trap_is_false && target_extensible) {
|
||||
return Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Proxy invariant: isExtensible trap inconsistent with target",
|
||||
));
|
||||
}
|
||||
}
|
||||
// setPrototypeOf trap:handler 报 true 时 target 原型须为对象或 null,
|
||||
// 报 false 时须为其它类型。
|
||||
let si_set_proto = vm.perm_intern("setPrototypeOf");
|
||||
if vm.get_own_property_slot(handler_obj, si_set_proto).is_some() {
|
||||
let trap_val = vm
|
||||
.ordinary_get(handler_obj, si_set_proto, handler)
|
||||
.map_err(|e| crate::iterator::engine_error(vm, &e))?;
|
||||
let target_proto = target_obj.proto();
|
||||
let target_proto_is_obj_or_null = target_proto.is_object() || target_proto.is_null();
|
||||
let trap_is_true = trap_val.is_bool() && trap_val.as_bool();
|
||||
let trap_is_false = trap_val.is_bool() && !trap_val.as_bool();
|
||||
if (trap_is_true && !target_proto_is_obj_or_null) || (trap_is_false && target_proto_is_obj_or_null) {
|
||||
return Err(crate::error::create_type_error(
|
||||
vm,
|
||||
"Proxy invariant: setPrototypeOf trap inconsistent with target",
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -146,7 +109,7 @@ fn create_proxy_object<H: VmHost>(vm: &mut H, target: JsValue, handler: JsValue)
|
||||
/// # 步骤
|
||||
/// 1. NewTarget 校验:非构造形态调用抛 TypeError。
|
||||
/// 2. 参数校验:target 与 handler 均须对象。
|
||||
/// 3. 不变量检查:handler 的 isExtensible / setPrototypeOf trap 与 target 一致性。
|
||||
/// 3. 不变量检查:target 可调用时须可扩展(构造器不读 handler trap 属性)。
|
||||
/// 4. 创建代理对象(tag 39 + 状态盒 + Object.prototype 原型链)。
|
||||
///
|
||||
/// # 边界与前提
|
||||
@@ -164,8 +127,7 @@ pub fn proxy_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
// SAFETY: check_target_and_handler 已校验非空对象指针。
|
||||
let target_obj = unsafe { &*target.as_js_object_ptr() };
|
||||
let handler_obj = unsafe { &*handler.as_js_object_ptr() };
|
||||
if let Err(exc) = proxy_create_invariants(vm, target, target_obj, handler_obj, handler) {
|
||||
if let Err(exc) = proxy_create_invariants(vm, target, target_obj) {
|
||||
return NativeResult::Err(exc);
|
||||
}
|
||||
NativeResult::Ok(create_proxy_object(vm, target, handler))
|
||||
@@ -191,8 +153,7 @@ pub fn proxy_revocable<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
// SAFETY: check_target_and_handler 已校验非空对象指针。
|
||||
let target_obj = unsafe { &*target.as_js_object_ptr() };
|
||||
let handler_obj = unsafe { &*handler.as_js_object_ptr() };
|
||||
if let Err(exc) = proxy_create_invariants(vm, target, target_obj, handler_obj, handler) {
|
||||
if let Err(exc) = proxy_create_invariants(vm, target, target_obj) {
|
||||
return NativeResult::Err(exc);
|
||||
}
|
||||
let proxy_val = create_proxy_object(vm, target, handler);
|
||||
|
||||
@@ -233,12 +233,20 @@ pub fn reflect_has<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
}
|
||||
|
||||
/// `Reflect.isExtensible(target)`:对象是否可扩展。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 代理经 isExtensible trap 路由(缺失落穿 target,报告与 target 状态
|
||||
/// 不一致抛 TypeError);普通对象读自身标志。
|
||||
pub fn reflect_is_extensible<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.isExtensible target is not an object");
|
||||
};
|
||||
NativeResult::Ok(JsValue::bool(unsafe { &*target_ptr }.is_extensible()))
|
||||
match vm.is_extensible(unsafe { &*target_ptr }) {
|
||||
Ok(extensible) => NativeResult::Ok(JsValue::bool(extensible)),
|
||||
// 代理 trap 异常原值传播(ReturnIfAbrupt)。
|
||||
Err(msg) => NativeResult::Err(from_engine_error(vm, &msg)),
|
||||
}
|
||||
}
|
||||
|
||||
/// `Reflect.ownKeys(target)`:返回对象全部自身属性键,字符串键在前、Symbol 键在后。
|
||||
@@ -297,14 +305,22 @@ pub fn reflect_own_keys<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
NativeResult::Ok(JsValue::from_js_object(arr))
|
||||
}
|
||||
|
||||
/// `Reflect.preventExtensions(target)`:阻止扩展,返回 true。
|
||||
/// `Reflect.preventExtensions(target)`:阻止扩展,返回 `[[PreventExtensions]]`
|
||||
/// 的布尔结果。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 代理经 preventExtensions trap 路由(缺失落穿 target);结果按规范
|
||||
/// 原样返回(非恒 true)。
|
||||
pub fn reflect_prevent_extensions<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let target_val = arg(vm, args, 1);
|
||||
let Some(target_ptr) = object_ptr(target_val) else {
|
||||
return type_error(vm, "Reflect.preventExtensions target is not an object");
|
||||
};
|
||||
unsafe { &mut *target_ptr }.set_extensible(false);
|
||||
NativeResult::Ok(JsValue::bool(true))
|
||||
match vm.prevent_extensions(unsafe { &mut *target_ptr }) {
|
||||
Ok(status) => NativeResult::Ok(JsValue::bool(status)),
|
||||
// 代理 trap 异常原值传播(ReturnIfAbrupt)。
|
||||
Err(msg) => NativeResult::Err(from_engine_error(vm, &msg)),
|
||||
}
|
||||
}
|
||||
|
||||
/// `Reflect.set(target, key, value, receiver)`:按 OrdinarySetWithReceiver 语义写入属性。
|
||||
|
||||
Reference in New Issue
Block a user