diff --git a/crates/oxide_builtins/src/iterator.rs b/crates/oxide_builtins/src/iterator.rs index 07a9902d..48db4e47 100644 --- a/crates/oxide_builtins/src/iterator.rs +++ b/crates/oxide_builtins/src/iterator.rs @@ -119,7 +119,12 @@ pub fn iterator_wrapper_next(vm: &mut H, args: &[u8]) -> NativeResult } fn get_iterator(vm: &mut H, value: JsValue) -> Result { - 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( 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; diff --git a/crates/oxide_builtins/src/typed_array.rs b/crates/oxide_builtins/src/typed_array.rs index abda3ddd..c73628e5 100644 --- a/crates/oxide_builtins/src/typed_array.rs +++ b/crates/oxide_builtins/src/typed_array.rs @@ -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(vm: &mut H, obj: &JsObject, index: u32) -> Result { + 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), diff --git a/crates/oxide_vm/src/vm_props.rs b/crates/oxide_vm/src/vm_props.rs index be30fb26..b36b5f4d 100644 --- a/crates/oxide_vm/src/vm_props.rs +++ b/crates/oxide_vm/src/vm_props.rs @@ -53,6 +53,11 @@ impl Vm { } } } + if obj.is_typed_array_obj() { + if let Some(index) = self.array_index_from_property_key(prop_name_si) { + return oxide_builtins::typed_array::typed_array_element_get(self, obj, index); + } + } if let Some(pos) = self.get_own_property_slot(obj, prop_name_si) { if let Some(meta) = obj.prop_meta_at(pos) { if meta.is_accessor {