Skip to content

Commit

Permalink
Create new lazy Error type (#2283)
Browse files Browse the repository at this point in the history
This is an experiment that tries to migrate the codebase from eager `Error` objects to lazy ones.

In short words, this redefines `JsResult = Result<JsValue, JsError>`, where `JsError` is a brand new type that stores only the essential part of an error type, and only transforms those errors to `JsObject`s on demand (when having to pass them as arguments to functions or store them inside async/generators).

This change is pretty big, because it unblocks a LOT of code from having to take a `&mut Context` on each call. It also paves the road for possibly making `JsError` a proper variant of `JsValue`, which can be a pretty big optimization for try/catch.

A downside of this is that it exposes some brand new error types to our public API. However, we can now implement `Error` on `JsError`, making our `JsResult` type a bit more inline with Rust's best practices.

~Will mark this as draft, since it's missing some documentation and a lot of examples, but~ it's pretty much feature complete. As always, any comments about the design are very much appreciated!

Note: Since there are a lot of changes which are essentially just rewriting `context.throw` to `JsNativeError::%type%`, I'll leave an "index" of the most important changes here:

- [boa_engine/src/error.rs](https://github.com/boa-dev/boa/pull/2283/files#diff-f15f2715655440626eefda5c46193d29856f4949ad37380c129a8debc6b82f26)
- [boa_engine/src/builtins/error/mod.rs](https://github.com/boa-dev/boa/pull/2283/files#diff-3eb1e4b4b5c7210eb98192a5277f5a239148423c6b970c4ae05d1b267f8f1084)
- [boa_tester/src/exec/mod.rs](https://github.com/boa-dev/boa/pull/2283/files#diff-fc3d7ad7b5e64574258c9febbe56171f3309b74e0c8da35238a76002f3ee34d9)
  • Loading branch information
jedel1043 committed Oct 19, 2022
1 parent 4601b92 commit dc9c1cb
Show file tree
Hide file tree
Showing 97 changed files with 3,282 additions and 1,996 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions boa_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ impl Opt {
#[derive(Debug, Clone, ValueEnum)]
enum DumpFormat {
/// The different types of format available for dumping.
///
// NOTE: This can easily support other formats just by
// adding a field to this enum and adding the necessary
// implementation. Example: Toml, Html, etc.
Expand Down Expand Up @@ -204,7 +203,7 @@ pub fn main() -> Result<(), io::Error> {
} else {
match context.eval(&buffer) {
Ok(v) => println!("{}", v.display()),
Err(v) => eprintln!("Uncaught {}", v.display()),
Err(v) => eprintln!("Uncaught {v}"),
}
}
}
Expand Down Expand Up @@ -251,11 +250,7 @@ pub fn main() -> Result<(), io::Error> {
match context.eval(line.trim_end()) {
Ok(v) => println!("{}", v.display()),
Err(v) => {
eprintln!(
"{}: {}",
"Uncaught".red(),
v.display().to_string().red()
);
eprintln!("{}: {}", "Uncaught".red(), v.to_string().red());
}
}
}
Expand Down
1 change: 1 addition & 0 deletions boa_engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ once_cell = "1.15.0"
tap = "1.0.1"
sptr = "0.3.2"
static_assertions = "1.1.0"
thiserror = "1.0.37"
icu_locale_canonicalizer = { version = "0.6.0", features = ["serde"], optional = true }
icu_locid = { version = "0.6.0", features = ["serde"], optional = true }
icu_datetime = { version = "0.6.0", features = ["serde"], optional = true }
Expand Down
24 changes: 16 additions & 8 deletions boa_engine/src/bigint.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! This module implements the JavaScript bigint primitive rust type.
use crate::{builtins::Number, Context, JsValue};
use crate::{builtins::Number, error::JsNativeError, JsResult};
use num_integer::Integer;
use num_traits::{pow::Pow, FromPrimitive, One, ToPrimitive, Zero};
use std::{
Expand Down Expand Up @@ -148,11 +148,13 @@ impl JsBigInt {
}

#[inline]
pub fn pow(x: &Self, y: &Self, context: &mut Context) -> Result<Self, JsValue> {
pub fn pow(x: &Self, y: &Self) -> JsResult<Self> {
let y = if let Some(y) = y.inner.to_biguint() {
y
} else {
return context.throw_range_error("BigInt negative exponent");
return Err(JsNativeError::range()
.with_message("BigInt negative exponent")
.into());
};

let num_bits = (x.inner.bits() as f64
Expand All @@ -161,14 +163,16 @@ impl JsBigInt {
+ 1f64;

if num_bits > 1_000_000_000f64 {
return context.throw_range_error("Maximum BigInt size exceeded");
return Err(JsNativeError::range()
.with_message("Maximum BigInt size exceeded")
.into());
}

Ok(Self::new(x.inner.as_ref().clone().pow(y)))
}

#[inline]
pub fn shift_right(x: &Self, y: &Self, context: &mut Context) -> Result<Self, JsValue> {
pub fn shift_right(x: &Self, y: &Self) -> JsResult<Self> {
if let Some(n) = y.inner.to_i32() {
let inner = if n > 0 {
x.inner.as_ref().clone().shr(n as usize)
Expand All @@ -178,12 +182,14 @@ impl JsBigInt {

Ok(Self::new(inner))
} else {
context.throw_range_error("Maximum BigInt size exceeded")
Err(JsNativeError::range()
.with_message("Maximum BigInt size exceeded")
.into())
}
}

#[inline]
pub fn shift_left(x: &Self, y: &Self, context: &mut Context) -> Result<Self, JsValue> {
pub fn shift_left(x: &Self, y: &Self) -> JsResult<Self> {
if let Some(n) = y.inner.to_i32() {
let inner = if n > 0 {
x.inner.as_ref().clone().shl(n as usize)
Expand All @@ -193,7 +199,9 @@ impl JsBigInt {

Ok(Self::new(inner))
} else {
context.throw_range_error("Maximum BigInt size exceeded")
Err(JsNativeError::range()
.with_message("Maximum BigInt size exceeded")
.into())
}
}

Expand Down
11 changes: 7 additions & 4 deletions boa_engine/src/builtins/array/array_iterator.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
builtins::{function::make_builtin_fn, iterable::create_iter_result_object, Array, JsValue},
error::JsNativeError,
object::{JsObject, ObjectData},
property::{PropertyDescriptor, PropertyNameKind},
symbol::WellKnownSymbols,
Expand Down Expand Up @@ -72,7 +73,7 @@ impl ArrayIterator {
let array_iterator = array_iterator
.as_mut()
.and_then(|obj| obj.as_array_iterator_mut())
.ok_or_else(|| context.construct_type_error("`this` is not an ArrayIterator"))?;
.ok_or_else(|| JsNativeError::typ().with_message("`this` is not an ArrayIterator"))?;
let index = array_iterator.next_index;
if array_iterator.done {
return Ok(create_iter_result_object(
Expand All @@ -84,9 +85,11 @@ impl ArrayIterator {

let len = if let Some(f) = array_iterator.array.borrow().as_typed_array() {
if f.is_detached() {
return context.throw_type_error(
"Cannot get value from typed array that has a detached array buffer",
);
return Err(JsNativeError::typ()
.with_message(
"Cannot get value from typed array that has a detached array buffer",
)
.into());
}

f.array_length()
Expand Down
Loading

0 comments on commit dc9c1cb

Please sign in to comment.