feat: 搭建 Iterator 与 for-of 语法基础设施
This commit is contained in:
@@ -379,3 +379,40 @@ pub fn object_has_own(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
if !key_val.is_string() { return Ok(JsValue::bool(false)); }
|
||||
Ok(JsValue::bool(false))
|
||||
}
|
||||
|
||||
pub fn object_entries(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let obj_ptr = require_obj_arg(vm, args, "entries")?;
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
let keys = walk_own_keys(vm, obj);
|
||||
let n = keys.len().min(255);
|
||||
let array_proto = vm.kernel().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let arr = vm.epoch().alloc(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), n, vm.epoch().bump()));
|
||||
for (_i, (si, offset)) in keys.iter().enumerate().take(n) {
|
||||
let key_str = vm.kernel().string_forge().lookup(*si).unwrap_or_default();
|
||||
let key_val = vm.intern(&key_str);
|
||||
let val = obj.get_prop_at(*offset);
|
||||
let pair = vm.epoch().alloc(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), 2, vm.epoch().bump()));
|
||||
unsafe {
|
||||
(*pair).set_prop_at(0, key_val);
|
||||
(*pair).set_prop_at(1, val);
|
||||
(*pair).set_prop_count(2);
|
||||
(*arr).ensure_hash_props().push(Box::new(JsValue::from_js_object(pair)));
|
||||
}
|
||||
}
|
||||
Ok(JsValue::from_js_object(arr))
|
||||
}
|
||||
|
||||
pub fn object_values(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let obj_ptr = require_obj_arg(vm, args, "values")?;
|
||||
let obj = unsafe { &*obj_ptr };
|
||||
let keys = walk_own_keys(vm, obj);
|
||||
let n = keys.len().min(255);
|
||||
let array_proto = vm.kernel().builtin_world().array_proto.as_ptr() as *mut JsObject;
|
||||
let arr = vm.epoch().alloc(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(array_proto), n, vm.epoch().bump()));
|
||||
for (i, (_si, offset)) in keys.iter().enumerate().take(n) {
|
||||
let val = obj.get_prop_at(*offset);
|
||||
unsafe { (*arr).set_prop_at(i as u8, val); }
|
||||
}
|
||||
unsafe { (*arr).set_prop_count(n as u8); }
|
||||
Ok(JsValue::from_js_object(arr))
|
||||
}
|
||||
|
||||
@@ -469,3 +469,36 @@ pub fn string_normalize(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
};
|
||||
Ok(vm.intern(&result))
|
||||
}
|
||||
|
||||
pub fn string_match_all(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 { return Err(JsValue::undefined()); }
|
||||
let pattern_val = vm.reg(args[1]);
|
||||
if is_regexp_obj(pattern_val, vm) {
|
||||
let re_ptr = pattern_val.as_js_object_ptr();
|
||||
let re = unsafe { &*re_ptr };
|
||||
let fn_ptr = match re.native_fn() { Some(p) => p, None => return Ok(JsValue::undefined()) };
|
||||
let regex = unsafe { &*(fn_ptr as *const regex::Regex) };
|
||||
let matches: Vec<String> = regex.find_iter(&s).map(|m| m.as_str().to_string()).collect();
|
||||
return Ok(make_string_array(vm, &matches));
|
||||
}
|
||||
Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn string_replace_all(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 { return Ok(vm.intern(&s)); }
|
||||
let pattern_val = vm.reg(args[1]);
|
||||
let replacement = if args.len() > 2 { as_string(vm, vm.reg(args[2])) } else { String::new() };
|
||||
if is_regexp_obj(pattern_val, vm) {
|
||||
let re_ptr = pattern_val.as_js_object_ptr();
|
||||
let re = unsafe { &*re_ptr };
|
||||
let fn_ptr = match re.native_fn() { Some(p) => p, None => return Ok(vm.intern(&s)) };
|
||||
let regex = unsafe { &*(fn_ptr as *const regex::Regex) };
|
||||
let result = regex.replace_all(&s, replacement.as_str()).to_string();
|
||||
return Ok(vm.intern(&result));
|
||||
}
|
||||
let pattern = as_string(vm, pattern_val);
|
||||
let result = s.replace(&pattern, &replacement);
|
||||
Ok(vm.intern(&result))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user