mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-26 11:41:13 +08:00
fix: 类型化数组索引助手恢复 BigInt 实参抛 TypeError 语义
This commit is contained in:
@@ -35,15 +35,6 @@ fn range_error<H: VmHost>(vm: &mut H, msg: &str) -> JsValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_index<H: VmHost>(vm: &mut H, value: JsValue, msg: &str) -> Result<usize, JsValue> {
|
fn to_index<H: VmHost>(vm: &mut H, value: JsValue, msg: &str) -> Result<usize, JsValue> {
|
||||||
// ToIndex 的 BigInt 面:整数原语截断即自身,负值或超 2^53-1 抛
|
|
||||||
// RangeError(与数值臂同消息),无 NaN 概念。
|
|
||||||
if value.is_bigint() {
|
|
||||||
let b = vm.bigint_value(value);
|
|
||||||
if *b < BigInt::from(0) || *b > BigInt::from(9_007_199_254_740_991u64) {
|
|
||||||
return Err(range_error(vm, msg));
|
|
||||||
}
|
|
||||||
return Ok(b.to_usize().unwrap_or(0));
|
|
||||||
}
|
|
||||||
let n = match vm.coerce_number_bounded(value) {
|
let n = match vm.coerce_number_bounded(value) {
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(e) => return Err(crate::iterator::engine_error(vm, &e)),
|
Err(e) => return Err(crate::iterator::engine_error(vm, &e)),
|
||||||
@@ -60,27 +51,19 @@ fn to_index<H: VmHost>(vm: &mut H, value: JsValue, msg: &str) -> Result<usize, J
|
|||||||
/// 按 ToIntegerOrInfinity 语义把索引归一化到 `[0, len]`(越界夹取);符号等不可
|
/// 按 ToIntegerOrInfinity 语义把索引归一化到 `[0, len]`(越界夹取);符号等不可
|
||||||
/// 转换值透传异常。
|
/// 转换值透传异常。
|
||||||
fn normalize_index<H: VmHost>(vm: &mut H, value: JsValue, len: usize) -> Result<usize, JsValue> {
|
fn normalize_index<H: VmHost>(vm: &mut H, value: JsValue, len: usize) -> Result<usize, JsValue> {
|
||||||
// BigInt 面:ToIntegerOrInfinity 对整数原语即截断自身(无 NaN/±Infinity 臂),
|
let n = match vm.coerce_number_bounded(value) {
|
||||||
// 超 isize 域饱和到对应端点后走同一负/正夹取尾段。
|
Ok(n) => n,
|
||||||
let int: isize = if value.is_bigint() {
|
Err(e) => return Err(crate::iterator::engine_error(vm, &e)),
|
||||||
let b = vm.bigint_value(value);
|
|
||||||
b.to_isize()
|
|
||||||
.unwrap_or(if *b < BigInt::from(0) { isize::MIN } else { isize::MAX })
|
|
||||||
} else {
|
|
||||||
let n = match vm.coerce_number_bounded(value) {
|
|
||||||
Ok(n) => n,
|
|
||||||
Err(e) => return Err(crate::iterator::engine_error(vm, &e)),
|
|
||||||
};
|
|
||||||
if n.is_nan() {
|
|
||||||
return Ok(0);
|
|
||||||
}
|
|
||||||
// ToIntegerOrInfinity:±Infinity 不截断,负无穷归 0、正无穷归 len,
|
|
||||||
// 避免饱和成 isize::MIN 后取负溢出。
|
|
||||||
if n.is_infinite() {
|
|
||||||
return Ok(if n < 0.0 { 0 } else { len });
|
|
||||||
}
|
|
||||||
n.trunc() as isize
|
|
||||||
};
|
};
|
||||||
|
if n.is_nan() {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
// ToIntegerOrInfinity:±Infinity 不截断,负无穷归 0、正无穷归 len,
|
||||||
|
// 避免饱和成 isize::MIN 后取负溢出。
|
||||||
|
if n.is_infinite() {
|
||||||
|
return Ok(if n < 0.0 { 0 } else { len });
|
||||||
|
}
|
||||||
|
let int = n.trunc() as isize;
|
||||||
if int < 0 {
|
if int < 0 {
|
||||||
Ok(len.saturating_sub(int.unsigned_abs()))
|
Ok(len.saturating_sub(int.unsigned_abs()))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -278,10 +278,13 @@ fn typed_array_numeric_write_bigint_throws() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn typed_array_constructor_bigint_length() {
|
fn typed_array_constructor_bigint_length() {
|
||||||
let mut vm = Vm::new();
|
let mut vm = Vm::new();
|
||||||
// G6:第一参数 BigInt 按 ToIndex 语义建数组。
|
// 长度参数走 ToIndex:BigInt 实参在 ToNumber 步抛 TypeError,不截断建数组;
|
||||||
|
// 布尔/null 等原语按数值转换语义建数组。
|
||||||
let result = eval(
|
let result = eval(
|
||||||
&mut vm,
|
&mut vm,
|
||||||
"new BigInt64Array(5n).length === 5 && new Int8Array(true).length === 1 && new Int8Array(null).length === 0",
|
"(function () { var t = false; \
|
||||||
|
try { new BigInt64Array(5n); } catch (e) { t = e instanceof TypeError; } \
|
||||||
|
return t && new Int8Array(true).length === 1 && new Int8Array(null).length === 0; })()",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(result.as_bool());
|
assert!(result.as_bool());
|
||||||
|
|||||||
Reference in New Issue
Block a user