From 8c882817c0b2e47001737c2b3105978b162f7518 Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 24 Nov 2022 00:51:31 +0000 Subject: [PATCH] `JsArrayBuffer` take method and docs (#2454) This Pull Request is related to the #2058 and the discussion in the discord chat. It changes the following: - Adds a `take` method to `JsArrayBuffer` - Builds out `JsArrayBuffer` docs - Adds a `JsArrayBuffer::take()` example to `jsarraybuffer.rs` in `boa_examples` --- .../src/object/builtins/jsarraybuffer.rs | 97 +++++++++++++++++++ boa_examples/src/bin/jsarraybuffer.rs | 10 ++ 2 files changed, 107 insertions(+) diff --git a/boa_engine/src/object/builtins/jsarraybuffer.rs b/boa_engine/src/object/builtins/jsarraybuffer.rs index a24f92170e..abfa187d74 100644 --- a/boa_engine/src/object/builtins/jsarraybuffer.rs +++ b/boa_engine/src/object/builtins/jsarraybuffer.rs @@ -19,6 +19,23 @@ pub struct JsArrayBuffer { impl JsArrayBuffer { /// Create a new array buffer with byte length. + /// + /// ``` + /// # use boa_engine::{ + /// # object::builtins::JsArrayBuffer, + /// # Context, JsResult + /// # }; + /// # fn main() -> JsResult<()> { + /// # // Initialize context + /// # let context = &mut Context::default(); + /// // Creates a blank array buffer of n bytes + /// let array_buffer = JsArrayBuffer::new(4, context)?; + /// + /// assert_eq!(array_buffer.take()?, vec![0_u8; 4]); + /// + /// # Ok(()) + /// # } + /// ``` #[inline] pub fn new(byte_length: usize, context: &mut Context) -> JsResult { let inner = ArrayBuffer::allocate( @@ -40,6 +57,24 @@ impl JsArrayBuffer { /// This uses the passed byte block as the internal storage, it does not clone it! /// /// The `byte_length` will be set to `byte_block.len()`. + /// + /// ``` + /// # use boa_engine::{ + /// # object::builtins::JsArrayBuffer, + /// # Context, JsResult, + /// # }; + /// # fn main() -> JsResult<()> { + /// # // Initialize context + /// # let context = &mut Context::default(); + /// + /// // Create a buffer from a chunk of data + /// let data_block: Vec = (0..5).collect(); + /// let array_buffer = JsArrayBuffer::from_byte_block(data_block, context)?; + /// + /// assert_eq!(array_buffer.take()?, (0..5).collect::>()); + /// # Ok(()) + /// # } + /// ``` #[inline] pub fn from_byte_block(byte_block: Vec, context: &mut Context) -> JsResult { let byte_length = byte_block.len(); @@ -92,6 +127,26 @@ impl JsArrayBuffer { } /// Returns the byte length of the array buffer. + /// + /// ``` + /// # use boa_engine::{ + /// # object::builtins::JsArrayBuffer, + /// # Context, JsResult, + /// # }; + /// # fn main() -> JsResult<()> { + /// # // Initialize context + /// # let context = &mut Context::default(); + /// // Create a buffer from a chunk of data + /// let data_block: Vec = (0..5).collect(); + /// let array_buffer = JsArrayBuffer::from_byte_block(data_block, context)?; + /// + /// // Take the inner buffer + /// let buffer_length = array_buffer.byte_length(context); + /// + /// assert_eq!(buffer_length, 5); + /// # Ok(()) + /// # } + /// ``` #[inline] pub fn byte_length(&self, context: &mut Context) -> usize { ArrayBuffer::get_byte_length(&self.inner.clone().into(), &[], context) @@ -99,6 +154,48 @@ impl JsArrayBuffer { .as_number() .expect("expected a number") as usize } + + /// Take the inner `ArrayBuffer`'s `array_buffer_data` field and replace it with `None` + /// + /// Note: This causes the pre-existing `JsArrayBuffer` to become detached. + /// + /// ``` + /// # use boa_engine::{ + /// # object::builtins::JsArrayBuffer, + /// # Context, JsResult, + /// # }; + /// # fn main() -> JsResult<()> { + /// # // Initialize context + /// # let context = &mut Context::default(); + /// // Create a buffer from a chunk of data + /// let data_block: Vec = (0..5).collect(); + /// let array_buffer = JsArrayBuffer::from_byte_block(data_block, context)?; + /// + /// // Take the inner buffer + /// let internal_buffer = array_buffer.take()?; + /// + /// assert_eq!(internal_buffer, (0..5).collect::>()); + /// + /// // Anymore interaction with the buffer will return an error + /// let detached_err = array_buffer.take(); + /// assert!(detached_err.is_err()); + /// # Ok(()) + /// # } + /// ``` + #[inline] + pub fn take(&self) -> JsResult> { + self.inner + .borrow_mut() + .as_array_buffer_mut() + .expect("inner must be an ArrayBuffer") + .array_buffer_data + .take() + .ok_or_else(|| { + JsNativeError::typ() + .with_message("ArrayBuffer is detached") + .into() + }) + } } impl From for JsObject { diff --git a/boa_examples/src/bin/jsarraybuffer.rs b/boa_examples/src/bin/jsarraybuffer.rs index f0c0d8306e..c6987df25d 100644 --- a/boa_examples/src/bin/jsarraybuffer.rs +++ b/boa_examples/src/bin/jsarraybuffer.rs @@ -56,5 +56,15 @@ fn main() -> JsResult<()> { Attribute::WRITABLE | Attribute::ENUMERABLE | Attribute::CONFIGURABLE, ); + // We can also take the inner data from a JsArrayBuffer + let data_block: Vec = (0..5).collect(); + let array_buffer = JsArrayBuffer::from_byte_block(data_block, context)?; + + let internal_buffer = array_buffer.take()?; + + assert_eq!(internal_buffer, (0..5).collect::>()); + let detached_err = array_buffer.take(); + assert!(detached_err.is_err()); + Ok(()) }