diff --git a/core/engine/src/object/builtins/jsarray.rs b/core/engine/src/object/builtins/jsarray.rs index d80c964cf07..3f1f2a2fd84 100644 --- a/core/engine/src/object/builtins/jsarray.rs +++ b/core/engine/src/object/builtins/jsarray.rs @@ -1,6 +1,6 @@ //! A Rust API wrapper for Boa's `Array` Builtin ECMAScript Object use crate::{ - Context, JsResult, JsString, JsValue, + Context, JsExpect, JsResult, JsString, JsValue, builtins::Array, error::JsNativeError, object::{JsFunction, JsObject}, @@ -17,12 +17,16 @@ pub struct JsArray { impl JsArray { /// Create a new empty array. + /// + /// # Errors + /// + /// Returns a `PanicError` if creating the array fails due to an engine bug. #[inline] - pub fn new(context: &mut Context) -> Self { + pub fn new(context: &mut Context) -> JsResult { let inner = Array::array_create(0, None, context) - .expect("creating an empty array with the default prototype must not fail"); + .js_expect("creating an empty array with the default prototype must not fail")?; - Self { inner } + Ok(Self { inner }) } /// Create an array from a `IntoIterator` convertible object. @@ -115,7 +119,7 @@ impl JsArray { pub fn concat(&self, items: &[JsValue], context: &mut Context) -> JsResult { let object = Array::concat(&self.inner.clone().into(), items, context)? .as_object() - .expect("Array.prototype.filter should always return object"); + .js_expect("Array.prototype.concat should always return object")?; Self::from_object(object) } @@ -123,15 +127,15 @@ impl JsArray { /// Calls `Array.prototype.join()`. #[inline] pub fn join(&self, separator: Option, context: &mut Context) -> JsResult { - Array::join( + let result = Array::join( &self.inner.clone().into(), &[separator.into_or_undefined()], context, - ) - .map(|x| { - x.as_string() - .expect("Array.prototype.join always returns string") - }) + )?; + result + .as_string() + .js_expect("Array.prototype.join always returns string") + .map_err(Into::into) } /// Calls `Array.prototype.fill()`. @@ -173,7 +177,7 @@ impl JsArray { context, )? .as_number() - .expect("Array.prototype.indexOf should always return number"); + .js_expect("Array.prototype.indexOf should always return number")?; #[allow(clippy::float_cmp)] if index == -1.0 { @@ -199,7 +203,7 @@ impl JsArray { context, )? .as_number() - .expect("Array.prototype.lastIndexOf should always return number"); + .js_expect("Array.prototype.lastIndexOf should always return number")?; #[allow(clippy::float_cmp)] if index == -1.0 { @@ -238,7 +242,7 @@ impl JsArray { context, )? .as_object() - .expect("Array.prototype.filter should always return object"); + .js_expect("Array.prototype.filter should always return object")?; Self::from_object(object) } @@ -257,7 +261,7 @@ impl JsArray { context, )? .as_object() - .expect("Array.prototype.map should always return object"); + .js_expect("Array.prototype.map should always return object")?; Self::from_object(object) } @@ -276,7 +280,7 @@ impl JsArray { context, )? .as_boolean() - .expect("Array.prototype.every should always return boolean"); + .js_expect("Array.prototype.every should always return boolean")?; Ok(result) } @@ -295,7 +299,7 @@ impl JsArray { context, )? .as_boolean() - .expect("Array.prototype.some should always return boolean"); + .js_expect("Array.prototype.some should always return boolean")?; Ok(result) } @@ -326,7 +330,7 @@ impl JsArray { context, )? .as_object() - .expect("Array.prototype.slice should always return object"); + .js_expect("Array.prototype.slice should always return object")?; Self::from_object(object) } @@ -378,7 +382,7 @@ impl JsArray { context, )? .as_object() - .expect("Array.prototype.splice should always return object"); + .js_expect("Array.prototype.splice should always return object")?; Self::from_object(object) } @@ -421,7 +425,7 @@ impl JsArray { Ok(Self { inner: array .as_object() - .expect("`to_reversed` must always return an `Array` on success"), + .js_expect("`to_reversed` must always return an `Array` on success")?, }) } @@ -441,7 +445,7 @@ impl JsArray { Ok(Self { inner: array .as_object() - .expect("`to_sorted` must always return an `Array` on success"), + .js_expect("`to_sorted` must always return an `Array` on success")?, }) } @@ -453,7 +457,7 @@ impl JsArray { Ok(Self { inner: array .as_object() - .expect("`with` must always return an `Array` on success"), + .js_expect("`with` must always return an `Array` on success")?, }) } } @@ -547,7 +551,7 @@ mod tests { #[test] fn splice_empty_array() { let context = &mut Context::default(); - let array = JsArray::new(context); + let array = JsArray::new(context).unwrap(); let removed = array.splice(0, Some(0), &[], context).unwrap(); diff --git a/core/engine/src/object/builtins/jsmap.rs b/core/engine/src/object/builtins/jsmap.rs index 056dd651b61..c35a014cdbf 100644 --- a/core/engine/src/object/builtins/jsmap.rs +++ b/core/engine/src/object/builtins/jsmap.rs @@ -52,7 +52,7 @@ use std::ops::Deref; /// let context = &mut Context::default(); /// /// // Create an array of two `[key, value]` pairs -/// let js_array = JsArray::new(context); +/// let js_array = JsArray::new(context)?; /// /// // Create a `[key, value]` pair of JsValues /// let vec_one: Vec = vec![ @@ -111,7 +111,7 @@ impl JsMap { /// # // Create a default `Context` /// # let context = &mut Context::default(); /// // Create an array of two `[key, value]` pairs - /// let js_array = JsArray::new(context); + /// let js_array = JsArray::new(context)?; /// /// // Create a `[key, value]` pair of JsValues and add it to the `JsArray` as a `JsArray` /// let vec_one: Vec = vec![js_string!("first-key").into(), js_string!("first-value").into()]; @@ -171,11 +171,14 @@ impl JsMap { /// # object::{JsObject, builtins::{JsArray, JsMap}}, /// # Context, JsResult, JsValue, /// # }; + /// # fn main() -> JsResult<()> { /// # let context = &mut Context::default(); - /// let some_object = JsArray::new(context); + /// let some_object = JsArray::new(context)?; /// /// // `some_object` is an Array object, not a map object /// assert!(JsMap::from_object(some_object.into()).is_err()); + /// # Ok(()) + /// # } /// ``` #[inline] pub fn from_object(object: JsObject) -> JsResult { diff --git a/core/engine/src/object/jsobject.rs b/core/engine/src/object/jsobject.rs index af72bc01554..e666d39590e 100644 --- a/core/engine/src/object/jsobject.rs +++ b/core/engine/src/object/jsobject.rs @@ -436,17 +436,20 @@ impl JsObject { /// # Examples /// /// ``` - /// # use boa_engine::{Context, JsObject, JsValue}; + /// # use boa_engine::{Context, JsObject, JsValue ,JsResult}; /// # use boa_engine::object::builtins::JsArray; + /// # fn main() -> JsResult<()> { /// let context = &mut Context::default(); /// - /// let array = JsArray::new(context); + /// let array = JsArray::new(context)?; /// // A JsArray's inner JsObject is an array. /// assert!(JsObject::from(array).is_array()); /// /// // An ordinary object is not an array. /// let obj = JsObject::with_object_proto(context.intrinsics()); /// assert!(!obj.is_array()); + /// # Ok(()) + /// # } /// ``` #[inline] #[must_use] diff --git a/core/engine/src/value/conversions/serde_json.rs b/core/engine/src/value/conversions/serde_json.rs index 42614857989..4350b4c30a6 100644 --- a/core/engine/src/value/conversions/serde_json.rs +++ b/core/engine/src/value/conversions/serde_json.rs @@ -341,7 +341,7 @@ mod tests { .create_data_property(js_string!("inner_a"), JsValue::undefined(), &mut context) .expect("should add property"); - let array = JsArray::new(&mut context); + let array = JsArray::new(&mut context).expect("creating array in test must not fail"); array.push(2, &mut context).expect("should push"); array .push(JsValue::undefined(), &mut context) diff --git a/core/engine/src/value/conversions/try_into_js.rs b/core/engine/src/value/conversions/try_into_js.rs index bd710fca7be..585033f17bd 100644 --- a/core/engine/src/value/conversions/try_into_js.rs +++ b/core/engine/src/value/conversions/try_into_js.rs @@ -163,7 +163,7 @@ where T: TryIntoJs, { fn try_into_js(&self, context: &mut Context) -> JsResult { - let arr = crate::object::JsArray::new(context); + let arr = crate::object::JsArray::new(context)?; for value in self { let value = value.try_into_js(context)?; arr.push(value, context)?; @@ -177,7 +177,7 @@ macro_rules! impl_try_into_js_for_tuples { impl<$($ts: TryIntoJs,)+> TryIntoJs for ($($ts,)+) { fn try_into_js(&self, context: &mut Context) -> JsResult { let ($($names,)+) = self; - let arr = crate::object::JsArray::new(context); + let arr = crate::object::JsArray::new(context)?; $(arr.push($names.try_into_js(context)?, context)?;)+ Ok(arr.into()) } diff --git a/core/runtime/src/store/to.rs b/core/runtime/src/store/to.rs index d75368c3b1b..071093590ae 100644 --- a/core/runtime/src/store/to.rs +++ b/core/runtime/src/store/to.rs @@ -47,7 +47,7 @@ fn try_items_into_js_array( seen: &mut ReverseSeenMap, context: &mut Context, ) -> JsResult { - let dolly = JsArray::new(context); + let dolly = JsArray::new(context)?; seen.insert(store, dolly.clone().into()); for (k, v) in items diff --git a/examples/src/bin/jsarray.rs b/examples/src/bin/jsarray.rs index 9b7e851dba1..3b39f185058 100644 --- a/examples/src/bin/jsarray.rs +++ b/examples/src/bin/jsarray.rs @@ -11,7 +11,7 @@ fn main() -> JsResult<()> { let context = &mut Context::default(); // Create an empty array. - let array = JsArray::new(context); + let array = JsArray::new(context)?; assert!(array.is_empty(context)?); diff --git a/examples/src/bin/jsmap.rs b/examples/src/bin/jsmap.rs index e44058ec0cb..80774b44958 100644 --- a/examples/src/bin/jsmap.rs +++ b/examples/src/bin/jsmap.rs @@ -40,7 +40,7 @@ fn main() -> JsResult<()> { let _first_value = entries.next(context)?; // Create a multidimensional array with key value pairs -> [[first-key, first-value], [second-key, second-value]] - let js_array = JsArray::new(context); + let js_array = JsArray::new(context)?; let vec_one = vec![ JsValue::new(js_string!("first-key")),