From 7705a9a60020879e5a0740a7f5e1493264e68c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E7=89=B9=E6=AF=8F=E7=BE=8A=E9=98=9F?= Date: Sat, 27 Jun 2026 15:28:46 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E5=A4=8D=20Array.slice=20?= =?UTF-8?q?=E8=B4=9F=E6=95=B0=E7=B4=A2=E5=BC=95=E5=A4=84=E7=90=86=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20Array=20push/pop/shift/unshift/slice=20?= =?UTF-8?q?=E8=BE=B9=E7=95=8C=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_builtins/src/array.rs | 14 ++-- .../tests/array_boundary_tests.rs | 66 +++++++++++++++++++ 2 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 crates/oxide_builtins/tests/array_boundary_tests.rs diff --git a/crates/oxide_builtins/src/array.rs b/crates/oxide_builtins/src/array.rs index 608dac5..aa4fe85 100644 --- a/crates/oxide_builtins/src/array.rs +++ b/crates/oxide_builtins/src/array.rs @@ -193,19 +193,19 @@ pub fn array_slice(vm: &mut H, args: &[u8]) -> NativeResult { builtins_debug!("Array.prototype.slice called with {} args", args.len()); let arr_ptr = array_ptr!(vm, args); let arr = unsafe { &*arr_ptr }; - let n = arr.prop_count() as usize; - let start = if args.len() > 1 { - (vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as i32) as usize + let n = arr.prop_count() as isize; + let rel_start = if args.len() > 1 { + oxide_runtime_api::to_integer_or_infinity(vm.reg(args[1])) as isize } else { 0 }; - let end = if args.len() > 2 { - (vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as i32) as usize + let rel_end = if args.len() > 2 { + oxide_runtime_api::to_integer_or_infinity(vm.reg(args[2])) as isize } else { n }; - let start = start.min(n); - let end = end.min(n); + let start = if rel_start < 0 { (n + rel_start).max(0) } else { rel_start.min(n) } as usize; + let end = if rel_end < 0 { (n + rel_end).max(0) } else { rel_end.min(n) } as usize; let count = end.saturating_sub(start); let new_arr = create_new_array(vm, count); diff --git a/crates/oxide_builtins/tests/array_boundary_tests.rs b/crates/oxide_builtins/tests/array_boundary_tests.rs new file mode 100644 index 0000000..94f6b37 --- /dev/null +++ b/crates/oxide_builtins/tests/array_boundary_tests.rs @@ -0,0 +1,66 @@ +use oxide_compiler::compiler::Compiler; +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(); + let result = vm.run(&module)?; + Ok((vm, result)) +} + +#[test] +fn test_push_returns_new_length() { + let (_vm, result) = eval("var a = [1, 2]; a.push(3)").unwrap(); + assert_eq!(result.as_int(), 3); +} + +#[test] +fn test_push_multiple_args() { + let (_vm, result) = eval("var a = [1]; a.push(2, 3)").unwrap(); + assert_eq!(result.as_int(), 3); +} + +#[test] +fn test_pop_empty_returns_undefined() { + let (_vm, result) = eval("[].pop()").unwrap(); + assert!(result.is_undefined()); +} + +#[test] +fn test_pop_returns_last_element() { + let (_vm, result) = eval("[1, 2, 3].pop()").unwrap(); + assert_eq!(result.as_int(), 3); +} + +#[test] +fn test_shift_empty_returns_undefined() { + let (_vm, result) = eval("[].shift()").unwrap(); + assert!(result.is_undefined()); +} + +#[test] +fn test_shift_returns_first_element() { + let (_vm, result) = eval("[1, 2, 3].shift()").unwrap(); + assert_eq!(result.as_int(), 1); +} + +#[test] +fn test_unshift_returns_new_length() { + let (_vm, result) = eval("var a = [3, 4]; a.unshift(1, 2)").unwrap(); + assert_eq!(result.as_int(), 4); +} + +#[test] +fn test_slice_negative_start() { + let (_vm, result) = eval("[1, 2, 3, 4].slice(-2).length").unwrap(); + assert_eq!(result.as_int(), 2); +} + +#[test] +fn test_slice_negative_end() { + let (_vm, result) = eval("[1, 2, 3].slice(0, -1).length").unwrap(); + assert_eq!(result.as_int(), 2); +}