Browse Source

Add a js_error! macro to create opaque errors (#3920)

* Add a js_error! macro to create opaque errors

And as a bonus since I needed it, simplify comparison of strings
and add PartialEq<&str> for JsString.

* Add PartialEq<str> for JsStr. PartialEq<&str> uses the other

* Cargo clippy

* Remove conversion of non-string literals and remove From<String> for JsValue
pull/3928/head
Hans Larsen 4 months ago committed by GitHub
parent
commit
d8b8066a58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 44
      core/engine/src/error.rs
  2. 17
      core/string/src/lib.rs
  3. 17
      core/string/src/str.rs

44
core/engine/src/error.rs

@ -14,6 +14,48 @@ use boa_gc::{custom_trace, Finalize, Trace};
use boa_macros::js_str;
use thiserror::Error;
/// Create an opaque error object from a value or string literal.
///
/// Can be used with an expression that converts into `JsValue` or a format
/// string with arguments.
///
/// # Examples
///
/// ```
/// # use boa_engine::{js_str, Context, JsValue};
/// use boa_engine::{js_error};
/// let context = &mut Context::default();
///
/// let error = js_error!("error!");
/// assert!(error.as_opaque().is_some());
/// assert_eq!(error.as_opaque().unwrap().to_string(context).unwrap(), "error!");
///
/// let error = js_error!("error: {}", 5);
/// assert_eq!(error.as_opaque().unwrap().to_string(context).unwrap(), "error: 5");
///
/// // Non-string literals must be used as an expression.
/// let error = js_error!({ true });
/// assert_eq!(error.as_opaque().unwrap(), &JsValue::from(true));
/// ```
#[macro_export]
macro_rules! js_error {
($value: literal) => {
$crate::JsError::from_opaque($crate::JsValue::from(
$crate::js_string!($value)
))
};
($value: expr) => {
$crate::JsError::from_opaque(
$crate::JsValue::from($value)
)
};
($value: literal $(, $args: tt)* $(,)?) => {
$crate::JsError::from_opaque($crate::JsValue::from(
$crate::JsString::from(format!($value $(, $args)*))
))
};
}
/// The error type returned by all operations related
/// to the execution of Javascript code.
///
@ -352,7 +394,7 @@ impl JsError {
///
/// assert!(error.as_native().is_some());
///
/// let error = JsError::from_opaque(JsValue::undefined().into());
/// let error = JsError::from_opaque(JsValue::undefined());
///
/// assert!(error.as_native().is_none());
/// ```

17
core/string/src/lib.rs

@ -1073,19 +1073,14 @@ impl<const N: usize> PartialEq<[u16; N]> for JsString {
impl PartialEq<str> for JsString {
#[inline]
fn eq(&self, other: &str) -> bool {
let utf16 = self.code_points();
let mut utf8 = other.chars();
for lhs in utf16 {
if let Some(rhs) = utf8.next() {
match lhs {
CodePoint::Unicode(lhs) if lhs == rhs => continue,
_ => return false,
}
self.as_str() == other
}
return false;
}
utf8.next().is_none()
impl PartialEq<&str> for JsString {
#[inline]
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}

17
core/string/src/str.rs

@ -291,6 +291,23 @@ impl PartialEq for JsStr<'_> {
}
}
impl PartialEq<str> for JsStr<'_> {
#[inline]
fn eq(&self, other: &str) -> bool {
match self.variant() {
JsStrVariant::Latin1(v) => v == other.as_bytes(),
JsStrVariant::Utf16(v) => other.encode_utf16().zip(v).all(|(a, b)| a == *b),
}
}
}
impl PartialEq<&str> for JsStr<'_> {
#[inline]
fn eq(&self, other: &&str) -> bool {
self == *other
}
}
impl<'a> PartialEq<JsStr<'a>> for [u16] {
#[inline]
fn eq(&self, other: &JsStr<'a>) -> bool {

Loading…
Cancel
Save