docs: 堆外属性区 SAFETY 样板收敛为字段声明

This commit is contained in:
2026-09-16 19:45:27 +00:00
parent faaa1e494b
commit ded63a739b
2 changed files with 32 additions and 27 deletions
+11 -2
View File
@@ -90,10 +90,20 @@ pub struct JsObject {
is_session_epoch: u8, is_session_epoch: u8,
_pad: u8, _pad: u8,
/// 数组元素区(仅数组对象):`Vec<JsValue>`,`len == array_prop_count`。 /// 数组元素区(仅数组对象):`Vec<JsValue>`,`len == array_prop_count`。
/// 经 `Box::into_raw` 创建(仅 `new_array` / `ensure_array_elements` 分配),
/// 本对象持有期间有效,由 `release_raw_heap` 释放。
array_elements: *mut u8, array_elements: *mut u8,
/// 数组元素元数据区(仅数组对象,懒分配):`Vec<Option<PropMetaEntry>>`。 /// 数组元素元数据区(仅数组对象,懒分配):`Vec<Option<PropMetaEntry>>`。
/// 经 `Box::into_raw` 创建(仅 `ensure_array_elements_meta` 分配),
/// 本对象持有期间有效,由 `release_raw_heap` 释放。
array_elements_meta: *mut u8, array_elements_meta: *mut u8,
/// 命名属性区(懒分配):`Vec<JsValue>` 值向量。
/// 经 `Box::into_raw` 创建(仅 `ensure_hash_props` 分配),
/// 本对象持有期间有效,由 `release_raw_heap` 释放。
hash_props: *mut u8, hash_props: *mut u8,
/// 命名属性元数据区(懒分配):`Vec<Option<PropMetaEntry>>`。
/// 经 `Box::into_raw` 创建(仅 `ensure_prop_meta` 分配),
/// 本对象持有期间有效,由 `release_raw_heap` 释放。
prop_meta: *mut u8, prop_meta: *mut u8,
native_data: *mut u8, native_data: *mut u8,
proto: JsValue, proto: JsValue,
@@ -516,8 +526,7 @@ impl JsObject {
/// 每区至多释放一次、重复调用为 no-op。upvalue 列表不在本函数释放范围内 /// 每区至多释放一次、重复调用为 no-op。upvalue 列表不在本函数释放范围内
/// (原件与晋升克隆间别名,须收尾时去重统一释放)。 /// (原件与晋升克隆间别名,须收尾时去重统一释放)。
pub fn release_raw_heap(&mut self) { pub fn release_raw_heap(&mut self) {
// SAFETY: 四个区各由 ensure_* 路径经 Box::into_raw 分配一次(或为空指针); // SAFETY: 四个区指针归本对象所有(见字段声明);回收后即刻置空。
// Box::from_raw 回收后即刻置空,杜绝二次释放。
unsafe { unsafe {
if !self.array_elements.is_null() { if !self.array_elements.is_null() {
drop(Box::from_raw(self.array_elements as *mut Vec<JsValue>)); drop(Box::from_raw(self.array_elements as *mut Vec<JsValue>));
+21 -25
View File
@@ -16,8 +16,7 @@ impl JsObject {
if self.hash_props.is_null() { if self.hash_props.is_null() {
0 0
} else { } else {
// SAFETY: hash_props 要么为空,要么在 ensure_hash_props/new_array 中 // SAFETY: 指针归本对象所有,见字段声明。
// 由 Box<Vec<JsValue>> 创建并归本对象所有。
let vec = unsafe { &*(self.hash_props as *const Vec<JsValue>) }; let vec = unsafe { &*(self.hash_props as *const Vec<JsValue>) };
vec.len() as u32 vec.len() as u32
} }
@@ -123,8 +122,7 @@ impl JsObject {
let vec = Box::new(vec![None::<PropMetaEntry>; len]); let vec = Box::new(vec![None::<PropMetaEntry>; len]);
self.prop_meta = Box::into_raw(vec) as *mut u8; self.prop_meta = Box::into_raw(vec) as *mut u8;
} }
// SAFETY: prop_meta 在 ensure_prop_meta 中由 // SAFETY: 指针归本对象所有,见字段声明。
// Box<Vec<Option<PropMetaEntry>>> 创建,本对象持有期间始终有效。
unsafe { &mut *(self.prop_meta as *mut Vec<Option<PropMetaEntry>>) } unsafe { &mut *(self.prop_meta as *mut Vec<Option<PropMetaEntry>>) }
} }
@@ -133,8 +131,7 @@ impl JsObject {
if self.prop_meta.is_null() { if self.prop_meta.is_null() {
None None
} else { } else {
// SAFETY: prop_meta 在 ensure_prop_meta 中由 // SAFETY: 指针归本对象所有,见字段声明。
// Box<Vec<Option<PropMetaEntry>>> 创建,本对象持有期间始终有效。
unsafe { Some(&*(self.prop_meta as *const Vec<Option<PropMetaEntry>>)) } unsafe { Some(&*(self.prop_meta as *const Vec<Option<PropMetaEntry>>)) }
} }
} }
@@ -143,8 +140,7 @@ impl JsObject {
if self.prop_meta.is_null() { if self.prop_meta.is_null() {
None None
} else { } else {
// SAFETY: prop_meta 在 ensure_prop_meta 中由 // SAFETY: 指针归本对象所有,见字段声明。
// Box<Vec<Option<PropMetaEntry>>> 创建,本对象持有期间始终有效。
unsafe { Some(&mut *(self.prop_meta as *mut Vec<Option<PropMetaEntry>>)) } unsafe { Some(&mut *(self.prop_meta as *mut Vec<Option<PropMetaEntry>>)) }
} }
} }
@@ -287,22 +283,22 @@ impl JsObject {
/// `set_prop_count` 按新形状重填。不清除形状 ID,调用方自行处理。 /// `set_prop_count` 按新形状重填。不清除形状 ID,调用方自行处理。
pub fn clear_props(&mut self) { pub fn clear_props(&mut self) {
if !self.array_elements.is_null() { if !self.array_elements.is_null() {
// SAFETY: array_elements 在 ensure_array_elements/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
let vec = unsafe { &mut *(self.array_elements as *mut Vec<JsValue>) }; let vec = unsafe { &mut *(self.array_elements as *mut Vec<JsValue>) };
vec.clear(); vec.clear();
} }
if !self.array_elements_meta.is_null() { if !self.array_elements_meta.is_null() {
// SAFETY: array_elements_meta 在 ensure_array_elements_meta 中创建。 // SAFETY: 指针归本对象所有,见字段声明。
let meta = unsafe { &mut *(self.array_elements_meta as *mut Vec<Option<PropMetaEntry>>) }; let meta = unsafe { &mut *(self.array_elements_meta as *mut Vec<Option<PropMetaEntry>>) };
meta.clear(); meta.clear();
} }
if !self.hash_props.is_null() { if !self.hash_props.is_null() {
// SAFETY: hash_props 在 ensure_hash_props/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
let vec = unsafe { &mut *(self.hash_props as *mut Vec<JsValue>) }; let vec = unsafe { &mut *(self.hash_props as *mut Vec<JsValue>) };
vec.clear(); vec.clear();
} }
if !self.prop_meta.is_null() { if !self.prop_meta.is_null() {
// SAFETY: prop_meta 在 ensure_prop_meta 中由 Box<Vec<Option<PropMetaEntry>>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
let meta = unsafe { &mut *(self.prop_meta as *mut Vec<Option<PropMetaEntry>>) }; let meta = unsafe { &mut *(self.prop_meta as *mut Vec<Option<PropMetaEntry>>) };
meta.clear(); meta.clear();
} }
@@ -315,7 +311,7 @@ impl JsObject {
let vec = Box::new(Vec::<JsValue>::new()); let vec = Box::new(Vec::<JsValue>::new());
self.hash_props = Box::into_raw(vec) as *mut u8; self.hash_props = Box::into_raw(vec) as *mut u8;
} }
// SAFETY: hash_props 在本方法或 new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
unsafe { &mut *(self.hash_props as *mut Vec<JsValue>) } unsafe { &mut *(self.hash_props as *mut Vec<JsValue>) }
} }
@@ -324,7 +320,7 @@ impl JsObject {
if self.hash_props.is_null() { if self.hash_props.is_null() {
None None
} else { } else {
// SAFETY: hash_props 在 ensure_hash_props/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
unsafe { Some(&*(self.hash_props as *const Vec<JsValue>)) } unsafe { Some(&*(self.hash_props as *const Vec<JsValue>)) }
} }
} }
@@ -333,7 +329,7 @@ impl JsObject {
if self.hash_props.is_null() { if self.hash_props.is_null() {
None None
} else { } else {
// SAFETY: hash_props 在 ensure_hash_props/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
unsafe { Some(&mut *(self.hash_props as *mut Vec<JsValue>)) } unsafe { Some(&mut *(self.hash_props as *mut Vec<JsValue>)) }
} }
} }
@@ -344,7 +340,7 @@ impl JsObject {
let vec = Box::new(Vec::<JsValue>::new()); let vec = Box::new(Vec::<JsValue>::new());
self.array_elements = Box::into_raw(vec) as *mut u8; self.array_elements = Box::into_raw(vec) as *mut u8;
} }
// SAFETY: array_elements 在本方法或 new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
let vec = unsafe { &mut *(self.array_elements as *mut Vec<JsValue>) }; let vec = unsafe { &mut *(self.array_elements as *mut Vec<JsValue>) };
while vec.len() < self.array_prop_count as usize { while vec.len() < self.array_prop_count as usize {
vec.push(JsValue::undefined()); vec.push(JsValue::undefined());
@@ -357,7 +353,7 @@ impl JsObject {
if self.array_elements.is_null() { if self.array_elements.is_null() {
None None
} else { } else {
// SAFETY: array_elements 在 ensure_array_elements/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
unsafe { Some(&*(self.array_elements as *const Vec<JsValue>)) } unsafe { Some(&*(self.array_elements as *const Vec<JsValue>)) }
} }
} }
@@ -366,7 +362,7 @@ impl JsObject {
if self.array_elements.is_null() { if self.array_elements.is_null() {
None None
} else { } else {
// SAFETY: array_elements 在 ensure_array_elements/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
unsafe { Some(&mut *(self.array_elements as *mut Vec<JsValue>)) } unsafe { Some(&mut *(self.array_elements as *mut Vec<JsValue>)) }
} }
} }
@@ -378,7 +374,7 @@ impl JsObject {
let vec = Box::new(vec![None::<PropMetaEntry>; len]); let vec = Box::new(vec![None::<PropMetaEntry>; len]);
self.array_elements_meta = Box::into_raw(vec) as *mut u8; self.array_elements_meta = Box::into_raw(vec) as *mut u8;
} }
// SAFETY: array_elements_meta 在本方法中由 Box<Vec<Option<PropMetaEntry>>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
let vec = unsafe { &mut *(self.array_elements_meta as *mut Vec<Option<PropMetaEntry>>) }; let vec = unsafe { &mut *(self.array_elements_meta as *mut Vec<Option<PropMetaEntry>>) };
while vec.len() < self.array_prop_count as usize { while vec.len() < self.array_prop_count as usize {
vec.push(None); vec.push(None);
@@ -391,7 +387,7 @@ impl JsObject {
if self.array_elements_meta.is_null() { if self.array_elements_meta.is_null() {
None None
} else { } else {
// SAFETY: array_elements_meta 在 ensure_array_elements_meta 中创建。 // SAFETY: 指针归本对象所有,见字段声明。
unsafe { Some(&*(self.array_elements_meta as *const Vec<Option<PropMetaEntry>>)) } unsafe { Some(&*(self.array_elements_meta as *const Vec<Option<PropMetaEntry>>)) }
} }
} }
@@ -400,7 +396,7 @@ impl JsObject {
if self.array_elements_meta.is_null() { if self.array_elements_meta.is_null() {
None None
} else { } else {
// SAFETY: array_elements_meta 在 ensure_array_elements_meta 中创建。 // SAFETY: 指针归本对象所有,见字段声明。
unsafe { Some(&mut *(self.array_elements_meta as *mut Vec<Option<PropMetaEntry>>)) } unsafe { Some(&mut *(self.array_elements_meta as *mut Vec<Option<PropMetaEntry>>)) }
} }
} }
@@ -415,21 +411,21 @@ impl JsObject {
if self.array_elements.is_null() { if self.array_elements.is_null() {
return JsValue::undefined(); return JsValue::undefined();
} }
// SAFETY: array_elements 在 ensure_array_elements/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
let vec = unsafe { &*(self.array_elements as *const Vec<JsValue>) }; let vec = unsafe { &*(self.array_elements as *const Vec<JsValue>) };
return vec.get(pos).copied().unwrap_or(JsValue::undefined()); return vec.get(pos).copied().unwrap_or(JsValue::undefined());
} }
if self.hash_props.is_null() { if self.hash_props.is_null() {
return JsValue::undefined(); return JsValue::undefined();
} }
// SAFETY: hash_props 在 ensure_hash_props/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
let vec = unsafe { &*(self.hash_props as *const Vec<JsValue>) }; let vec = unsafe { &*(self.hash_props as *const Vec<JsValue>) };
return vec.get(pos - count).copied().unwrap_or(JsValue::undefined()); return vec.get(pos - count).copied().unwrap_or(JsValue::undefined());
} }
if self.hash_props.is_null() { if self.hash_props.is_null() {
return JsValue::undefined(); return JsValue::undefined();
} }
// SAFETY: hash_props 在 ensure_hash_props/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
let vec = unsafe { &*(self.hash_props as *const Vec<JsValue>) }; let vec = unsafe { &*(self.hash_props as *const Vec<JsValue>) };
vec.get(pos).copied().unwrap_or(JsValue::undefined()) vec.get(pos).copied().unwrap_or(JsValue::undefined())
} }
@@ -552,7 +548,7 @@ impl JsObject {
if self.hash_props.is_null() { if self.hash_props.is_null() {
0 0
} else { } else {
// SAFETY: hash_props 在 ensure_hash_props/new_array 中由 Box<Vec<JsValue>> 创建。 // SAFETY: 指针归本对象所有,见字段声明。
unsafe { &*(self.hash_props as *const Vec<JsValue>) }.len() unsafe { &*(self.hash_props as *const Vec<JsValue>) }.len()
} }
} }