fix: BigInt64Array/BigUint64Array 与 DataView BigInt 存取走真 BigInt 语义
TA 元素读写按 kind 分流:BigInt 类型走 ToBigInt(Number 入参抛 TypeError、 写入 mod 2^64 截断、读出为真 BigInt 值),数值类型走 ToNumber 且显式拒绝 BigInt 值;消除 64 位整数经 f64 中转的静默精度丢失。 - runtime_api 新增公共 to_bigint_full / string_to_bigint_full,bigint 构造器 与 asIntN/asUintN 改调公共版消除双实现 - sort/toSorted 默认序对 BigInt 类型按 i64/u64 值比较;reverse/copyWithin/ filter/toReversed/with 消除无谓数值中转 - 构造器第一参数非对象统一走 ToIndex(bool/null/BigInt/字符串),Symbol 抛 TypeError - DataView get/setBigInt64/getBigUint64 返回 BigInt 值、入参按 ToBigInt 校验 - 测试:精度往返 / TypeError / mod 2^64 / 字节序 / 排序 / 回调值类型断言
This commit is contained in:
@@ -128,3 +128,74 @@ fn data_view_to_string_is_identifiable() {
|
||||
let result = eval(&mut vm, "var dv = new DataView(new ArrayBuffer(1)); dv.toString()").unwrap();
|
||||
assert_eq!(to_str(&vm, result), "[object DataView]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_view_get_big_int64_returns_bigint() {
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(&mut vm, "new DataView(new ArrayBuffer(8)).getBigInt64(0)").unwrap();
|
||||
assert!(result.is_bigint());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_view_set_big_int64_with_number_throws() {
|
||||
let mut vm = Vm::new();
|
||||
// ToBigInt 语义:Number 入参抛 TypeError。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"try { new DataView(new ArrayBuffer(8)).setBigInt64(0, 1); false } catch (e) { e instanceof TypeError }",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_view_big_int64_precision_roundtrip() {
|
||||
let mut vm = Vm::new();
|
||||
// 2^63-1(i64::MAX)超出 f64 精确范围,真 BigInt 语义读回必须原值。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var dv = new DataView(new ArrayBuffer(8)); \
|
||||
dv.setBigInt64(0, 9223372036854775807n); dv.getBigInt64(0) === 9223372036854775807n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_view_big_uint64_precision_roundtrip() {
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var dv = new DataView(new ArrayBuffer(8)); \
|
||||
dv.setBigUint64(0, 18446744073709551615n, true); dv.getBigUint64(0, true) === 18446744073709551615n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_view_big_int64_little_endian_byte_order() {
|
||||
let mut vm = Vm::new();
|
||||
// 小端写入后首字节为低字节;同一字节序读回原值。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var dv = new DataView(new ArrayBuffer(8)); \
|
||||
dv.setBigInt64(0, 0x0102030405060708n, true); \
|
||||
dv.getUint8(0) === 8 && dv.getBigInt64(0, true) === 0x0102030405060708n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_view_set_big_int64_mod_2_64_truncation() {
|
||||
let mut vm = Vm::new();
|
||||
// 超 64 位值按 mod 2^64 截断写入。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var dv = new DataView(new ArrayBuffer(8)); \
|
||||
dv.setBigInt64(0, 1180591620717411303429n); dv.getBigInt64(0) === 5n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
@@ -122,10 +122,27 @@ fn typed_array_float64_roundtrips() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint_fallback_returns_float() {
|
||||
fn typed_array_bigint_roundtrips_bigint_values() {
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(&mut vm, "var ta = new BigInt64Array(1); ta.fill(42); ta.at(0)").unwrap();
|
||||
assert_eq!(result.as_double(), 42.0);
|
||||
// BigInt64Array 元素读写为真 BigInt 值(非 f64 近似)。
|
||||
let result = eval(&mut vm, "var ta = new BigInt64Array(1); ta.fill(42n); ta.at(0)").unwrap();
|
||||
assert!(result.is_bigint());
|
||||
assert_eq!(vm.bigint_value(result).to_string(), "42");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint_fill_with_number_throws() {
|
||||
let mut vm = Vm::new();
|
||||
// 数值 TA 写 BigInt 值按规范抛 TypeError;BigInt TA 写 Number 同样抛 TypeError。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var ok = true; \
|
||||
try { new BigInt64Array(1).fill(42); ok = false; } catch (e) { ok = e instanceof TypeError; } \
|
||||
try { new Int8Array(1)[0] = 1n; ok = ok && false; } catch (e) { ok = ok && e instanceof TypeError; } \
|
||||
ok",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -190,3 +207,124 @@ fn typed_array_reflect_set_writes_to_receiver() {
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint64_precision_roundtrip() {
|
||||
let mut vm = Vm::new();
|
||||
// 2^63-1(i64::MAX)超出 f64 精确范围:f64 会舍入为 2^63,真 BigInt 存储读回必须原值。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var a = new BigInt64Array(1); a[0] = 9223372036854775807n; a[0] === 9223372036854775807n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint64_write_overflow_wraps() {
|
||||
let mut vm = Vm::new();
|
||||
// 2^63 写入 i64 槽按二进制补码回读为 -2^63。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var a = new BigInt64Array(1); a[0] = 9223372036854775808n; a[0] === -9223372036854775808n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_biguint64_precision_roundtrip() {
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var a = new BigUint64Array(1); a[0] = 18446744073709551615n; a[0] === 18446744073709551615n && a[0] > Number.MAX_SAFE_INTEGER",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint_negative_roundtrip() {
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(&mut vm, "var a = new BigInt64Array(1); a[0] = -1n; a[0] === -1n").unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint_mod_2_64_truncation() {
|
||||
let mut vm = Vm::new();
|
||||
// 写入按 mod 2^64 截断:2^70 + 5 的低 64 位为 5。
|
||||
let result = eval(&mut vm, "var a = new BigInt64Array(1); a[0] = 1180591620717411303429n; a[0] === 5n").unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint_write_number_throws() {
|
||||
let mut vm = Vm::new();
|
||||
let result =
|
||||
eval(&mut vm, "try { new BigInt64Array(1)[0] = 1; false } catch (e) { e instanceof TypeError }").unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_numeric_write_bigint_throws() {
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(&mut vm, "try { new Int8Array(1)[0] = 1n; false } catch (e) { e instanceof TypeError }").unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_constructor_bigint_length() {
|
||||
let mut vm = Vm::new();
|
||||
// G6:第一参数 BigInt 按 ToIndex 语义建数组。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"new BigInt64Array(5n).length === 5 && new Int8Array(true).length === 1 && new Int8Array(null).length === 0",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint_from_array_and_set() {
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var a = new BigInt64Array([1n, 2n]); \
|
||||
a.length === 2 && a[0] === 1n && a[1] === 2n && \
|
||||
BigInt64Array.from([3n]).at(0) === 3n && \
|
||||
(function () { var t = new BigInt64Array(2); t.set([9n, 8n]); return t[0] === 9n && t[1] === 8n; })()",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint_sort_uses_bigint_compare() {
|
||||
let mut vm = Vm::new();
|
||||
// 超出 f64 精度的 BigInt 排序仍按 BigInt 值升序(f64 中转会静默错序)。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var a = new BigInt64Array([9223372036854775807n, -1n, 0n, 1n]); a.sort(); \
|
||||
a[0] === -1n && a[1] === 0n && a[2] === 1n && a[3] === 9223372036854775807n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_array_bigint_methods_receive_bigint_values() {
|
||||
let mut vm = Vm::new();
|
||||
// map/filter/reduce 回调收到的元素是真 BigInt;map 结果按元素类型转换回写。
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var a = new BigInt64Array([1n, 2n]); \
|
||||
var seen = []; \
|
||||
var m = a.map(function (v) { seen.push(typeof v); return v + 1n; }); \
|
||||
seen[0] === 'bigint' && seen[1] === 'bigint' && m[0] === 2n && m[1] === 3n && \
|
||||
a.filter(function (v) { return v > 1n; }).length === 1 && \
|
||||
a.reduce(function (acc, v) { return acc + v; }, 0n) === 3n",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(result.as_bool());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user