From ab5705d887e525fd5aa4e066f0abd1623b4c8d20 Mon Sep 17 00:00:00 2001 From: KAUSTUBHOG Date: Fri, 10 Apr 2026 02:14:55 +0530 Subject: [PATCH] fix(object/operations,string): convert remaining panics to EngineError::Panic --- core/engine/src/object/builtins/jsdataview.rs | 13 ++++++- .../engine/src/object/internal_methods/mod.rs | 35 ++++++++++++++--- .../src/object/internal_methods/string.rs | 39 +++++++++++++------ core/engine/src/object/operations.rs | 22 +++++++---- 4 files changed, 83 insertions(+), 26 deletions(-) diff --git a/core/engine/src/object/builtins/jsdataview.rs b/core/engine/src/object/builtins/jsdataview.rs index 7bf07ade92d..41fb2e99921 100644 --- a/core/engine/src/object/builtins/jsdataview.rs +++ b/core/engine/src/object/builtins/jsdataview.rs @@ -2,6 +2,7 @@ use crate::{ Context, JsExpect, JsNativeError, JsResult, JsValue, builtins::{DataView, array_buffer::BufferObject}, + error::PanicError, object::{JsArrayBuffer, JsObject}, value::TryFromJs, }; @@ -60,7 +61,9 @@ impl JsDataView { let offset = offset.unwrap_or_default(); let (buf_byte_len, is_fixed_len) = { - let buffer = buffer.borrow(); + let buffer = buffer + .try_borrow() + .map_err(|e| PanicError::new(e.to_string()))?; let buffer = buffer.data(); // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. @@ -110,7 +113,13 @@ impl JsDataView { // 11. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. // 12. Set bufferByteLength to ArrayBufferByteLength(buffer, seq-cst). - let Some(buf_byte_len) = buffer.borrow().data().bytes().map(|s| s.len() as u64) else { + let Some(buf_byte_len) = buffer + .try_borrow() + .map_err(|e| PanicError::new(e.to_string()))? + .data() + .bytes() + .map(|s| s.len() as u64) + else { return Err(JsNativeError::typ() .with_message("ArrayBuffer is detached") .into()); diff --git a/core/engine/src/object/internal_methods/mod.rs b/core/engine/src/object/internal_methods/mod.rs index 8e474b5dde5..4edc9c7d566 100644 --- a/core/engine/src/object/internal_methods/mod.rs +++ b/core/engine/src/object/internal_methods/mod.rs @@ -14,6 +14,7 @@ use super::{ use crate::{ Context, JsNativeError, JsResult, context::intrinsics::{StandardConstructor, StandardConstructors}, + error::PanicError, object::JsObject, property::{DescriptorKind, PropertyDescriptor, PropertyKey}, value::JsValue, @@ -588,7 +589,10 @@ pub(crate) fn ordinary_set_prototype_of( #[allow(clippy::unnecessary_wraps)] pub(crate) fn ordinary_is_extensible(obj: &JsObject, _context: &mut Context) -> JsResult { // 1. Return O.[[Extensible]]. - Ok(obj.borrow().extensible) + Ok(obj + .try_borrow() + .map_err(|e| PanicError::new(e.to_string()))? + .extensible) } /// Abstract operation `OrdinaryPreventExtensions`. @@ -603,7 +607,9 @@ pub(crate) fn ordinary_prevent_extensions( _context: &mut Context, ) -> JsResult { // 1. Set O.[[Extensible]] to false. - obj.borrow_mut().extensible = false; + obj.try_borrow_mut() + .map_err(|e| PanicError::new(e.to_string()))? + .extensible = false; // 2. Return true. Ok(true) @@ -635,7 +641,11 @@ pub(crate) fn ordinary_get_own_property( // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute. // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute. // 9. Return D. - Ok(obj.borrow().properties.get_with_slot(key, context.slot())) + Ok(obj + .try_borrow() + .map_err(|e| PanicError::new(e.to_string()))? + .properties + .get_with_slot(key, context.slot())) } /// Abstract operation `OrdinaryDefineOwnProperty`. @@ -945,7 +955,9 @@ pub(crate) fn ordinary_delete( // 4. If desc.[[Configurable]] is true, then Some(desc) if desc.expect_configurable() => { // a. Remove the own property with name P from O. - obj.borrow_mut().remove(key); + obj.try_borrow_mut() + .map_err(|e| PanicError::new(e.to_string()))? + .remove(key); // b. Return true. true } @@ -972,7 +984,12 @@ pub(crate) fn ordinary_own_property_keys( let mut keys = Vec::new(); let ordered_indexes = { - let mut indexes: Vec<_> = obj.borrow().properties.index_property_keys().collect(); + let mut indexes: Vec<_> = obj + .try_borrow() + .map_err(|e| PanicError::new(e.to_string()))? + .properties + .index_property_keys() + .collect(); indexes.sort_unstable(); indexes }; @@ -986,7 +1003,13 @@ pub(crate) fn ordinary_own_property_keys( // // 4. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do // a. Add P as the last element of keys. - keys.extend(obj.borrow().properties.shape.keys()); + keys.extend( + obj.try_borrow() + .map_err(|e| PanicError::new(e.to_string()))? + .properties + .shape + .keys(), + ); // 5. Return keys. Ok(keys) diff --git a/core/engine/src/object/internal_methods/string.rs b/core/engine/src/object/internal_methods/string.rs index 11a60219bd3..7e41181c601 100644 --- a/core/engine/src/object/internal_methods/string.rs +++ b/core/engine/src/object/internal_methods/string.rs @@ -1,5 +1,6 @@ use crate::{ Context, JsExpect, JsResult, JsString, + error::PanicError, object::{JsData, JsObject}, property::{PropertyDescriptor, PropertyKey}, }; @@ -39,7 +40,7 @@ pub(crate) fn string_exotic_get_own_property( Ok(desc) } else { // 4. Return ! StringGetOwnProperty(S, P). - Ok(string_get_own_property(obj, key)) + string_get_own_property(obj, key) } } @@ -57,12 +58,15 @@ pub(crate) fn string_exotic_define_own_property( ) -> JsResult { // 1. Assert: IsPropertyKey(P) is true. // 2. Let stringDesc be ! StringGetOwnProperty(S, P). - let string_desc = string_get_own_property(obj, key); + let string_desc = string_get_own_property(obj, key)?; // 3. If stringDesc is not undefined, then if let Some(string_desc) = string_desc { // a. Let extensible be S.[[Extensible]]. - let extensible = obj.borrow().extensible; + let extensible = obj + .try_borrow() + .map_err(|e| PanicError::new(e.to_string()))? + .extensible; // b. Return ! IsCompatiblePropertyDescriptor(extensible, Desc, stringDesc). Ok(super::is_compatible_property_descriptor( extensible, @@ -106,7 +110,8 @@ pub(crate) fn string_exotic_own_property_keys( // and ! ToIntegerOrInfinity(P) ≥ len, in ascending numeric index order, do // a. Add P as the last element of keys. let mut remaining_indices: Vec<_> = obj - .borrow() + .try_borrow() + .map_err(|e| PanicError::new(e.to_string()))? .properties .index_property_keys() .filter(|idx| (*idx as usize) >= len) @@ -121,7 +126,13 @@ pub(crate) fn string_exotic_own_property_keys( // 8. For each own property key P of O such that Type(P) is Symbol, in ascending // chronological order of property creation, do // a. Add P as the last element of keys. - keys.extend(obj.borrow().properties.shape.keys()); + keys.extend( + obj.try_borrow() + .map_err(|e| PanicError::new(e.to_string()))? + .properties + .shape + .keys(), + ); // 9. Return keys. Ok(keys) @@ -133,7 +144,10 @@ pub(crate) fn string_exotic_own_property_keys( /// - [ECMAScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-stringgetownproperty -fn string_get_own_property(obj: &JsObject, key: &PropertyKey) -> Option { +fn string_get_own_property( + obj: &JsObject, + key: &PropertyKey, +) -> JsResult> { // 1. Assert: S is an Object that has a [[StringData]] internal slot. // 2. Assert: IsPropertyKey(P) is true. // 3. If Type(P) is not String, return undefined. @@ -143,20 +157,23 @@ fn string_get_own_property(obj: &JsObject, key: &PropertyKey) -> Option index.get() as usize, - _ => return None, + _ => return Ok(None), }; // 8. Let str be S.[[StringData]]. // 9. Assert: Type(str) is String. let string = obj .downcast_ref::() - .expect("string exotic method should only be callable from string objects") + .js_expect("string exotic method should only be callable from string objects")? .clone(); // 10. Let len be the length of str. // 11. If ℝ(index) < 0 or len ≤ ℝ(index), return undefined. - // 12. Let resultStr be the String value of length 1, containing one code unit from str, specifically the code unit at index ℝ(index). - let result_str = string.get(pos..=pos)?; + // 12. Let resultStr be the String value of length 1, containing one code unit from str, + // specifically the code unit at index ℝ(index). + let Some(result_str) = string.get(pos..=pos) else { + return Ok(None); + }; // 13. Return the PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }. let desc = PropertyDescriptor::builder() @@ -166,5 +183,5 @@ fn string_get_own_property(obj: &JsObject, key: &PropertyKey) -> Option JsResult<()> { // 1. Let entry be PrivateElementFind(O, P). // Note: This function is inlined here for mutable access. - let mut object_mut = self.borrow_mut(); + let mut object_mut = self + .try_borrow_mut() + .map_err(|e| PanicError::new(e.to_string()))?; let entry = object_mut .private_elements .iter_mut()