mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
docs: 补齐 Promise 结算与构造的安全注记
This commit is contained in:
@@ -23,6 +23,8 @@ impl Vm {
|
|||||||
pub(super) fn create_promise_object(&mut self) -> JsValue {
|
pub(super) fn create_promise_object(&mut self) -> JsValue {
|
||||||
let proto_val = JsValue::from_js_object(self.promise_proto.as_ptr() as *mut JsObject);
|
let proto_val = JsValue::from_js_object(self.promise_proto.as_ptr() as *mut JsObject);
|
||||||
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
|
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
|
||||||
|
// SAFETY: `alloc_object` 返回非空 arena 指针;此处写 type_tag 与 native_data
|
||||||
|
// (Box<PromiseState> 由 Box::into_raw 分配,随对象释放),无别名。
|
||||||
let obj = unsafe { &mut *ptr };
|
let obj = unsafe { &mut *ptr };
|
||||||
obj.type_tag = JsObject::OBJ_TYPE_PROMISE;
|
obj.type_tag = JsObject::OBJ_TYPE_PROMISE;
|
||||||
let state = Box::new(PromiseState {
|
let state = Box::new(PromiseState {
|
||||||
@@ -45,6 +47,8 @@ impl Vm {
|
|||||||
if !is_constructor_value(ctor) {
|
if !is_constructor_value(ctor) {
|
||||||
return Err(oxide_builtins::error::create_type_error(self, "constructor is not a constructor"));
|
return Err(oxide_builtins::error::create_type_error(self, "constructor is not a constructor"));
|
||||||
}
|
}
|
||||||
|
// SAFETY: `is_constructor_value` 已含对象校验,指针非空且指向存活对象;
|
||||||
|
// 此处只读 native_fn() 判定分支,不跨 GC/reset。
|
||||||
let ctor_obj = unsafe { &*ctor.as_js_object_ptr() };
|
let ctor_obj = unsafe { &*ctor.as_js_object_ptr() };
|
||||||
// native 构造器:receiver 为新对象,值传递调用(%Promise% 主路径)。
|
// native 构造器:receiver 为新对象,值传递调用(%Promise% 主路径)。
|
||||||
if ctor_obj.native_fn().is_some() {
|
if ctor_obj.native_fn().is_some() {
|
||||||
@@ -206,14 +210,20 @@ impl Vm {
|
|||||||
// 固定地址后互相接线:proto.constructor ↔ ctor.prototype。
|
// 固定地址后互相接线:proto.constructor ↔ ctor.prototype。
|
||||||
Self::swap_intrinsic_proto(&mut self.promise_proto, *proto);
|
Self::swap_intrinsic_proto(&mut self.promise_proto, *proto);
|
||||||
Self::swap_intrinsic_proto(&mut self.promise_constructor, *ctor);
|
Self::swap_intrinsic_proto(&mut self.promise_constructor, *ctor);
|
||||||
|
// SAFETY: `promise_proto` 为 Box<JsObject>,固定堆址且本行前刚经
|
||||||
|
// swap_intrinsic_proto 落地;与下一处 ctor_mut 指向不同对象,无别名。
|
||||||
let proto_mut = unsafe { &mut *self.promise_proto.as_mut_ptr() };
|
let proto_mut = unsafe { &mut *self.promise_proto.as_mut_ptr() };
|
||||||
proto_mut.set_prop_at(0u32, JsValue::from_js_object(self.promise_constructor.as_ptr() as *mut JsObject));
|
proto_mut.set_prop_at(0u32, JsValue::from_js_object(self.promise_constructor.as_ptr() as *mut JsObject));
|
||||||
|
// SAFETY: `promise_constructor` 同为固定堆址的存活 Box;此处写 prototype
|
||||||
|
// 槽位(下标 2),与 proto_mut 分属不同对象,无别名。
|
||||||
let ctor_mut = unsafe { &mut *self.promise_constructor.as_mut_ptr() };
|
let ctor_mut = unsafe { &mut *self.promise_constructor.as_mut_ptr() };
|
||||||
// prototype 槽位在 length/name 之后(下标 2)。
|
// prototype 槽位在 length/name 之后(下标 2)。
|
||||||
ctor_mut.set_prop_at(2u32, JsValue::from_js_object(self.promise_proto.as_ptr() as *mut JsObject));
|
ctor_mut.set_prop_at(2u32, JsValue::from_js_object(self.promise_proto.as_ptr() as *mut JsObject));
|
||||||
|
|
||||||
// 绑定 global:槽已存在则更新(full_reset 未重建 global 时旧槽指向已弃 ctor)。
|
// 绑定 global:槽已存在则更新(full_reset 未重建 global 时旧槽指向已弃 ctor)。
|
||||||
let global_ptr = self.session.global_object().as_ptr() as *mut JsObject;
|
let global_ptr = self.session.global_object().as_ptr() as *mut JsObject;
|
||||||
|
// SAFETY: global 对象由 session 持有,存活整个 session;本函数内只改其
|
||||||
|
// shape/属性区,期间无 reset 或对象搬移。
|
||||||
let global = unsafe { &mut *global_ptr };
|
let global = unsafe { &mut *global_ptr };
|
||||||
let si = self.kernel_core.perm_interner().intern("Promise").0;
|
let si = self.kernel_core.perm_interner().intern("Promise").0;
|
||||||
let ctor_val = JsValue::from_js_object(self.promise_constructor.as_ptr() as *mut JsObject);
|
let ctor_val = JsValue::from_js_object(self.promise_constructor.as_ptr() as *mut JsObject);
|
||||||
@@ -240,6 +250,8 @@ fn promise_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
|||||||
if !vm.has_promise_proto(this_val) {
|
if !vm.has_promise_proto(this_val) {
|
||||||
return NativeResult::Err(oxide_builtins::error::create_type_error(vm, "Promise must be called with new"));
|
return NativeResult::Err(oxide_builtins::error::create_type_error(vm, "Promise must be called with new"));
|
||||||
}
|
}
|
||||||
|
// SAFETY: `has_promise_proto` 已校验 this 为存活对象且原型链含 %Promise.prototype%;
|
||||||
|
// 此处写 type_tag 后即新建状态盒,无别名。
|
||||||
let obj = unsafe { &mut *this_val.as_js_object_ptr() };
|
let obj = unsafe { &mut *this_val.as_js_object_ptr() };
|
||||||
obj.type_tag = JsObject::OBJ_TYPE_PROMISE;
|
obj.type_tag = JsObject::OBJ_TYPE_PROMISE;
|
||||||
let resolve = vm.make_resolve_reject_fn(this_val, false, false);
|
let resolve = vm.make_resolve_reject_fn(this_val, false, false);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ impl Vm {
|
|||||||
let resolve = self.make_resolve_reject_fn(promise, false, false);
|
let resolve = self.make_resolve_reject_fn(promise, false, false);
|
||||||
let reject = self.make_resolve_reject_fn(promise, true, false);
|
let reject = self.make_resolve_reject_fn(promise, true, false);
|
||||||
let state = self.promise_state_ptr(promise);
|
let state = self.promise_state_ptr(promise);
|
||||||
|
// SAFETY: `state` 来自 create_promise_object 写入的状态盒,非空且随对象存活;此处块内唯一可变借用,无别名。
|
||||||
let state = unsafe { &mut *state };
|
let state = unsafe { &mut *state };
|
||||||
state.resolve_fn = resolve;
|
state.resolve_fn = resolve;
|
||||||
state.reject_fn = reject;
|
state.reject_fn = reject;
|
||||||
@@ -50,6 +51,8 @@ impl Vm {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
let (resolve, reject) = {
|
let (resolve, reject) = {
|
||||||
|
// SAFETY: `executor` 由 make_capability_executor 新建,为存活的 arena 函数
|
||||||
|
// 对象、指针非空;此处只读 CAP_* 属性,不跨 GC/reset 点。
|
||||||
let exec_obj = unsafe { &*executor.as_js_object_ptr() };
|
let exec_obj = unsafe { &*executor.as_js_object_ptr() };
|
||||||
let res_si = self.kernel_core.perm_interner().intern(CAP_RESOLVE_PROP).0;
|
let res_si = self.kernel_core.perm_interner().intern(CAP_RESOLVE_PROP).0;
|
||||||
let rej_si = self.kernel_core.perm_interner().intern(CAP_REJECT_PROP).0;
|
let rej_si = self.kernel_core.perm_interner().intern(CAP_REJECT_PROP).0;
|
||||||
@@ -75,6 +78,7 @@ impl Vm {
|
|||||||
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(capability_executor as *const ()) }));
|
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(capability_executor as *const ()) }));
|
||||||
func.set_native_arg_count(2);
|
func.set_native_arg_count(2);
|
||||||
let ptr = self.alloc_object(func);
|
let ptr = self.alloc_object(func);
|
||||||
|
// SAFETY: `alloc_object` 返回非空 arena 指针,本次 native 调用内不搬移;借出期间无别名。
|
||||||
let obj = unsafe { &mut *ptr };
|
let obj = unsafe { &mut *ptr };
|
||||||
self.add_fn_name_length(obj, "", 2);
|
self.add_fn_name_length(obj, "", 2);
|
||||||
JsValue::from_js_object(ptr)
|
JsValue::from_js_object(ptr)
|
||||||
@@ -93,6 +97,7 @@ impl Vm {
|
|||||||
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(native_fn as *const ()) }));
|
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(native_fn as *const ()) }));
|
||||||
func.set_native_arg_count(1);
|
func.set_native_arg_count(1);
|
||||||
let ptr = self.alloc_object(func);
|
let ptr = self.alloc_object(func);
|
||||||
|
// SAFETY: `alloc_object` 返回非空 arena 指针;后续属性/shape 分配不改对象地址,无别名。
|
||||||
let obj = unsafe { &mut *ptr };
|
let obj = unsafe { &mut *ptr };
|
||||||
let si = self.kernel_core.perm_interner().intern(PROMISE_PROP).0;
|
let si = self.kernel_core.perm_interner().intern(PROMISE_PROP).0;
|
||||||
self.set_or_create_prop_value(obj, si, promise);
|
self.set_or_create_prop_value(obj, si, promise);
|
||||||
@@ -108,6 +113,7 @@ impl Vm {
|
|||||||
if !callee.is_object() {
|
if !callee.is_object() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
// SAFETY: `is_object` 已保证指针非空且指向存活对象;只读 PROMISE_PROP,不跨 GC/reset。
|
||||||
let obj = unsafe { &*callee.as_js_object_ptr() };
|
let obj = unsafe { &*callee.as_js_object_ptr() };
|
||||||
let si = self.kernel_core.perm_interner().intern(PROMISE_PROP).0;
|
let si = self.kernel_core.perm_interner().intern(PROMISE_PROP).0;
|
||||||
match self.resolve_property(obj, si) {
|
match self.resolve_property(obj, si) {
|
||||||
@@ -122,6 +128,7 @@ impl Vm {
|
|||||||
if !callee.is_object() {
|
if !callee.is_object() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// SAFETY: `is_object` 已保证指针非空且指向存活对象;只读 DELEGATED_PROP,不跨 GC/reset。
|
||||||
let obj = unsafe { &*callee.as_js_object_ptr() };
|
let obj = unsafe { &*callee.as_js_object_ptr() };
|
||||||
let si = self.kernel_core.perm_interner().intern(DELEGATED_PROP).0;
|
let si = self.kernel_core.perm_interner().intern(DELEGATED_PROP).0;
|
||||||
self.resolve_property(obj, si)
|
self.resolve_property(obj, si)
|
||||||
@@ -131,6 +138,8 @@ impl Vm {
|
|||||||
|
|
||||||
/// 取出 Promise 状态盒指针(调用方须先校验 `is_promise_value`)。
|
/// 取出 Promise 状态盒指针(调用方须先校验 `is_promise_value`)。
|
||||||
pub(super) fn promise_state_ptr(&self, promise: JsValue) -> *mut PromiseState {
|
pub(super) fn promise_state_ptr(&self, promise: JsValue) -> *mut PromiseState {
|
||||||
|
// SAFETY: 调用方已按文档前提校验 `is_promise_value`,对象指针非空且 native_data
|
||||||
|
// 为 create_promise_object 写入的 Box<PromiseState>;裸指针由调用方即时解引用。
|
||||||
unsafe { (*promise.as_js_object_ptr()).native_data() as *mut PromiseState }
|
unsafe { (*promise.as_js_object_ptr()).native_data() as *mut PromiseState }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,6 +147,7 @@ impl Vm {
|
|||||||
pub(crate) fn is_promise_value(&self, v: JsValue) -> bool {
|
pub(crate) fn is_promise_value(&self, v: JsValue) -> bool {
|
||||||
v.is_object() && {
|
v.is_object() && {
|
||||||
let ptr = v.as_js_object_ptr();
|
let ptr = v.as_js_object_ptr();
|
||||||
|
// SAFETY: `is_object` 与 `ptr` 非空双守卫保证可解引用;只读 type_tag 判定,立即消费。
|
||||||
!ptr.is_null() && unsafe { &*ptr }.is_promise_obj()
|
!ptr.is_null() && unsafe { &*ptr }.is_promise_obj()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,6 +170,7 @@ impl Vm {
|
|||||||
if std::ptr::eq(ptr, target) {
|
if std::ptr::eq(ptr, target) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// SAFETY: 循环内 `is_object` 与 `ptr` 非空守卫保证可解引用;只读 proto(),链深受深度上限约束。
|
||||||
cursor = unsafe { &*ptr }.proto();
|
cursor = unsafe { &*ptr }.proto();
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
@@ -185,6 +196,7 @@ impl Vm {
|
|||||||
return self.reject_promise(promise, err);
|
return self.reject_promise(promise, err);
|
||||||
}
|
}
|
||||||
if x.is_object() {
|
if x.is_object() {
|
||||||
|
// SAFETY: `is_object` 保证指针非空且指向存活对象;只读 `then` 属性,本次读取内即时消费。
|
||||||
let x_obj = unsafe { &*x.as_js_object_ptr() };
|
let x_obj = unsafe { &*x.as_js_object_ptr() };
|
||||||
let then_si = self.kernel_core.perm_interner().intern("then").0;
|
let then_si = self.kernel_core.perm_interner().intern("then").0;
|
||||||
let then = match self.ordinary_get(x_obj, then_si, x) {
|
let then = match self.ordinary_get(x_obj, then_si, x) {
|
||||||
@@ -202,6 +214,7 @@ impl Vm {
|
|||||||
// 后续 executor 的 resolve/reject 均 no-op。委托用独立结算代理闭包
|
// 后续 executor 的 resolve/reject 均 no-op。委托用独立结算代理闭包
|
||||||
// (绕过 alreadyResolved——委托才是真正结算路径),仍受 state != Pending 守卫。
|
// (绕过 alreadyResolved——委托才是真正结算路径),仍受 state != Pending 守卫。
|
||||||
let state = self.promise_state_ptr(promise);
|
let state = self.promise_state_ptr(promise);
|
||||||
|
// SAFETY: 状态盒随已建 Promise 存活、指针非空;本块唯一可变借用,写 already_resolved 后结束。
|
||||||
let state = unsafe { &mut *state };
|
let state = unsafe { &mut *state };
|
||||||
state.already_resolved = true;
|
state.already_resolved = true;
|
||||||
let resolve = self.make_resolve_reject_fn(promise, false, true);
|
let resolve = self.make_resolve_reject_fn(promise, false, true);
|
||||||
@@ -222,6 +235,7 @@ impl Vm {
|
|||||||
pub(crate) fn fulfill_promise(&mut self, promise: JsValue, value: JsValue) -> Result<(), String> {
|
pub(crate) fn fulfill_promise(&mut self, promise: JsValue, value: JsValue) -> Result<(), String> {
|
||||||
let state_ptr = self.promise_state_ptr(promise);
|
let state_ptr = self.promise_state_ptr(promise);
|
||||||
let settled = {
|
let settled = {
|
||||||
|
// SAFETY: `state_ptr` 取自 promise_state_ptr,盒非空且随 promise 存活;本块唯一可变借用,块末释放。
|
||||||
let state = unsafe { &mut *state_ptr };
|
let state = unsafe { &mut *state_ptr };
|
||||||
if state.state != PromiseStateKind::Pending {
|
if state.state != PromiseStateKind::Pending {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -242,6 +256,8 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
// 原件若已晋升出克隆,把结算传导到克隆:克隆上晋升后新挂的反应方随此触发
|
// 原件若已晋升出克隆,把结算传导到克隆:克隆上晋升后新挂的反应方随此触发
|
||||||
// (顶层 var 读克隆,原件反应已在本处直接触发,不重复传导)。
|
// (顶层 var 读克隆,原件反应已在本处直接触发,不重复传导)。
|
||||||
|
// SAFETY: 同一 `state_ptr`,前块可变借用已结束;盒仍存活,promoted_clone
|
||||||
|
// 由 promise_native_edges 的 mark 边保证同轮存活(mod.rs 模块头不变量)。
|
||||||
let clone_ptr = unsafe { (*state_ptr).promoted_clone };
|
let clone_ptr = unsafe { (*state_ptr).promoted_clone };
|
||||||
if !clone_ptr.is_null() {
|
if !clone_ptr.is_null() {
|
||||||
let clone = JsValue::from_js_object(clone_ptr);
|
let clone = JsValue::from_js_object(clone_ptr);
|
||||||
@@ -254,6 +270,7 @@ impl Vm {
|
|||||||
pub(crate) fn reject_promise(&mut self, promise: JsValue, reason: JsValue) -> Result<(), String> {
|
pub(crate) fn reject_promise(&mut self, promise: JsValue, reason: JsValue) -> Result<(), String> {
|
||||||
let state_ptr = self.promise_state_ptr(promise);
|
let state_ptr = self.promise_state_ptr(promise);
|
||||||
let settled = {
|
let settled = {
|
||||||
|
// SAFETY: `state_ptr` 取自 promise_state_ptr,盒非空且随 promise 存活;本块唯一可变借用,块末释放。
|
||||||
let state = unsafe { &mut *state_ptr };
|
let state = unsafe { &mut *state_ptr };
|
||||||
if state.state != PromiseStateKind::Pending {
|
if state.state != PromiseStateKind::Pending {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -273,6 +290,8 @@ impl Vm {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 原件若已晋升出克隆,把拒绝传导到克隆(同 fulfill:顶层 var 读克隆)。
|
// 原件若已晋升出克隆,把拒绝传导到克隆(同 fulfill:顶层 var 读克隆)。
|
||||||
|
// SAFETY: 同一 `state_ptr`,前块可变借用已结束;盒仍存活,promoted_clone
|
||||||
|
// 由 promise_native_edges 的 mark 边保证同轮存活(mod.rs 模块头不变量)。
|
||||||
let clone_ptr = unsafe { (*state_ptr).promoted_clone };
|
let clone_ptr = unsafe { (*state_ptr).promoted_clone };
|
||||||
if !clone_ptr.is_null() {
|
if !clone_ptr.is_null() {
|
||||||
let clone = JsValue::from_js_object(clone_ptr);
|
let clone = JsValue::from_js_object(clone_ptr);
|
||||||
@@ -286,6 +305,7 @@ impl Vm {
|
|||||||
/// 结算(thenable 委托)。constructor getter / 结算抛错时透传原异常值。
|
/// 结算(thenable 委托)。constructor getter / 结算抛错时透传原异常值。
|
||||||
pub(crate) fn promise_resolve(&mut self, value: JsValue) -> Result<JsValue, JsValue> {
|
pub(crate) fn promise_resolve(&mut self, value: JsValue) -> Result<JsValue, JsValue> {
|
||||||
if self.is_promise_value(value) {
|
if self.is_promise_value(value) {
|
||||||
|
// SAFETY: `is_promise_value` 保证指针非空且 type_tag 为 Promise;只读 `constructor`,即时消费。
|
||||||
let obj = unsafe { &*value.as_js_object_ptr() };
|
let obj = unsafe { &*value.as_js_object_ptr() };
|
||||||
let ctor_si = self.kernel_core.perm_interner().intern("constructor").0;
|
let ctor_si = self.kernel_core.perm_interner().intern("constructor").0;
|
||||||
let ctor = match self.ordinary_get(obj, ctor_si, value) {
|
let ctor = match self.ordinary_get(obj, ctor_si, value) {
|
||||||
@@ -327,6 +347,7 @@ fn promise_resolve_closure(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
|||||||
if !delegated {
|
if !delegated {
|
||||||
// 非委托:alreadyResolved 守卫——首次调用置位,含 thenable 委托期间。
|
// 非委托:alreadyResolved 守卫——首次调用置位,含 thenable 委托期间。
|
||||||
let state = vm.promise_state_ptr(promise);
|
let state = vm.promise_state_ptr(promise);
|
||||||
|
// SAFETY: 非委托分支的唯一可变借用;状态盒随 promise 存活,写 already_resolved 后结束。
|
||||||
let state = unsafe { &mut *state };
|
let state = unsafe { &mut *state };
|
||||||
if state.already_resolved {
|
if state.already_resolved {
|
||||||
return NativeResult::Ok(JsValue::undefined());
|
return NativeResult::Ok(JsValue::undefined());
|
||||||
@@ -352,6 +373,7 @@ fn promise_reject_closure(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
|||||||
let reason = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
let reason = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||||
if !delegated {
|
if !delegated {
|
||||||
let state = vm.promise_state_ptr(promise);
|
let state = vm.promise_state_ptr(promise);
|
||||||
|
// SAFETY: 非委托分支的唯一可变借用;状态盒随 promise 存活,写 already_resolved 后结束。
|
||||||
let state = unsafe { &mut *state };
|
let state = unsafe { &mut *state };
|
||||||
if state.already_resolved {
|
if state.already_resolved {
|
||||||
return NativeResult::Ok(JsValue::undefined());
|
return NativeResult::Ok(JsValue::undefined());
|
||||||
@@ -369,6 +391,7 @@ fn capability_executor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
|||||||
if !callee.is_object() {
|
if !callee.is_object() {
|
||||||
return NativeResult::Err(oxide_builtins::error::create_type_error(vm, "executor is invalid"));
|
return NativeResult::Err(oxide_builtins::error::create_type_error(vm, "executor is invalid"));
|
||||||
}
|
}
|
||||||
|
// SAFETY: `callee` 来自 reg(254) 且 `is_object` 守卫保证指针非空存活;只读 CAP_* 判定,不跨 GC/reset。
|
||||||
let obj = unsafe { &*callee.as_js_object_ptr() };
|
let obj = unsafe { &*callee.as_js_object_ptr() };
|
||||||
let res_si = vm.kernel_core.perm_interner().intern(CAP_RESOLVE_PROP).0;
|
let res_si = vm.kernel_core.perm_interner().intern(CAP_RESOLVE_PROP).0;
|
||||||
let rej_si = vm.kernel_core.perm_interner().intern(CAP_REJECT_PROP).0;
|
let rej_si = vm.kernel_core.perm_interner().intern(CAP_REJECT_PROP).0;
|
||||||
@@ -382,6 +405,7 @@ fn capability_executor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
|||||||
}
|
}
|
||||||
let resolve = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
let resolve = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||||
let reject = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
let reject = if args.len() > 2 { vm.reg(args[2]) } else { JsValue::undefined() };
|
||||||
|
// SAFETY: 同一 `callee`,前一读借用已结束;对象存活且本块唯一可变借用,写 CAP_* 无别名。
|
||||||
let obj = unsafe { &mut *callee.as_js_object_ptr() };
|
let obj = unsafe { &mut *callee.as_js_object_ptr() };
|
||||||
vm.set_or_create_prop_value(obj, res_si, resolve);
|
vm.set_or_create_prop_value(obj, res_si, resolve);
|
||||||
vm.set_or_create_prop_value(obj, rej_si, reject);
|
vm.set_or_create_prop_value(obj, rej_si, reject);
|
||||||
|
|||||||
Reference in New Issue
Block a user