feat: 支持 to_string 与错误栈

This commit is contained in:
爱特每羊队
2026-06-08 14:52:44 +08:00
parent 3880882fda
commit a6e448e326
12 changed files with 233 additions and 0 deletions
+28
View File
@@ -116,3 +116,31 @@ pub fn eval_error_constructor(vm: &mut Vm, args: &[u8]) -> NativeResult {
let proto_ptr = P::as_ptr(&vm.kernel().builtin_world().eval_error_proto) as *mut JsObject;
Ok(create_error_object(vm, proto_ptr, "EvalError", &msg))
}
pub fn error_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
let this_val = vm.reg(args[0]);
let (name, msg) = if this_val.is_object() {
let obj = unsafe { &*this_val.as_js_object_ptr() };
let name_val = obj.hash_props_vec().and_then(|v| v.first()).map(|b| **b).unwrap_or(JsValue::undefined());
let msg_val = obj.hash_props_vec().and_then(|v| v.get(1)).map(|b| **b).unwrap_or(JsValue::undefined());
(vm.lookup_str(name_val).unwrap_or_else(|| "Error".to_string()),
vm.lookup_str(msg_val).unwrap_or_default())
} else {
("Error".to_string(), String::new())
};
let result = if msg.is_empty() { name } else { format!("{}: {}", name, msg) };
let si = vm.kernel().string_forge().intern(&result).0;
Ok(JsValue::string(si, 0))
}
pub fn error_stack_getter(vm: &mut Vm, _args: &[u8]) -> NativeResult {
let mut lines = vec![];
for frame in vm.frames.iter().rev() {
let func_name = vm.kernel().string_forge().lookup(frame.function_name).unwrap_or_else(|| "<anonymous>".to_string());
lines.push(format!(" at {} (native)", func_name));
}
lines.push(" at <anonymous> (native)".to_string());
let result = lines.join("\n");
let si = vm.kernel().string_forge().intern(&result).0;
Ok(JsValue::string(si, 0))
}
+11
View File
@@ -158,3 +158,14 @@ pub fn function_bind(vm: &mut Vm, args: &[u8]) -> NativeResult {
Ok(JsValue::from_js_object(wrapper))
}
pub fn function_to_string(vm: &mut Vm, args: &[u8]) -> NativeResult {
let name = vm.kernel().string_forge().lookup(vm.reg(args[0]).as_string_index()).unwrap_or_default();
let result = if name.is_empty() {
"function () { [native code] }".to_string()
} else {
format!("function {}() {{ [native code] }}", name)
};
let si = vm.kernel().string_forge().intern(&result).0;
Ok(JsValue::string(si, 0))
}
+47
View File
@@ -167,3 +167,50 @@ pub fn number_to_fixed(vm: &mut Vm, args: &[u8]) -> NativeResult {
let formatted = format!("{:.digits$}", n);
Ok(vm.intern(&formatted))
}
pub fn number_is_integer(vm: &mut Vm, args: &[u8]) -> NativeResult {
let val = vm.reg(if args.len() > 1 { args[1] } else { args[0] });
let n = coercion::to_number(val, vm.kernel().string_forge().as_ref());
Ok(JsValue::bool(n.trunc() == n && n.is_finite()))
}
pub fn number_is_safe_integer(vm: &mut Vm, args: &[u8]) -> NativeResult {
let val = vm.reg(if args.len() > 1 { args[1] } else { args[0] });
let n = coercion::to_number(val, vm.kernel().string_forge().as_ref());
let safe = n.trunc() == n && n.is_finite() && n >= -9007199254740991i64 as f64 && n <= 9007199254740991i64 as f64;
Ok(JsValue::bool(safe))
}
pub fn number_to_exponential(vm: &mut Vm, args: &[u8]) -> NativeResult {
let n = coercion::to_number(vm.reg(args[0]), vm.kernel().string_forge().as_ref());
let digits = if args.len() > 1 {
coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref()) as usize
} else { 0usize }.min(100);
if n.is_nan() { return Ok(vm.intern("NaN")); }
if n.is_infinite() {
return Ok(vm.intern(if n.is_sign_positive() { "Infinity" } else { "-Infinity" }));
}
let formatted = format!("{:.digits$e}", n);
Ok(vm.intern(&formatted))
}
pub fn number_to_precision(vm: &mut Vm, args: &[u8]) -> NativeResult {
let n = coercion::to_number(vm.reg(args[0]), vm.kernel().string_forge().as_ref());
let precision = if args.len() > 1 {
coercion::to_number(vm.reg(args[1]), vm.kernel().string_forge().as_ref()) as usize
} else { 0usize }.min(21);
if n.is_nan() { return Ok(vm.intern("NaN")); }
if n.is_infinite() {
return Ok(vm.intern(if n.is_sign_positive() { "Infinity" } else { "-Infinity" }));
}
let formatted = format!("{:.precision$}", n);
Ok(vm.intern(&formatted))
}
pub fn number_value_of(vm: &mut Vm, args: &[u8]) -> NativeResult {
let this_val = vm.reg(args[0]);
if this_val.is_int() || this_val.is_double() {
return Ok(this_val);
}
Ok(JsValue::float(f64::NAN))
}