mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
feat: 实现整数索引读取与 for-of 迭代(get_iterator 支持)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user