feat(typedarray): 实现整数索引读取与 for-of 迭代(get_iterator 支持)

This commit is contained in:
爱特每羊队
2026-08-07 18:10:19 +08:00
parent 33690fb803
commit eebee1b624
3 changed files with 51 additions and 1 deletions
+33 -1
View File
@@ -119,7 +119,12 @@ pub fn iterator_wrapper_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
}
fn get_iterator<H: VmHost>(vm: &mut H, value: JsValue) -> Result<JsValue, JsValue> {
if value.is_string() || is_array_value(value) || is_map_value(value) || is_set_value(value) {
if value.is_string()
|| is_array_value(value)
|| is_typed_array_value(value)
|| is_map_value(value)
|| is_set_value(value)
{
return Ok(value);
}
@@ -197,6 +202,25 @@ fn next_array_like<H: VmHost>(
return Ok(Some(make_iter_result(vm, JsValue::undefined(), true)));
}
if is_typed_array_value(inner) {
let index = current_index(vm, wrapper, index_si);
let length_si = vm.kernel_core().perm_interner().intern("length").0;
let obj = unsafe { &*inner.as_js_object_ptr() };
let len = vm
.ordinary_get(obj, length_si, inner)
.map(|v| if v.is_int() { v.as_int().max(0) as usize } else { 0 })
.unwrap_or(0);
if index < len {
let value = match crate::typed_array::typed_array_element_get(vm, obj, index as u32) {
Ok(v) => v,
Err(e) => return Err(crate::error::create_type_error(vm, &e)),
};
vm.set_or_create_prop_value(wrapper, index_si, JsValue::int((index + 1) as i32));
return Ok(Some(make_iter_result(vm, value, false)));
}
return Ok(Some(make_iter_result(vm, JsValue::undefined(), true)));
}
// for-of 循环默认迭代:Map 产出 [key, value] 对,Set 产出值。
if is_map_value(inner) {
return Ok(Some(map_set_step(vm, wrapper, inner, index_si, MapSetMode::MapEntries)));
@@ -252,6 +276,14 @@ fn is_array_value(value: JsValue) -> bool {
!ptr.is_null() && unsafe { &*ptr }.is_array()
}
fn is_typed_array_value(value: JsValue) -> bool {
if !value.is_object() {
return false;
}
let ptr = value.as_js_object_ptr();
!ptr.is_null() && unsafe { &*ptr }.is_typed_array_obj()
}
fn is_callable(value: JsValue) -> bool {
if !value.is_object() {
return false;
+13
View File
@@ -214,6 +214,19 @@ fn absolute_byte_offset(view: TypedArrayData, index: usize) -> usize {
view.byte_offset + index * view.kind.bytes_per_element()
}
/// 读 TypedArray 指定整数索引的元素(供 VM 普通属性 get 的 typed 分支使用)。
/// 越界返回 undefined;内部状态非法返回 Err(String)。
pub fn typed_array_element_get<H: VmHost>(vm: &mut H, obj: &JsObject, index: u32) -> Result<JsValue, String> {
let this_val = JsValue::from_js_object(obj as *const JsObject as *mut JsObject);
let view = get_typed_array_data(vm, this_val).map_err(|e| format!("{e}"))?;
if index as usize >= view.length {
return Ok(JsValue::undefined());
}
let buffer_ptr = array_buffer_data_ptr(vm, view.buffer).map_err(|e| format!("{e}"))?;
let buffer = unsafe { &*buffer_ptr };
Ok(read_element(view.kind, buffer, absolute_byte_offset(view, index as usize)))
}
fn read_element(kind: TypedArrayKind, bytes: &[u8], offset: usize) -> JsValue {
match kind {
TypedArrayKind::Int8 => JsValue::int(bytes[offset] as i8 as i32),