mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 10:41:11 +08:00
refactor: 统一调用调度并安全化 IC 缓存
This commit is contained in:
@@ -31,11 +31,15 @@ fn boxed_primitive_value(this_val: JsValue) -> Option<JsValue> {
|
||||
pub fn string_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let this_val = vm.reg(args[0]);
|
||||
if this_val.is_string() {
|
||||
return Ok(this_val);
|
||||
return NativeResult::Ok(this_val);
|
||||
}
|
||||
match boxed_primitive_value(this_val) {
|
||||
Some(v) => NativeResult::Ok(v),
|
||||
None => NativeResult::Err(crate::builtins::error::create_type_error(
|
||||
vm,
|
||||
"String.prototype.valueOf called on non-String object",
|
||||
)),
|
||||
}
|
||||
boxed_primitive_value(this_val).ok_or_else(|| {
|
||||
crate::builtins::error::create_type_error(vm, "String.prototype.valueOf called on non-String object")
|
||||
})
|
||||
}
|
||||
|
||||
fn make_string_array(vm: &mut Vm, parts: &[String]) -> JsValue {
|
||||
@@ -58,6 +62,27 @@ fn as_string(vm: &Vm, val: JsValue) -> String {
|
||||
coercion::to_string(vm.kernel().string_forge().as_ref(), val)
|
||||
}
|
||||
|
||||
fn char_len(s: &str) -> usize {
|
||||
s.chars().count()
|
||||
}
|
||||
|
||||
fn byte_index_at_char(s: &str, char_pos: usize) -> usize {
|
||||
if char_pos == 0 {
|
||||
return 0;
|
||||
}
|
||||
s.char_indices().nth(char_pos).map(|(idx, _)| idx).unwrap_or(s.len())
|
||||
}
|
||||
|
||||
fn char_slice(s: &str, start: usize, end: usize) -> &str {
|
||||
let start_byte = byte_index_at_char(s, start);
|
||||
let end_byte = byte_index_at_char(s, end);
|
||||
&s[start_byte..end_byte]
|
||||
}
|
||||
|
||||
fn take_chars(s: &str, count: usize) -> String {
|
||||
s.chars().take(count).collect()
|
||||
}
|
||||
|
||||
fn is_regexp_obj(val: JsValue, vm: &Vm) -> bool {
|
||||
if !val.is_object() {
|
||||
return false;
|
||||
@@ -81,52 +106,57 @@ fn is_regexp_obj(val: JsValue, vm: &Vm) -> bool {
|
||||
|
||||
pub fn string_index_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s);
|
||||
if args.len() < 2 {
|
||||
return Ok(JsValue::int(-1));
|
||||
return NativeResult::Ok(JsValue::int(-1));
|
||||
}
|
||||
let search = as_string(vm, vm.reg(args[1]));
|
||||
let pos = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2]), vm.kernel().string_forge().as_ref()) as usize).min(s.len())
|
||||
(coercion::to_number(vm.reg(args[2]), vm.kernel().string_forge().as_ref()) as usize).min(n)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
if search.is_empty() {
|
||||
return Ok(JsValue::int(pos as i32));
|
||||
return NativeResult::Ok(JsValue::int(pos as i32));
|
||||
}
|
||||
|
||||
let haystack = &s.as_bytes()[pos..];
|
||||
let start_byte = byte_index_at_char(&s, pos);
|
||||
let haystack = &s[start_byte..];
|
||||
if search.len() == 1 {
|
||||
if let Some(idx) = memchr(search.as_bytes()[0], haystack) {
|
||||
return Ok(JsValue::int((pos + idx) as i32));
|
||||
if let Some(idx) = memchr(search.as_bytes()[0], haystack.as_bytes()) {
|
||||
let matched_byte = start_byte + idx;
|
||||
return NativeResult::Ok(JsValue::int(char_len(&s[..matched_byte]) as i32));
|
||||
}
|
||||
} else if let Some(idx) = s[pos..].find(&search) {
|
||||
return Ok(JsValue::int((pos + idx) as i32));
|
||||
} else if let Some(idx) = haystack.find(&search) {
|
||||
let matched_byte = start_byte + idx;
|
||||
return NativeResult::Ok(JsValue::int(char_len(&s[..matched_byte]) as i32));
|
||||
}
|
||||
Ok(JsValue::int(-1))
|
||||
NativeResult::Ok(JsValue::int(-1))
|
||||
}
|
||||
|
||||
pub fn string_includes(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s);
|
||||
if args.len() < 2 {
|
||||
return Ok(JsValue::bool(false));
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
let search = as_string(vm, vm.reg(args[1]));
|
||||
let pos = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2]), vm.kernel().string_forge().as_ref()) as usize).min(s.len())
|
||||
(coercion::to_number(vm.reg(args[2]), vm.kernel().string_forge().as_ref()) as usize).min(n)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
if search.is_empty() {
|
||||
return Ok(JsValue::bool(true));
|
||||
return NativeResult::Ok(JsValue::bool(true));
|
||||
}
|
||||
|
||||
let haystack = &s.as_bytes()[pos..];
|
||||
let haystack = &s[byte_index_at_char(&s, pos)..];
|
||||
if search.len() == 1 {
|
||||
Ok(JsValue::bool(memchr(search.as_bytes()[0], haystack).is_some()))
|
||||
NativeResult::Ok(JsValue::bool(memchr(search.as_bytes()[0], haystack.as_bytes()).is_some()))
|
||||
} else {
|
||||
Ok(JsValue::bool(s[pos..].contains(&search)))
|
||||
NativeResult::Ok(JsValue::bool(haystack.contains(&search)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,31 +164,31 @@ pub fn string_char_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
if s.is_empty() {
|
||||
return Ok(vm.intern(""));
|
||||
return NativeResult::Ok(vm.intern(""));
|
||||
}
|
||||
return Ok(vm.intern(&s[0..1]));
|
||||
return NativeResult::Ok(vm.intern(&take_chars(&s, 1)));
|
||||
}
|
||||
let idx = coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref()) as i32;
|
||||
if idx < 0 || idx as usize >= s.len() {
|
||||
return Ok(vm.intern(""));
|
||||
if idx < 0 || idx as usize >= char_len(&s) {
|
||||
return NativeResult::Ok(vm.intern(""));
|
||||
}
|
||||
let ch = &s[(idx as usize)..(idx as usize + 1)];
|
||||
Ok(vm.intern(ch))
|
||||
let ch = s.chars().nth(idx as usize).map(|c| c.to_string()).unwrap_or_default();
|
||||
NativeResult::Ok(vm.intern(&ch))
|
||||
}
|
||||
|
||||
pub fn string_char_code_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
if s.is_empty() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
return NativeResult::Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
return Ok(JsValue::int(s.as_bytes()[0] as i32));
|
||||
return NativeResult::Ok(JsValue::int(s.chars().next().unwrap() as i32));
|
||||
}
|
||||
let idx = coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref()) as i32;
|
||||
if idx < 0 || idx as usize >= s.len() {
|
||||
return Ok(JsValue::float(f64::NAN));
|
||||
if idx < 0 || idx as usize >= char_len(&s) {
|
||||
return NativeResult::Ok(JsValue::float(f64::NAN));
|
||||
}
|
||||
Ok(JsValue::int(s.as_bytes()[idx as usize] as i32))
|
||||
NativeResult::Ok(JsValue::int(s.chars().nth(idx as usize).unwrap() as i32))
|
||||
}
|
||||
|
||||
pub fn string_concat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
@@ -167,12 +197,12 @@ pub fn string_concat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
for &arg_reg in args.iter().skip(1) {
|
||||
result.push_str(&coercion::to_string(sf, vm.reg(arg_reg)));
|
||||
}
|
||||
Ok(vm.intern(&result))
|
||||
NativeResult::Ok(vm.intern(&result))
|
||||
}
|
||||
|
||||
pub fn string_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = s.len() as i32;
|
||||
let n = char_len(&s) as i32;
|
||||
let start = if args.len() > 1 {
|
||||
let v = coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref()) as i32;
|
||||
if v < 0 {
|
||||
@@ -195,13 +225,13 @@ pub fn string_slice(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
};
|
||||
let start = start as usize;
|
||||
let end = end as usize;
|
||||
let result = if start < end { &s[start..end] } else { "" };
|
||||
Ok(vm.intern(result))
|
||||
let result = if start < end { char_slice(&s, start, end) } else { "" };
|
||||
NativeResult::Ok(vm.intern(result))
|
||||
}
|
||||
|
||||
pub fn string_substring(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = s.len() as i32;
|
||||
let n = char_len(&s) as i32;
|
||||
let mut start = if args.len() > 1 {
|
||||
(coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref()) as i32)
|
||||
.max(0)
|
||||
@@ -219,23 +249,23 @@ pub fn string_substring(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
if start > end {
|
||||
std::mem::swap(&mut start, &mut end);
|
||||
}
|
||||
let result = &s[start as usize..end as usize];
|
||||
Ok(vm.intern(result))
|
||||
let result = char_slice(&s, start as usize, end as usize);
|
||||
NativeResult::Ok(vm.intern(result))
|
||||
}
|
||||
|
||||
pub fn string_to_upper_case(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
Ok(vm.intern(&s.to_uppercase()))
|
||||
NativeResult::Ok(vm.intern(&s.to_uppercase()))
|
||||
}
|
||||
|
||||
pub fn string_to_lower_case(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
Ok(vm.intern(&s.to_lowercase()))
|
||||
NativeResult::Ok(vm.intern(&s.to_lowercase()))
|
||||
}
|
||||
|
||||
pub fn string_trim(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
Ok(vm.intern(s.trim()))
|
||||
NativeResult::Ok(vm.intern(s.trim()))
|
||||
}
|
||||
|
||||
pub fn string_repeat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
@@ -245,80 +275,84 @@ pub fn string_repeat(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
} else {
|
||||
1
|
||||
};
|
||||
Ok(vm.intern(&s.repeat(n)))
|
||||
NativeResult::Ok(vm.intern(&s.repeat(n)))
|
||||
}
|
||||
|
||||
pub fn string_pad_start(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let s_len = char_len(&s);
|
||||
let target = if args.len() > 1 {
|
||||
coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref()) as usize
|
||||
} else {
|
||||
s.len()
|
||||
s_len
|
||||
};
|
||||
let pad = if args.len() > 2 { as_string(vm, vm.reg(args[2])) } else { " ".to_string() };
|
||||
if s.len() >= target || pad.is_empty() {
|
||||
return Ok(vm.intern(&s));
|
||||
if s_len >= target || pad.is_empty() {
|
||||
return NativeResult::Ok(vm.intern(&s));
|
||||
}
|
||||
let needed = target - s.len();
|
||||
let reps = needed.div_ceil(pad.len());
|
||||
let mut out = pad.repeat(reps);
|
||||
out.truncate(needed);
|
||||
let needed = target - s_len;
|
||||
let pad_len = char_len(&pad).max(1);
|
||||
let reps = needed.div_ceil(pad_len);
|
||||
let mut out = take_chars(&pad.repeat(reps), needed);
|
||||
out.push_str(&s);
|
||||
Ok(vm.intern(&out))
|
||||
NativeResult::Ok(vm.intern(&out))
|
||||
}
|
||||
|
||||
pub fn string_pad_end(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let s_len = char_len(&s);
|
||||
let target = if args.len() > 1 {
|
||||
coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref()) as usize
|
||||
} else {
|
||||
s.len()
|
||||
s_len
|
||||
};
|
||||
let pad = if args.len() > 2 { as_string(vm, vm.reg(args[2])) } else { " ".to_string() };
|
||||
if s.len() >= target || pad.is_empty() {
|
||||
return Ok(vm.intern(&s));
|
||||
if s_len >= target || pad.is_empty() {
|
||||
return NativeResult::Ok(vm.intern(&s));
|
||||
}
|
||||
let needed = target - s.len();
|
||||
let reps = needed.div_ceil(pad.len());
|
||||
let needed = target - s_len;
|
||||
let pad_len = char_len(&pad).max(1);
|
||||
let reps = needed.div_ceil(pad_len);
|
||||
let mut out = s;
|
||||
let pad_repeated = pad.repeat(reps);
|
||||
out.push_str(&pad_repeated[..needed]);
|
||||
Ok(vm.intern(&out))
|
||||
out.push_str(&take_chars(&pad.repeat(reps), needed));
|
||||
NativeResult::Ok(vm.intern(&out))
|
||||
}
|
||||
|
||||
pub fn string_starts_with(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s);
|
||||
if args.len() < 2 {
|
||||
return Ok(JsValue::bool(false));
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
let search = as_string(vm, vm.reg(args[1]));
|
||||
let pos = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2]), vm.kernel().string_forge().as_ref()) as usize).min(s.len())
|
||||
(coercion::to_number(vm.reg(args[2]), vm.kernel().string_forge().as_ref()) as usize).min(n)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
Ok(JsValue::bool(s[pos..].starts_with(&search)))
|
||||
NativeResult::Ok(JsValue::bool(s[byte_index_at_char(&s, pos)..].starts_with(&search)))
|
||||
}
|
||||
|
||||
pub fn string_ends_with(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
let n = char_len(&s);
|
||||
if args.len() < 2 {
|
||||
return Ok(JsValue::bool(false));
|
||||
return NativeResult::Ok(JsValue::bool(false));
|
||||
}
|
||||
let search = as_string(vm, vm.reg(args[1]));
|
||||
let end_pos = if args.len() > 2 {
|
||||
(coercion::to_number(vm.reg(args[2]), vm.kernel().string_forge().as_ref()) as usize).min(s.len())
|
||||
(coercion::to_number(vm.reg(args[2]), vm.kernel().string_forge().as_ref()) as usize).min(n)
|
||||
} else {
|
||||
s.len()
|
||||
n
|
||||
};
|
||||
Ok(JsValue::bool(s[..end_pos].ends_with(&search)))
|
||||
NativeResult::Ok(JsValue::bool(s[..byte_index_at_char(&s, end_pos)].ends_with(&search)))
|
||||
}
|
||||
|
||||
pub fn string_split(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
let parts = vec![s.clone()];
|
||||
return Ok(make_string_array(vm, &parts));
|
||||
return NativeResult::Ok(make_string_array(vm, &parts));
|
||||
}
|
||||
let sep_val = vm.reg(args[1]);
|
||||
let limit = if args.len() > 2 {
|
||||
@@ -334,13 +368,14 @@ pub fn string_split(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
let parts = vec![s.clone()];
|
||||
return Ok(make_string_array(vm, &parts));
|
||||
return NativeResult::Ok(make_string_array(vm, &parts));
|
||||
}
|
||||
};
|
||||
let regex = unsafe { &*(fn_ptr as *const regex::Regex) };
|
||||
// SAFETY: fn_ptr holds a Box<regex::Regex> pointer stored by regexp_constructor.
|
||||
let regex = unsafe { &*(fn_ptr.as_ptr() as *const regex::Regex) };
|
||||
let raw: Vec<&str> = regex.split(&s).collect();
|
||||
let parts: Vec<String> = raw.iter().map(|p| p.to_string()).take(limit).collect();
|
||||
return Ok(make_string_array(vm, &parts));
|
||||
return NativeResult::Ok(make_string_array(vm, &parts));
|
||||
}
|
||||
|
||||
let sep = as_string(vm, sep_val);
|
||||
@@ -349,13 +384,13 @@ pub fn string_split(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
} else {
|
||||
s.split(&sep).map(|p| p.to_string()).take(limit).collect()
|
||||
};
|
||||
Ok(make_string_array(vm, &parts))
|
||||
NativeResult::Ok(make_string_array(vm, &parts))
|
||||
}
|
||||
|
||||
pub fn string_replace(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
return Ok(vm.intern(&s));
|
||||
return NativeResult::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() };
|
||||
@@ -365,22 +400,23 @@ pub fn string_replace(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let re = unsafe { &*re_ptr };
|
||||
let fn_ptr = match re.native_fn() {
|
||||
Some(p) => p,
|
||||
None => return Ok(vm.intern(&s)),
|
||||
None => return NativeResult::Ok(vm.intern(&s)),
|
||||
};
|
||||
let regex = unsafe { &*(fn_ptr as *const regex::Regex) };
|
||||
// SAFETY: fn_ptr holds a Box<regex::Regex> pointer stored by regexp_constructor.
|
||||
let regex = unsafe { &*(fn_ptr.as_ptr() as *const regex::Regex) };
|
||||
let result = regex.replace_all(&s, replacement.as_str()).to_string();
|
||||
return Ok(vm.intern(&result));
|
||||
return NativeResult::Ok(vm.intern(&result));
|
||||
}
|
||||
|
||||
let pattern = as_string(vm, pattern_val);
|
||||
let result = s.replacen(&pattern, &replacement, 1);
|
||||
Ok(vm.intern(&result))
|
||||
NativeResult::Ok(vm.intern(&result))
|
||||
}
|
||||
|
||||
pub fn string_match_fn(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
return Ok(JsValue::undefined());
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
let pattern_val = vm.reg(args[1]);
|
||||
|
||||
@@ -389,24 +425,25 @@ pub fn string_match_fn(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let re = unsafe { &*re_ptr };
|
||||
let fn_ptr = match re.native_fn() {
|
||||
Some(p) => p,
|
||||
None => return Ok(JsValue::undefined()),
|
||||
None => return NativeResult::Ok(JsValue::undefined()),
|
||||
};
|
||||
let regex = unsafe { &*(fn_ptr as *const regex::Regex) };
|
||||
// SAFETY: fn_ptr holds a Box<regex::Regex> pointer stored by regexp_constructor.
|
||||
let regex = unsafe { &*(fn_ptr.as_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));
|
||||
return NativeResult::Ok(make_string_array(vm, &matches));
|
||||
}
|
||||
|
||||
let pattern = as_string(vm, pattern_val);
|
||||
if let Some(pos) = s.find(&pattern) {
|
||||
return Ok(make_string_array(vm, &[s[pos..pos + pattern.len()].to_string()]));
|
||||
return NativeResult::Ok(make_string_array(vm, &[s[pos..pos + pattern.len()].to_string()]));
|
||||
}
|
||||
Ok(JsValue::undefined())
|
||||
NativeResult::Ok(JsValue::undefined())
|
||||
}
|
||||
|
||||
pub fn string_search(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
if args.len() < 2 {
|
||||
return Ok(JsValue::int(-1));
|
||||
return NativeResult::Ok(JsValue::int(-1));
|
||||
}
|
||||
let pattern_val = vm.reg(args[1]);
|
||||
|
||||
@@ -415,30 +452,31 @@ pub fn string_search(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let re = unsafe { &*re_ptr };
|
||||
let fn_ptr = match re.native_fn() {
|
||||
Some(p) => p,
|
||||
None => return Ok(JsValue::int(-1)),
|
||||
None => return NativeResult::Ok(JsValue::int(-1)),
|
||||
};
|
||||
let regex = unsafe { &*(fn_ptr as *const regex::Regex) };
|
||||
// SAFETY: fn_ptr holds a Box<regex::Regex> pointer stored by regexp_constructor.
|
||||
let regex = unsafe { &*(fn_ptr.as_ptr() as *const regex::Regex) };
|
||||
if let Some(m) = regex.find(&s) {
|
||||
return Ok(JsValue::int(m.start() as i32));
|
||||
return NativeResult::Ok(JsValue::int(m.start() as i32));
|
||||
}
|
||||
return Ok(JsValue::int(-1));
|
||||
return NativeResult::Ok(JsValue::int(-1));
|
||||
}
|
||||
|
||||
let pattern = as_string(vm, pattern_val);
|
||||
if let Some(pos) = s.find(&pattern) {
|
||||
return Ok(JsValue::int(pos as i32));
|
||||
return NativeResult::Ok(JsValue::int(pos as i32));
|
||||
}
|
||||
Ok(JsValue::int(-1))
|
||||
NativeResult::Ok(JsValue::int(-1))
|
||||
}
|
||||
|
||||
pub fn string_trim_start(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
Ok(vm.intern(s.trim_start()))
|
||||
NativeResult::Ok(vm.intern(s.trim_start()))
|
||||
}
|
||||
|
||||
pub fn string_trim_end(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let s = this_string(vm, args);
|
||||
Ok(vm.intern(s.trim_end()))
|
||||
NativeResult::Ok(vm.intern(s.trim_end()))
|
||||
}
|
||||
|
||||
pub fn string_code_point_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
@@ -450,17 +488,17 @@ pub fn string_code_point_at(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
};
|
||||
let chars: Vec<char> = s.chars().collect();
|
||||
if pos >= chars.len() {
|
||||
return Ok(JsValue::undefined());
|
||||
return NativeResult::Ok(JsValue::undefined());
|
||||
}
|
||||
let c = chars[pos] as u32;
|
||||
if (0xD800..=0xDBFF).contains(&c) && pos + 1 < chars.len() {
|
||||
let next = chars[pos + 1] as u32;
|
||||
if (0xDC00..=0xDFFF).contains(&next) {
|
||||
let cp = 0x10000 + ((c - 0xD800) << 10) + (next - 0xDC00);
|
||||
return Ok(JsValue::int(cp as i32));
|
||||
return NativeResult::Ok(JsValue::int(cp as i32));
|
||||
}
|
||||
}
|
||||
Ok(JsValue::int(c as i32))
|
||||
NativeResult::Ok(JsValue::int(c as i32))
|
||||
}
|
||||
|
||||
pub fn string_normalize(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
@@ -473,13 +511,13 @@ pub fn string_normalize(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
"NFKD" => s.nfkd().collect(),
|
||||
_ => s.nfc().collect(),
|
||||
};
|
||||
Ok(vm.intern(&result))
|
||||
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());
|
||||
return NativeResult::Err(JsValue::undefined());
|
||||
}
|
||||
let pattern_val = vm.reg(args[1]);
|
||||
if is_regexp_obj(pattern_val, vm) {
|
||||
@@ -487,19 +525,20 @@ pub fn string_match_all(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let re = unsafe { &*re_ptr };
|
||||
let fn_ptr = match re.native_fn() {
|
||||
Some(p) => p,
|
||||
None => return Ok(JsValue::undefined()),
|
||||
None => return NativeResult::Ok(JsValue::undefined()),
|
||||
};
|
||||
let regex = unsafe { &*(fn_ptr as *const regex::Regex) };
|
||||
// SAFETY: fn_ptr holds a Box<regex::Regex> pointer stored by regexp_constructor.
|
||||
let regex = unsafe { &*(fn_ptr.as_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));
|
||||
return NativeResult::Ok(make_string_array(vm, &matches));
|
||||
}
|
||||
Ok(JsValue::undefined())
|
||||
NativeResult::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));
|
||||
return NativeResult::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() };
|
||||
@@ -508,13 +547,14 @@ pub fn string_replace_all(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||
let re = unsafe { &*re_ptr };
|
||||
let fn_ptr = match re.native_fn() {
|
||||
Some(p) => p,
|
||||
None => return Ok(vm.intern(&s)),
|
||||
None => return NativeResult::Ok(vm.intern(&s)),
|
||||
};
|
||||
let regex = unsafe { &*(fn_ptr as *const regex::Regex) };
|
||||
// SAFETY: fn_ptr holds a Box<regex::Regex> pointer stored by regexp_constructor.
|
||||
let regex = unsafe { &*(fn_ptr.as_ptr() as *const regex::Regex) };
|
||||
let result = regex.replace_all(&s, replacement.as_str()).to_string();
|
||||
return Ok(vm.intern(&result));
|
||||
return NativeResult::Ok(vm.intern(&result));
|
||||
}
|
||||
let pattern = as_string(vm, pattern_val);
|
||||
let result = s.replace(&pattern, &replacement);
|
||||
Ok(vm.intern(&result))
|
||||
NativeResult::Ok(vm.intern(&result))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user