From 722696dd850d57cd7ba9e8b35e0057d0eff3dc3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20Sj=C3=B6green?= Date: Fri, 3 Jan 2025 17:47:08 +0100 Subject: [PATCH] feat(test262): Implement the `detachArrayBuffer` test harness function --- nova_cli/src/helper.rs | 46 ++++++++++++++++++- .../src/ecmascript/builtins/array_buffer.rs | 1 + .../array_buffer/abstract_operations.rs | 6 +-- tests/nova-harness.js | 3 +- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/nova_cli/src/helper.rs b/nova_cli/src/helper.rs index 145e96c9c..4f874f673 100644 --- a/nova_cli/src/helper.rs +++ b/nova_cli/src/helper.rs @@ -1,5 +1,7 @@ use nova_vm::ecmascript::{ - builtins::{create_builtin_function, ArgumentsList, Behaviour, BuiltinFunctionArgs}, + builtins::{ + array_buffer, create_builtin_function, ArgumentsList, Behaviour, BuiltinFunctionArgs, + }, execution::{agent::ExceptionType, Agent, JsResult}, types::{InternalMethods, IntoValue, Object, PropertyDescriptor, PropertyKey, String, Value}, }; @@ -22,6 +24,7 @@ pub fn initialize_global_object(agent: &mut Agent, global: Object, mut gc: GcSco } Ok(Value::Undefined) } + // 'readTextFile' function fn read_text_file( agent: &mut Agent, @@ -48,6 +51,25 @@ pub fn initialize_global_object(agent: &mut Agent, global: Object, mut gc: GcSco .map_err(|e| agent.throw_exception(ExceptionType::Error, e.to_string(), gc.nogc()))?; Ok(String::from_string(agent, file, gc.nogc()).into_value()) } + + // `detachArrayBuffer` function + fn detach_array_buffer( + agent: &mut Agent, + _this: Value, + args: ArgumentsList, + gc: GcScope<'_, '_>, + ) -> JsResult { + let Value::ArrayBuffer(array_buffer) = args.get(0) else { + return Err(agent.throw_exception_with_static_message( + ExceptionType::Error, + "Cannot detach non ArrayBuffer argument", + gc.nogc(), + )); + }; + array_buffer::detach_array_buffer(agent, array_buffer, None); + Ok(Value::Undefined) + } + let function = create_builtin_function( agent, Behaviour::Regular(print), @@ -91,6 +113,28 @@ pub fn initialize_global_object(agent: &mut Agent, global: Object, mut gc: GcSco gc.reborrow(), ) .unwrap(); + + let function = create_builtin_function( + agent, + Behaviour::Regular(detach_array_buffer), + BuiltinFunctionArgs::new(1, "detachArrayBuffer", agent.current_realm_id()), + gc.nogc(), + ); + let property_key = PropertyKey::from_static_str(agent, "detachArrayBuffer", gc.nogc()).unbind(); + global + .internal_define_own_property( + agent, + property_key, + PropertyDescriptor { + value: Some(function.into_value()), + writable: Some(true), + enumerable: Some(false), + configurable: Some(true), + ..Default::default() + }, + gc.reborrow(), + ) + .unwrap(); } /// Exit the program with parse errors. diff --git a/nova_vm/src/ecmascript/builtins/array_buffer.rs b/nova_vm/src/ecmascript/builtins/array_buffer.rs index 437fd8bbf..c4c6c3399 100644 --- a/nova_vm/src/ecmascript/builtins/array_buffer.rs +++ b/nova_vm/src/ecmascript/builtins/array_buffer.rs @@ -19,6 +19,7 @@ use crate::{ }, }; +pub use abstract_operations::detach_array_buffer; pub(crate) use abstract_operations::{ allocate_array_buffer, array_buffer_byte_length, clone_array_buffer, get_value_from_buffer, is_detached_buffer, is_fixed_length_array_buffer, set_value_in_buffer, Ordering, diff --git a/nova_vm/src/ecmascript/builtins/array_buffer/abstract_operations.rs b/nova_vm/src/ecmascript/builtins/array_buffer/abstract_operations.rs index a9d8b8fc5..c8ae5ce40 100644 --- a/nova_vm/src/ecmascript/builtins/array_buffer/abstract_operations.rs +++ b/nova_vm/src/ecmascript/builtins/array_buffer/abstract_operations.rs @@ -118,11 +118,7 @@ pub(crate) fn is_detached_buffer(agent: &Agent, array_buffer: ArrayBuffer) -> bo /// The abstract operation DetachArrayBuffer takes argument *arrayBuffer* (an /// ArrayBuffer) and optional argument *key* (anything) and returns either a /// normal completion containing UNUSED or a throw completion. -pub(crate) fn detach_array_buffer( - array_buffer: ArrayBuffer, - agent: &mut Agent, - _key: Option, -) { +pub fn detach_array_buffer(agent: &mut Agent, array_buffer: ArrayBuffer, _key: Option) { // 1. Assert: IsSharedArrayBuffer(arrayBuffer) is false. // TODO: SharedArrayBuffer that we can even take here. // 2. If key is not present, set key to undefined. diff --git a/tests/nova-harness.js b/tests/nova-harness.js index edeb6ea30..7d29b6528 100644 --- a/tests/nova-harness.js +++ b/tests/nova-harness.js @@ -17,5 +17,6 @@ // ES2020). globalThis.$262 = { - global: globalThis + global: globalThis, + detachArrayBuffer: detachArrayBuffer, };