mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 02:31:13 +08:00
docs: 补齐 Promise 聚合与反应的安全注记
This commit is contained in:
@@ -24,6 +24,7 @@ impl Vm {
|
||||
fn make_agg_record(&mut self, values: JsValue, resolve: JsValue, reject: JsValue) -> JsValue {
|
||||
let proto_val = JsValue::from_js_object(self.session.builtin_world().object_proto.as_ptr() as *mut JsObject);
|
||||
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
|
||||
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;本次 native 调用内不搬移,借出期间无别名。
|
||||
let obj = unsafe { &mut *ptr };
|
||||
let rem_si = self.kernel_core.perm_interner().intern(AGG_REMAINING_PROP).0;
|
||||
self.set_or_create_prop_value(obj, rem_si, JsValue::int(1));
|
||||
@@ -47,6 +48,7 @@ impl Vm {
|
||||
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(native_fn as *const ()) }));
|
||||
func.set_native_arg_count(1);
|
||||
let ptr = self.alloc_object(func);
|
||||
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;后续 add_fn_name_length 的 shape/属性分配不改对象地址,借出期间无别名。
|
||||
let obj = unsafe { &mut *ptr };
|
||||
self.add_fn_name_length(obj, "", 1);
|
||||
let sh = self.kernel_core.shape_forge().as_ref();
|
||||
@@ -73,6 +75,7 @@ impl Vm {
|
||||
fn make_settled_record(&mut self, status: &str, value_field: &str, value: JsValue) -> JsValue {
|
||||
let proto_val = JsValue::from_js_object(self.session.builtin_world().object_proto.as_ptr() as *mut JsObject);
|
||||
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
|
||||
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;写 status/value 属性(含 new_string 分配)期间不搬移,借出期间无别名。
|
||||
let obj = unsafe { &mut *ptr };
|
||||
let status_si = self.kernel_core.perm_interner().intern("status").0;
|
||||
let status_val = self.new_string(status);
|
||||
@@ -87,6 +90,7 @@ impl Vm {
|
||||
fn make_aggregate_error(&mut self, errors: JsValue, message: JsValue) -> JsValue {
|
||||
let proto_val = JsValue::from_js_object(self.aggregate_error_proto.as_ptr() as *mut JsObject);
|
||||
let ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, proto_val));
|
||||
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;写 message/errors 数据属性期间不搬移,借出期间无别名。
|
||||
let obj = unsafe { &mut *ptr };
|
||||
// message/errors 为数据属性:writable、非枚举、configurable(CreateMethodProperty)。
|
||||
let attrs = PropAttributes::new(true, false, true);
|
||||
@@ -173,14 +177,17 @@ impl Vm {
|
||||
// 固定地址后互相接线:proto.constructor ↔ ctor.prototype。
|
||||
Self::swap_intrinsic_proto(&mut self.aggregate_error_proto, *proto);
|
||||
Self::swap_intrinsic_proto(&mut self.aggregate_error_constructor, *ctor);
|
||||
// SAFETY: aggregate_error_proto 为堆址固定的 P<JsObject>(Arc 透明包装),本行前刚经 swap_intrinsic_proto 落地;与 ctor_mut 分属不同对象,无别名。
|
||||
let proto_mut = unsafe { &mut *self.aggregate_error_proto.as_mut_ptr() };
|
||||
proto_mut
|
||||
.set_prop_at(0u32, JsValue::from_js_object(self.aggregate_error_constructor.as_ptr() as *mut JsObject));
|
||||
// SAFETY: aggregate_error_constructor 同为堆址固定的 P<JsObject>(Arc 透明包装);此处写 prototype 槽位(下标 2),与 proto_mut 分属不同对象,无别名。
|
||||
let ctor_mut = unsafe { &mut *self.aggregate_error_constructor.as_mut_ptr() };
|
||||
ctor_mut.set_prop_at(2u32, JsValue::from_js_object(self.aggregate_error_proto.as_ptr() as *mut JsObject));
|
||||
|
||||
// 绑定 global(槽已存在则更新)。
|
||||
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 si = self.kernel_core.perm_interner().intern("AggregateError").0;
|
||||
let ctor_val = JsValue::from_js_object(self.aggregate_error_constructor.as_ptr() as *mut JsObject);
|
||||
@@ -202,6 +209,7 @@ pub(super) fn promise_static_resolve(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let ctor = vm.reg(if args.is_empty() { 0 } else { args[0] });
|
||||
let x = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||
if vm.is_promise_value(x) {
|
||||
// SAFETY: is_promise_value 已验证 x 为原生 Promise 对象,指针非空且存活;此处只读 constructor,即时消费。
|
||||
let x_obj = unsafe { &*x.as_js_object_ptr() };
|
||||
let ctor_si = vm.kernel_core.perm_interner().intern("constructor").0;
|
||||
let x_ctor = match vm.ordinary_get(x_obj, ctor_si, x) {
|
||||
@@ -273,6 +281,7 @@ pub(super) fn promise_static_with_resolvers(vm: &mut Vm, args: &[u8]) -> NativeR
|
||||
};
|
||||
let object_proto = JsValue::from_js_object(vm.session.builtin_world().object_proto.as_ptr() as *mut JsObject);
|
||||
let ptr = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, object_proto));
|
||||
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;写 promise/resolve/reject 属性期间不搬移,借出期间无别名。
|
||||
let obj = unsafe { &mut *ptr };
|
||||
let sf = vm.kernel_core.perm_interner().as_ref();
|
||||
let sh = vm.kernel_core.shape_forge().as_ref();
|
||||
@@ -707,6 +716,7 @@ fn aggregate_error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
Err(err) => return NativeResult::Err(err),
|
||||
};
|
||||
let err_si = vm.kernel_core.perm_interner().intern("errors").0;
|
||||
// SAFETY: this 为本次构造得到的既有或新建存活对象;此处写 errors 数据属性,与上方 message 写入顺序独占同一对象,无别名。
|
||||
let _ = vm.define_data_property(unsafe { &mut *this }, err_si, errors_list, PropAttributes::new(true, false, true));
|
||||
NativeResult::Ok(JsValue::from_js_object(this))
|
||||
}
|
||||
|
||||
@@ -54,11 +54,13 @@ impl Vm {
|
||||
let (new_promise, resolve, reject) = capability;
|
||||
let state_ptr = self.promise_state_ptr(this_val);
|
||||
let (kind, result) = {
|
||||
// SAFETY: this_val 已过 is_promise_value 校验,state_ptr 取自 promise_state_ptr;状态盒非空且随对象存活,本块唯一可变借用,读完 state/result 即结束。
|
||||
let state = unsafe { &mut *state_ptr };
|
||||
(state.state, state.result)
|
||||
};
|
||||
match kind {
|
||||
PromiseStateKind::Pending => {
|
||||
// SAFETY: 同一 state_ptr,前一可变借用已结束;状态盒非空且随 this_val 存活,此处仅向 reactions 追加两条反应,无别名。
|
||||
let state = unsafe { &mut *state_ptr };
|
||||
state.reactions.push(PromiseReaction {
|
||||
promise: new_promise,
|
||||
@@ -126,6 +128,7 @@ impl Vm {
|
||||
/// undefined 会错误退回内置;`@@species` 改写支持待补
|
||||
/// `Promise[Symbol.species]` getter 时一并落地。
|
||||
fn species_constructor(&mut self, promise: JsValue) -> Result<JsValue, JsValue> {
|
||||
// SAFETY: 调用方已按函数文档前提做 is_promise_value 校验,指针非空且指向存活 Promise 对象;此处只读 constructor。
|
||||
let obj = unsafe { &*promise.as_js_object_ptr() };
|
||||
let ctor_si = self.kernel_core.perm_interner().intern("constructor").0;
|
||||
let ctor = match self.ordinary_get(obj, ctor_si, promise) {
|
||||
@@ -211,6 +214,7 @@ impl Vm {
|
||||
Err(e) => return Err(oxide_builtins::error::create_type_error(self, &e)),
|
||||
}
|
||||
};
|
||||
// SAFETY: get_receiver 两分支均为对象(is_object 原值或 to_object 返回对象),指针非空且存活;此处只读 then 属性。
|
||||
let receiver_obj = unsafe { &*get_receiver.as_js_object_ptr() };
|
||||
let then = match self.ordinary_get(receiver_obj, then_si, this_val) {
|
||||
Ok(v) => v,
|
||||
@@ -244,6 +248,7 @@ impl Vm {
|
||||
func.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(promise_finally_handler as *const ()) }));
|
||||
func.set_native_arg_count(0);
|
||||
let ptr = self.alloc_object(func);
|
||||
// SAFETY: ptr 由 alloc_object 新建,返回非空 arena 指针;本次 native 调用内不搬移,借出期间无别名。
|
||||
let obj = unsafe { &mut *ptr };
|
||||
let of_si = self.kernel_core.perm_interner().intern(ON_FINALLY_PROP).0;
|
||||
self.set_or_create_prop_value(obj, of_si, on_finally);
|
||||
@@ -278,6 +283,7 @@ fn promise_finally_handler(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
if !callee.is_object() {
|
||||
return NativeResult::Err(oxide_builtins::error::create_type_error(vm, "finally handler is invalid"));
|
||||
}
|
||||
// SAFETY: callee 来自 reg(254) 且 is_object 守卫保证指针非空存活;此处只读 ON_FINALLY/FINALLY_REJECT 属性。
|
||||
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
|
||||
let of_si = vm.kernel_core.perm_interner().intern(ON_FINALLY_PROP).0;
|
||||
let on_finally = vm.resolve_property(callee_obj, of_si).unwrap_or(JsValue::undefined());
|
||||
|
||||
Reference in New Issue
Block a user