This repository has been archived on 2026-09-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
OxideJS/crates/oxide_vm/tests/builtins_data_view_tests.rs
T
pjh123 1b9974fe7f 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 / 字节序 / 排序 / 回调值类型断言
2026-08-15 20:04:48 +08:00

202 lines
5.8 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_compiler::compiler::Compiler;
use oxide_types::value::JsValue;
use oxide_vm::vm::Vm;
fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
let allocator = oxide_parser::Allocator::default();
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
vm.run(&module)
}
fn to_str(vm: &Vm, val: JsValue) -> String {
vm.lookup_str(val).unwrap_or_default()
}
#[test]
fn data_view_global_and_methods_exist() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"typeof DataView === 'function' && typeof DataView.prototype.getInt32 === 'function'",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_properties_reference_buffer_offset_and_length() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(16); var dv = new DataView(buf, 4, 8); \
dv.buffer === buf && dv.byteOffset === 4 && dv.byteLength === 8",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_set_get_int32_big_endian() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(16); var dv = new DataView(buf); \
dv.setInt32(0, 305419896, false); dv.getInt32(0, false)",
)
.unwrap();
assert_eq!(result.as_int(), 305419896);
}
#[test]
fn data_view_set_get_int32_little_endian_exposes_first_byte() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(16); var dv = new DataView(buf); \
dv.setInt32(0, 305419896, true); dv.getUint8(0)",
)
.unwrap();
assert_eq!(result.as_int(), 120);
}
#[test]
fn data_view_set_get_uint16_and_int8() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(4); var dv = new DataView(buf); \
var neg = -1; dv.setUint16(0, 65535, false); dv.setInt8(2, neg); \
dv.getUint16(0, false) === 65535 && dv.getInt8(2) === -1",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_float64_roundtrip() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(8); var dv = new DataView(buf); \
dv.setFloat64(0, 3.5, true); dv.getFloat64(0, true)",
)
.unwrap();
assert_eq!(result.as_double(), 3.5);
}
#[test]
fn data_view_offset_view_writes_into_underlying_buffer() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(16); var base = new DataView(buf); var dv = new DataView(buf, 4, 8); \
dv.setUint8(0, 77); base.getUint8(4)",
)
.unwrap();
assert_eq!(result.as_int(), 77);
}
#[test]
fn data_view_is_array_buffer_view() {
let mut vm = Vm::new();
let result = eval(&mut vm, "var dv = new DataView(new ArrayBuffer(1)); ArrayBuffer.isView(dv)").unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_rejects_non_array_buffer() {
let mut vm = Vm::new();
let result = eval(&mut vm, "try { new DataView({}) } catch (e) { e instanceof TypeError }").unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_rejects_out_of_bounds_access() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"try { var dv = new DataView(new ArrayBuffer(4)); dv.getInt32(2); } catch (e) { e instanceof RangeError }",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_to_string_is_identifiable() {
let mut vm = Vm::new();
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());
}