Files
OxideJS-New/crates/oxide_builtins/src/global.rs
T

86 lines
3.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use oxide_runtime_api::{NativeResult, VmHost};
use oxide_types::value::JsValue;
mod annex_b;
mod uri;
/// 全局函数模块:聚合 Annex B 的 `escape`/`unescape` 与 URI 处理函数
/// (`encodeURI`/`decodeURI`/`encodeURIComponent`/`decodeURIComponent`)。
pub use annex_b::{js_escape, js_unescape};
/// URI 编解码全局函数(`encodeURI`/`decodeURI` 等)。
pub use uri::{decode_uri, decode_uri_component, encode_uri, encode_uri_component};
/// `isNaN(x)`:ToNumber 后检查是否为 NaN(隐式类型转换)。
///
/// ToNumber 可抛:Symbol 抛 TypeError,对象 ToPrimitive 触发 valueOf/toString
/// 抛出的原生异常原样传播。
pub fn global_is_nan<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
let n = if args.len() < 2 {
f64::NAN
} else {
match oxide_runtime_api::to_number_full(vm.reg(args[1]), vm) {
Ok(n) => n,
Err(_) => {
if let Some(exc) = vm.take_uncaught_value() {
return NativeResult::Err(exc);
}
return NativeResult::Err(crate::error::create_type_error(vm, "Cannot convert value to a number"));
}
}
};
NativeResult::Ok(JsValue::bool(n.is_nan()))
}
/// `isFinite(x)`:ToNumber 后检查是否为有限数(隐式类型转换)。
///
/// ToNumber 可抛:Symbol 抛 TypeError,对象 ToPrimitive 触发 valueOf/toString
/// 抛出的原生异常原样传播。
pub fn global_is_finite<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
let n = if args.len() < 2 {
f64::NAN
} else {
match oxide_runtime_api::to_number_full(vm.reg(args[1]), vm) {
Ok(n) => n,
Err(_) => {
if let Some(exc) = vm.take_uncaught_value() {
return NativeResult::Err(exc);
}
return NativeResult::Err(crate::error::create_type_error(vm, "Cannot convert value to a number"));
}
}
};
NativeResult::Ok(JsValue::bool(n.is_finite()))
}
/// `escape`/`unescape` 的字符串参数:按规范 `? ToString` 完整转换,
/// 取 UTF-16 单元序列(不 lossy,孤立 surrogate 保真)。
///
/// 对象经 ToPrimitive(string hint) 强制转换,Symbol 抛 TypeError,对象方法
/// 抛出的原生异常原样传播;缺省参数按 "undefined" 处理。
fn units_arg_full<H: VmHost>(vm: &mut H, args: &[u8]) -> Result<Vec<u16>, JsValue> {
if args.len() > 1 {
match oxide_runtime_api::to_units_full(vm.reg(args[1]), vm) {
Ok(u) => Ok(u),
Err(_) => {
if let Some(exc) = vm.take_uncaught_value() {
return Err(exc);
}
Err(crate::error::create_type_error(vm, "Cannot convert value to a string"))
}
}
} else {
Ok("undefined".encode_utf16().collect())
}
}
/// 解析两位十六进制单元为字节:逐位严格匹配十六进制数字,不带符号位
/// (`from_str_radix` 会接受 `+1`/`-1`,`%+1` 这类序列按规范须判非法)。
fn parse_hex_u8(slice: &[u8]) -> Option<u8> {
let digit = |c: u8| match c {
b'0'..=b'9' => Some(c - b'0'),
b'a'..=b'f' => Some(c - b'a' + 10),
b'A'..=b'F' => Some(c - b'A' + 10),
_ => None,
};
Some(digit(slice[0])? * 16 + digit(slice[1])?)
}