Files
OxideJS-New/crates/oxide_builtins/tests/builtin_overflow_boundary_tests.rs
T

121 lines
4.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 std::sync::Arc;
use oxide_compiler::compiler::Compiler;
use oxide_compiler::DefaultCompilerService;
use oxide_types::value::JsValue;
use oxide_vm::vm::Vm;
fn eval(source: &str) -> Result<(Vm, 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))?;
let mut vm = Vm::new();
vm.set_compiler_service(Arc::new(DefaultCompilerService));
let result = vm.run(&Arc::new(module))?;
Ok((vm, result))
}
fn eval_str(source: &str) -> Result<String, String> {
let (vm, result) = eval(source)?;
vm.lookup_str(result)
.ok_or_else(|| "completion value is not a string".to_string())
}
fn assert_nan(source: &str) {
let (_vm, result) = eval(source).unwrap();
assert!(result.is_double() && result.as_double().is_nan(), "expected NaN from {source}");
}
// -Infinity 结束位:ToIntegerOrInfinity 不截断,负无穷归 0,slice 得空 buffer。
#[test]
fn array_buffer_slice_negative_infinity_end() {
let (_vm, result) = eval("new ArrayBuffer(8).slice(2, -Infinity).byteLength").unwrap();
assert_eq!(result.as_int(), 0);
}
// -Infinity 结束位:copyWithin 相对结束位归 0,区间为空,元素不变。
#[test]
fn typed_array_copy_within_negative_infinity_end() {
let s = eval_str("new Uint8Array([1, 2, 3, 4, 5]).copyWithin(0, 1, -Infinity).join(',')").unwrap();
assert_eq!(s, "1,2,3,4,5");
}
// 无穷年份入参:MakeDay 非有限分量得 NaN,日期置 Invalid。
#[test]
fn set_full_year_infinity_is_nan() {
assert_nan("new Date(2016, 6, 7).setFullYear(Infinity)");
}
// 无穷月/日入参:Date.UTC 走 MakeDay,非有限分量得 NaN。
#[test]
fn date_utc_infinite_fields_are_nan() {
assert_nan("Date.UTC(0, Infinity)");
assert_nan("Date.UTC(0, 0, -Infinity)");
}
// 毫秒分量 1e300:MakeTime 组合越界,整体得 NaN(不得溢出)。
#[test]
fn set_hours_huge_millisecond_is_nan() {
assert_nan("new Date(2016, 6, 7, 12, 30, 45, 99).setHours(0, 0, 0, 1e300)");
}
// at(-1e300):负无穷索引越界,得 undefined 而非溢出。
#[test]
fn typed_array_at_negative_infinity() {
let (_vm, result) = eval("new Uint8Array([1, 2, 3]).at(-1e300)").unwrap();
assert!(result.is_undefined());
}
// lastIndexOf(2, -Infinity):负无穷起点越界,得 -1 而非下溢。
#[test]
fn typed_array_last_index_of_negative_infinity() {
let (_vm, result) = eval("new Int8Array([7, 2, 9]).lastIndexOf(2, -Infinity)").unwrap();
assert_eq!(result.as_int(), -1);
}
// 日分量 0:rollover 到上一月月末(引擎内部自比,免时区依赖)。
#[test]
fn set_full_year_day_zero_rolls_to_previous_month() {
let s = eval_str("String((function() { var d = new Date(2016, 6, 7, 11, 36, 23, 2); return d.setFullYear(2016, 6, 0) === new Date(2016, 5, 30, 11, 36, 23, 2).getTime(); })())").unwrap();
assert_eq!(s, "true");
}
// 日分量 0 经 setMonth 同样 rollover。
#[test]
fn set_month_day_zero_rolls_to_previous_month() {
let s = eval_str("String((function() { var d = new Date(2016, 6, 7, 11, 36, 23, 2); return d.setMonth(6, 0) === new Date(2016, 5, 30, 11, 36, 23, 2).getTime(); })())").unwrap();
assert_eq!(s, "true");
}
// 无效日期 this 值:setFullYear 不早退,按 +0 基准得 2016-01-01。
#[test]
fn set_full_year_on_invalid_date_uses_epoch() {
let s = eval_str("String((function() { var d = new Date(NaN); return d.setFullYear(2016) === new Date(2016, 0, 1).getTime(); })())").unwrap();
assert_eq!(s, "true");
}
// 有限巨负起点:截断饱和成 isize::MIN 后归一化到 0,debug 构建不得取负溢出。
#[test]
fn typed_array_fill_finite_negative_huge_start() {
let s = eval_str("new Uint8Array(4).fill(0, -1e300).join(',')").unwrap();
assert_eq!(s, "0,0,0,0");
}
// 月份分量 ±Infinity/有限巨值:构造器与 setter 均直接 NaN(debug 构建不得整型溢出)。
#[test]
fn date_constructor_huge_month_is_nan() {
assert_nan("new Date(2020, Infinity, 1).getTime()");
assert_nan("new Date(2020, -Infinity, 1).getTime()");
assert_nan("new Date(2020, 1e300, 1).getTime()");
assert_nan("new Date(2020, 0, 1).setMonth(1e300)");
}
// 年分量超 TimeClip 包络:构造器组合结果归 NaN;包络内邻近组合不损伤
// (valueOf 直接读槽位,不经 chrono 年份上限,可钉超 262142 年存储值)。
#[test]
fn date_constructor_out_of_envelope_year_is_nan() {
assert_nan("new Date(275760, 8, 13, 1).getTime()");
let (_vm, result) = eval("new Date(275759, 11, 31).valueOf()").unwrap();
assert!(result.is_double() && result.as_double().is_finite(), "包络内组合应得有限时间戳");
}