Browse Source

Feature `boa::Result<T>` (#637)

pull/626/head
HalidOdat 4 years ago committed by GitHub
parent
commit
d025207fc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 82
      boa/src/builtins/array/mod.rs
  2. 18
      boa/src/builtins/bigint/mod.rs
  3. 15
      boa/src/builtins/boolean/mod.rs
  4. 39
      boa/src/builtins/console/mod.rs
  5. 28
      boa/src/builtins/date/mod.rs
  6. 7
      boa/src/builtins/error/mod.rs
  7. 11
      boa/src/builtins/error/range.rs
  8. 11
      boa/src/builtins/error/reference.rs
  9. 10
      boa/src/builtins/error/syntax.rs
  10. 12
      boa/src/builtins/error/type.rs
  11. 14
      boa/src/builtins/function/mod.rs
  12. 19
      boa/src/builtins/json/mod.rs
  13. 18
      boa/src/builtins/map/mod.rs
  14. 77
      boa/src/builtins/math/mod.rs
  15. 2
      boa/src/builtins/mod.rs
  16. 50
      boa/src/builtins/number/mod.rs
  17. 33
      boa/src/builtins/object/mod.rs
  18. 32
      boa/src/builtins/regexp/mod.rs
  19. 70
      boa/src/builtins/string/mod.rs
  20. 10
      boa/src/builtins/symbol/mod.rs
  21. 12
      boa/src/builtins/value/conversions.rs
  22. 2
      boa/src/builtins/value/equality.rs
  23. 34
      boa/src/builtins/value/mod.rs
  24. 38
      boa/src/builtins/value/operations.rs
  25. 6
      boa/src/exec/array/mod.rs
  26. 8
      boa/src/exec/block/mod.rs
  27. 7
      boa/src/exec/break_node/mod.rs
  28. 6
      boa/src/exec/call/mod.rs
  29. 7
      boa/src/exec/conditional/mod.rs
  30. 19
      boa/src/exec/declaration/mod.rs
  31. 8
      boa/src/exec/exception.rs
  32. 7
      boa/src/exec/field/mod.rs
  33. 4
      boa/src/exec/identifier/mod.rs
  34. 10
      boa/src/exec/iteration/mod.rs
  35. 23
      boa/src/exec/mod.rs
  36. 6
      boa/src/exec/new/mod.rs
  37. 5
      boa/src/exec/object/mod.rs
  38. 17
      boa/src/exec/operator/mod.rs
  39. 7
      boa/src/exec/return_smt/mod.rs
  40. 4
      boa/src/exec/spread/mod.rs
  41. 8
      boa/src/exec/statement_list.rs
  42. 7
      boa/src/exec/switch/mod.rs
  43. 4
      boa/src/exec/throw/mod.rs
  44. 6
      boa/src/exec/try_node/mod.rs
  45. 11
      boa/src/lib.rs

82
boa/src/builtins/array/mod.rs

@ -17,10 +17,10 @@ use crate::{
builtins::{
object::{ObjectData, PROTOTYPE},
property::{Attribute, Property},
value::{same_value_zero, ResultValue, Value},
value::{same_value_zero, Value},
},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
use std::{
borrow::Borrow,
@ -39,7 +39,7 @@ impl Array {
pub(crate) const LENGTH: usize = 1;
/// Creates a new `Array` instance.
pub(crate) fn new_array(interpreter: &Interpreter) -> ResultValue {
pub(crate) fn new_array(interpreter: &Interpreter) -> Result<Value> {
let array = Value::new_object(Some(
&interpreter
.realm()
@ -65,7 +65,7 @@ impl Array {
///
/// `array_obj` can be any array with prototype already set (it will be wiped and
/// recreated from `array_contents`)
pub(crate) fn construct_array(array_obj: &Value, array_contents: &[Value]) -> ResultValue {
pub(crate) fn construct_array(array_obj: &Value, array_contents: &[Value]) -> Result<Value> {
let array_obj_ptr = array_obj.clone();
// Wipe existing contents of the array object
@ -89,7 +89,7 @@ impl Array {
/// Utility function which takes an existing array object and puts additional
/// values on the end, correctly rewriting the length
pub(crate) fn add_to_array_object(array_ptr: &Value, add_values: &[Value]) -> ResultValue {
pub(crate) fn add_to_array_object(array_ptr: &Value, add_values: &[Value]) -> Result<Value> {
let orig_length = array_ptr.get_field("length").as_number().unwrap() as i32;
for (n, value) in add_values.iter().enumerate() {
@ -106,7 +106,7 @@ impl Array {
}
/// Create a new array
pub(crate) fn make_array(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_array(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// Make a new Object which will internally represent the Array (mapping
// between indices and values): this creates an Object with no prototype
@ -166,7 +166,7 @@ impl Array {
_this: &Value,
args: &[Value],
_interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
match args.get(0).and_then(|x| x.as_object()) {
Some(object) => Ok(Value::from(object.is_array())),
None => Ok(Value::from(false)),
@ -185,7 +185,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.concat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
pub(crate) fn concat(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn concat(this: &Value, args: &[Value], _: &mut Interpreter) -> Result<Value> {
if args.is_empty() {
// If concat is called with no arguments, it returns the original array
return Ok(this.clone());
@ -222,7 +222,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.push
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
pub(crate) fn push(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn push(this: &Value, args: &[Value], _: &mut Interpreter) -> Result<Value> {
let new_array = Self::add_to_array_object(this, args)?;
Ok(new_array.get_field("length"))
}
@ -237,8 +237,9 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.pop
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop
pub(crate) fn pop(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn pop(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
let curr_length = this.get_field("length").as_number().unwrap() as i32;
if curr_length < 1 {
return Ok(Value::undefined());
}
@ -263,7 +264,7 @@ impl Array {
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
if args.is_empty() {
return Err(Value::from("Missing argument for Array.prototype.forEach"));
}
@ -295,7 +296,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.join
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join
pub(crate) fn join(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn join(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let separator = if args.is_empty() {
String::from(",")
} else {
@ -328,7 +329,7 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let method_name = "join";
let mut arguments = vec![Value::from(",")];
// 2.
@ -368,8 +369,9 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.reverse
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse
#[allow(clippy::else_if_without_else)]
pub(crate) fn reverse(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn reverse(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
let len = this.get_field("length").as_number().unwrap() as i32;
let middle: i32 = len.wrapping_div(2);
for lower in 0..middle {
@ -406,7 +408,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.shift
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
pub(crate) fn shift(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn shift(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
let len = this.get_field("length").as_number().unwrap() as i32;
if len == 0 {
@ -448,8 +450,9 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.unshift
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
pub(crate) fn unshift(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn unshift(this: &Value, args: &[Value], _: &mut Interpreter) -> Result<Value> {
let len = this.get_field("length").as_number().unwrap() as i32;
let arg_c: i32 = args.len() as i32;
if arg_c > 0 {
@ -496,7 +499,7 @@ impl Array {
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
if args.is_empty() {
return Err(Value::from(
"missing callback when calling function Array.prototype.every",
@ -538,7 +541,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.map
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
pub(crate) fn map(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue {
pub(crate) fn map(
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> Result<Value> {
if args.is_empty() {
return Err(Value::from(
"missing argument 0 when calling function Array.prototype.map",
@ -585,7 +592,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.indexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
pub(crate) fn index_of(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn index_of(this: &Value, args: &[Value], _: &mut Interpreter) -> Result<Value> {
// If no arguments, return -1. Not described in spec, but is what chrome does.
if args.is_empty() {
return Ok(Value::from(-1));
@ -638,7 +645,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.lastindexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf
pub(crate) fn last_index_of(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn last_index_of(
this: &Value,
args: &[Value],
_: &mut Interpreter,
) -> Result<Value> {
// If no arguments, return -1. Not described in spec, but is what chrome does.
if args.is_empty() {
return Ok(Value::from(-1));
@ -685,7 +696,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.find
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
pub(crate) fn find(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue {
pub(crate) fn find(
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> Result<Value> {
if args.is_empty() {
return Err(Value::from(
"missing callback when calling function Array.prototype.find",
@ -721,7 +736,7 @@ impl Array {
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
if args.is_empty() {
return Err(Value::from(
"Missing argument for Array.prototype.findIndex",
@ -759,8 +774,9 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.fill
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill
pub(crate) fn fill(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn fill(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let len: i32 = this.get_field("length").as_number().unwrap() as i32;
let default_value = Value::undefined();
let value = args.get(0).unwrap_or(&default_value);
let relative_start = args.get(1).unwrap_or(&default_value).to_number(ctx)? as i32;
@ -798,7 +814,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.includes
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
pub(crate) fn includes_value(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn includes_value(
this: &Value,
args: &[Value],
_: &mut Interpreter,
) -> Result<Value> {
let search_element = args.get(0).cloned().unwrap_or_else(Value::undefined);
let length = this.get_field("length").as_number().unwrap() as i32;
@ -832,7 +852,7 @@ impl Array {
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
let new_array = Self::new_array(interpreter)?;
let len = this.get_field("length").as_number().unwrap() as i32;
@ -881,7 +901,7 @@ impl Array {
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
if args.is_empty() {
return Err(Value::from(
"missing argument 0 when calling function Array.prototype.filter",
@ -931,7 +951,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.some
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
pub(crate) fn some(this: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue {
pub(crate) fn some(
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> Result<Value> {
if args.is_empty() {
return Err(Value::from(
"missing callback when calling function Array.prototype.some",
@ -978,7 +1002,7 @@ impl Array {
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
let this = this.to_object(interpreter)?;
let callback = match args.get(0) {
Some(value) if value.is_function() => value,
@ -1045,7 +1069,7 @@ impl Array {
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
let this = this.to_object(interpreter)?;
let callback = match args.get(0) {
Some(value) if value.is_function() => value,

18
boa/src/builtins/bigint/mod.rs

@ -16,10 +16,10 @@ use crate::{
builtins::{
function::{make_builtin_fn, make_constructor_fn},
object::ObjectData,
value::{RcBigInt, ResultValue, Value},
value::{RcBigInt, Value},
},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
use gc::{unsafe_empty_trace, Finalize, Trace};
@ -61,7 +61,7 @@ impl BigInt {
///
/// [spec]: https://tc39.es/ecma262/#sec-thisbigintvalue
#[inline]
fn this_bigint_value(value: &Value, ctx: &mut Interpreter) -> Result<RcBigInt, Value> {
fn this_bigint_value(value: &Value, ctx: &mut Interpreter) -> Result<RcBigInt> {
match value {
// 1. If Type(value) is BigInt, return value.
Value::BigInt(ref bigint) => return Ok(bigint.clone()),
@ -91,7 +91,7 @@ impl BigInt {
///
/// [spec]: https://tc39.es/ecma262/#sec-bigint-objects
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/BigInt
pub(crate) fn make_bigint(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_bigint(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let data = match args.get(0) {
Some(ref value) => value.to_bigint(ctx)?,
None => RcBigInt::from(Self::from(0)),
@ -110,7 +110,7 @@ impl BigInt {
/// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let radix = if !args.is_empty() {
args[0].to_integer(ctx)? as i32
} else {
@ -135,7 +135,7 @@ impl BigInt {
///
/// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/valueOf
pub(crate) fn value_of(this: &Value, _args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn value_of(this: &Value, _args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(Value::from(Self::this_bigint_value(this, ctx)?))
}
@ -146,7 +146,7 @@ impl BigInt {
/// [spec]: https://tc39.es/ecma262/#sec-bigint.asintn
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asIntN
#[allow(clippy::wrong_self_convention)]
pub(crate) fn as_int_n(_this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn as_int_n(_this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let (modulo, bits) = Self::calculate_as_uint_n(args, ctx)?;
if bits > 0 && modulo >= BigInt::from(2).pow(&BigInt::from(bits as i64 - 1)) {
@ -165,7 +165,7 @@ impl BigInt {
/// [spec]: https://tc39.es/ecma262/#sec-bigint.asuintn
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asUintN
#[allow(clippy::wrong_self_convention)]
pub(crate) fn as_uint_n(_this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn as_uint_n(_this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let (modulo, _) = Self::calculate_as_uint_n(args, ctx)?;
Ok(Value::from(modulo))
@ -176,7 +176,7 @@ impl BigInt {
/// This function expects the same arguments as `as_uint_n` and wraps the value of a `BigInt`.
/// Additionally to the wrapped unsigned value it returns the converted `bits` argument, so it
/// can be reused from the `as_int_n` method.
fn calculate_as_uint_n(args: &[Value], ctx: &mut Interpreter) -> Result<(BigInt, u32), Value> {
fn calculate_as_uint_n(args: &[Value], ctx: &mut Interpreter) -> Result<(BigInt, u32)> {
use std::convert::TryFrom;
let undefined_value = Value::undefined();

15
boa/src/builtins/boolean/mod.rs

@ -14,12 +14,9 @@ mod tests;
use super::function::{make_builtin_fn, make_constructor_fn};
use crate::{
builtins::{
object::ObjectData,
value::{ResultValue, Value},
},
builtins::{object::ObjectData, value::Value},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
/// Boolean implementation.
@ -39,7 +36,7 @@ impl Boolean {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-thisbooleanvalue
fn this_boolean_value(value: &Value, ctx: &mut Interpreter) -> Result<bool, Value> {
fn this_boolean_value(value: &Value, ctx: &mut Interpreter) -> Result<bool> {
match value {
Value::Boolean(boolean) => return Ok(*boolean),
Value::Object(ref object) => {
@ -61,7 +58,7 @@ impl Boolean {
this: &Value,
args: &[Value],
_: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
// Get the argument, if any
let data = args.get(0).map(|x| x.to_boolean()).unwrap_or(false);
this.set_data(ObjectData::Boolean(data));
@ -78,7 +75,7 @@ impl Boolean {
/// [spec]: https://tc39.es/ecma262/#sec-boolean-object
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let boolean = Self::this_boolean_value(this, ctx)?;
Ok(Value::from(boolean.to_string()))
}
@ -92,7 +89,7 @@ impl Boolean {
/// [spec]: https://tc39.es/ecma262/#sec-boolean.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/valueOf
#[inline]
pub(crate) fn value_of(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn value_of(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(Value::from(Self::this_boolean_value(this, ctx)?))
}

39
boa/src/builtins/console/mod.rs

@ -19,10 +19,10 @@ mod tests;
use crate::{
builtins::{
function::make_builtin_fn,
value::{display_obj, RcString, ResultValue, Value},
value::{display_obj, RcString, Value},
},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
use rustc_hash::FxHashMap;
use std::time::SystemTime;
@ -59,8 +59,9 @@ pub(crate) fn logger(msg: LogMessage, console_state: &Console) {
}
/// This represents the `console` formatter.
pub fn formatter(data: &[Value], ctx: &mut Interpreter) -> Result<String, Value> {
pub fn formatter(data: &[Value], ctx: &mut Interpreter) -> Result<String> {
let target = data.get(0).cloned().unwrap_or_default().to_string(ctx)?;
match data.len() {
0 => Ok(String::new()),
1 => Ok(target.to_string()),
@ -153,7 +154,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#assert
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/assert
pub(crate) fn assert(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn assert(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let assertion = get_arg_at_index::<bool>(args, 0).unwrap_or_default();
if !assertion {
@ -184,7 +185,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#clear
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/clear
pub(crate) fn clear(_: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn clear(_: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
ctx.console_mut().groups.clear();
Ok(Value::undefined())
}
@ -199,7 +200,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#debug
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/debug
pub(crate) fn debug(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn debug(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
logger(LogMessage::Log(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined())
}
@ -214,7 +215,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#error
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/error
pub(crate) fn error(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn error(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
logger(LogMessage::Error(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined())
}
@ -229,7 +230,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#info
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/info
pub(crate) fn info(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn info(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
logger(LogMessage::Info(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined())
}
@ -244,7 +245,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#log
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/log
pub(crate) fn log(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn log(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
logger(LogMessage::Log(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined())
}
@ -259,7 +260,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#trace
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/trace
pub(crate) fn trace(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn trace(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
if !args.is_empty() {
logger(LogMessage::Log(formatter(args, ctx)?), ctx.console());
@ -283,7 +284,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#warn
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/warn
pub(crate) fn warn(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn warn(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
logger(LogMessage::Warn(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined())
}
@ -298,7 +299,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#count
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/count
pub(crate) fn count(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn count(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let label = match args.get(0) {
Some(value) => value.to_string(ctx)?,
None => "default".into(),
@ -322,7 +323,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#countreset
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/countReset
pub(crate) fn count_reset(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn count_reset(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let label = match args.get(0) {
Some(value) => value.to_string(ctx)?,
None => "default".into(),
@ -356,7 +357,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#time
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/time
pub(crate) fn time(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn time(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let label = match args.get(0) {
Some(value) => value.to_string(ctx)?,
None => "default".into(),
@ -385,7 +386,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#timelog
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/timeLog
pub(crate) fn time_log(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn time_log(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let label = match args.get(0) {
Some(value) => value.to_string(ctx)?,
None => "default".into(),
@ -418,7 +419,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#timeend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/timeEnd
pub(crate) fn time_end(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn time_end(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let label = match args.get(0) {
Some(value) => value.to_string(ctx)?,
None => "default".into(),
@ -450,7 +451,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#group
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/group
pub(crate) fn group(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn group(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let group_label = formatter(args, ctx)?;
logger(
@ -472,7 +473,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#groupend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/groupEnd
pub(crate) fn group_end(_: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn group_end(_: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
ctx.console_mut().groups.pop();
Ok(Value::undefined())
@ -488,7 +489,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#dir
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/dir
pub(crate) fn dir(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn dir(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let undefined = Value::undefined();
logger(
LogMessage::Info(display_obj(args.get(0).unwrap_or(&undefined), true)),

28
boa/src/builtins/date/mod.rs

@ -6,9 +6,9 @@ use crate::{
function::{make_builtin_fn, make_constructor_fn},
object::ObjectData,
value::PreferredType,
ResultValue, Value,
Value,
},
BoaProfiler, Interpreter,
BoaProfiler, Interpreter, Result,
};
use chrono::{prelude::*, Duration, LocalResult};
use gc::{unsafe_empty_trace, Finalize, Trace};
@ -40,13 +40,13 @@ fn ignore_ambiguity<T>(result: LocalResult<T>) -> Option<T> {
macro_rules! getter_method {
($name:ident) => {{
fn get_value(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
fn get_value(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(Value::from(this_time_value(this, ctx)?.$name()))
}
get_value
}};
(Self::$name:ident) => {{
fn get_value(_: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
fn get_value(_: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
Ok(Value::from(Date::$name()))
}
get_value
@ -55,7 +55,7 @@ macro_rules! getter_method {
macro_rules! setter_method {
($name:ident($($e:expr),* $(,)?)) => {{
fn set_value(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
fn set_value(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let mut result = this_time_value(this, ctx)?;
result.$name(
$(
@ -246,7 +246,7 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_date(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
if this.is_global() {
Self::make_date_string()
} else if args.is_empty() {
@ -268,7 +268,7 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date_string() -> ResultValue {
pub(crate) fn make_date_string() -> Result<Value> {
Ok(Value::from(Local::now().to_rfc3339()))
}
@ -282,7 +282,7 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date_now(this: &Value) -> ResultValue {
pub(crate) fn make_date_now(this: &Value) -> Result<Value> {
let date = Date::default();
this.set_data(ObjectData::Date(date));
Ok(this.clone())
@ -302,7 +302,7 @@ impl Date {
this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
let value = &args[0];
let tv = match this_time_value(value, ctx) {
Ok(dt) => dt.0,
@ -339,7 +339,7 @@ impl Date {
this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
let year = args[0].to_number(ctx)?;
let month = args[1].to_number(ctx)?;
let day = args.get(2).map_or(Ok(1f64), |value| value.to_number(ctx))?;
@ -1164,7 +1164,7 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date.now
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now
pub(crate) fn now(_: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn now(_: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
Ok(Value::from(Utc::now().timestamp_millis() as f64))
}
@ -1180,7 +1180,7 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date.parse
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
pub(crate) fn parse(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn parse(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// This method is implementation-defined and discouraged, so we just require the same format as the string
// constructor.
@ -1204,7 +1204,7 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date.utc
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC
pub(crate) fn utc(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn utc(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let year = args
.get(0)
.map_or(Ok(f64::NAN), |value| value.to_number(ctx))?;
@ -1581,7 +1581,7 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-thistimevalue
#[inline]
pub fn this_time_value(value: &Value, ctx: &mut Interpreter) -> Result<Date, Value> {
pub fn this_time_value(value: &Value, ctx: &mut Interpreter) -> Result<Date> {
if let Value::Object(ref object) = value {
if let ObjectData::Date(ref date) = object.borrow().data {
return Ok(*date);

7
boa/src/builtins/error/mod.rs

@ -14,10 +14,11 @@ use crate::{
builtins::{
function::{make_builtin_fn, make_constructor_fn},
object::ObjectData,
value::{ResultValue, Value},
value::Value,
},
exec::Interpreter,
profiler::BoaProfiler,
Result,
};
pub(crate) mod range;
@ -46,7 +47,7 @@ impl Error {
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
if let Some(message) = args.get(0) {
this.set_field("message", message.to_string(ctx)?);
}
@ -68,7 +69,7 @@ impl Error {
/// [spec]: https://tc39.es/ecma262/#sec-error.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
let name = this.get_field("name");
let message = this.get_field("message");
Ok(Value::from(format!(

11
boa/src/builtins/error/range.rs

@ -11,13 +11,11 @@
use crate::{
builtins::{
function::make_builtin_fn,
function::make_constructor_fn,
object::ObjectData,
value::{ResultValue, Value},
function::make_builtin_fn, function::make_constructor_fn, object::ObjectData, value::Value,
},
exec::Interpreter,
profiler::BoaProfiler,
Result,
};
/// JavaScript `RangeError` impleentation.
@ -32,7 +30,7 @@ impl RangeError {
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
if let Some(message) = args.get(0) {
this.set_field("message", message.to_string(ctx)?);
}
@ -54,9 +52,10 @@ impl RangeError {
/// [spec]: https://tc39.es/ecma262/#sec-error.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let name = this.get_field("name").to_string(ctx)?;
let message = this.get_field("message").to_string(ctx)?;
Ok(Value::from(format!("{}: {}", name, message)))
}

11
boa/src/builtins/error/reference.rs

@ -11,13 +11,11 @@
use crate::{
builtins::{
function::make_builtin_fn,
function::make_constructor_fn,
object::ObjectData,
value::{ResultValue, Value},
function::make_builtin_fn, function::make_constructor_fn, object::ObjectData, value::Value,
},
exec::Interpreter,
profiler::BoaProfiler,
Result,
};
#[derive(Debug, Clone, Copy)]
@ -31,7 +29,7 @@ impl ReferenceError {
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
if let Some(message) = args.get(0) {
this.set_field("message", message.to_string(ctx)?);
}
@ -53,9 +51,10 @@ impl ReferenceError {
/// [spec]: https://tc39.es/ecma262/#sec-error.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let name = this.get_field("name").to_string(ctx)?;
let message = this.get_field("message").to_string(ctx)?;
Ok(Value::from(format!("{}: {}", name, message)))
}

10
boa/src/builtins/error/syntax.rs

@ -13,13 +13,11 @@
use crate::{
builtins::{
function::make_builtin_fn,
function::make_constructor_fn,
object::ObjectData,
value::{ResultValue, Value},
function::make_builtin_fn, function::make_constructor_fn, object::ObjectData, value::Value,
},
exec::Interpreter,
profiler::BoaProfiler,
Result,
};
/// JavaScript `SyntaxError` impleentation.
@ -34,7 +32,7 @@ impl SyntaxError {
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
if let Some(message) = args.get(0) {
this.set_field("message", message.to_string(ctx)?);
}
@ -56,7 +54,7 @@ impl SyntaxError {
/// [spec]: https://tc39.es/ecma262/#sec-error.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
let name = this.get_field("name");
let message = this.get_field("message");
// FIXME: This should not use `.display()`

12
boa/src/builtins/error/type.rs

@ -17,13 +17,10 @@
use crate::{
builtins::{
function::make_builtin_fn,
function::make_constructor_fn,
object::ObjectData,
value::{ResultValue, Value},
function::make_builtin_fn, function::make_constructor_fn, object::ObjectData, value::Value,
},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
/// JavaScript `TypeError` implementation.
@ -38,7 +35,7 @@ impl TypeError {
pub(crate) const LENGTH: usize = 1;
/// Create a new error object.
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
if let Some(message) = args.get(0) {
this.set_field("message", message.to_string(ctx)?);
}
@ -60,9 +57,10 @@ impl TypeError {
/// [spec]: https://tc39.es/ecma262/#sec-error.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let name = this.get_field("name").to_string(ctx)?;
let message = this.get_field("message").to_string(ctx)?;
Ok(Value::from(format!("{}: {}", name, message)))
}

14
boa/src/builtins/function/mod.rs

@ -15,21 +15,21 @@ use crate::{
builtins::{
object::{Object, ObjectData, PROTOTYPE},
property::{Attribute, Property, PropertyKey},
value::{RcString, ResultValue, Value},
value::{RcString, Value},
Array,
},
environment::function_environment_record::BindingStatus,
environment::lexical_environment::{new_function_environment, Environment},
exec::{Executable, Interpreter},
syntax::ast::node::{FormalParameter, StatementList},
BoaProfiler,
BoaProfiler, Result,
};
use bitflags::bitflags;
use gc::{unsafe_empty_trace, Finalize, Trace};
use std::fmt::{self, Debug};
/// _fn(this, arguments, ctx) -> ResultValue_ - The signature of a built-in function
pub type NativeFunctionData = fn(&Value, &[Value], &mut Interpreter) -> ResultValue;
/// _fn(this, arguments, ctx) -> Result<Value>_ - The signature of a built-in function
pub type NativeFunctionData = fn(&Value, &[Value], &mut Interpreter) -> Result<Value>;
/// Sets the ConstructorKind
#[derive(Debug, Copy, Clone)]
@ -216,7 +216,7 @@ impl Function {
this: &Value,
args_list: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("function::call", "function");
if self.flags.is_callable() {
match self.body {
@ -283,7 +283,7 @@ impl Function {
this: &Value,
args_list: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
if self.flags.is_constructable() {
match self.body {
FunctionBody::BuiltIn(func) => {
@ -435,7 +435,7 @@ pub fn create_unmapped_arguments_object(arguments_list: &[Value]) -> Value {
/// Create new function `[[Construct]]`
///
// This gets called when a new Function() is created.
pub fn make_function(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub fn make_function(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
this.set_data(ObjectData::Function(Function::builtin(
Vec::new(),
|_, _, _| Ok(Value::undefined()),

19
boa/src/builtins/json/mod.rs

@ -13,12 +13,8 @@
//! [json]: https://www.json.org/json-en.html
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
use crate::builtins::{
function::make_builtin_fn,
property::Property,
value::{ResultValue, Value},
};
use crate::{exec::Interpreter, BoaProfiler};
use crate::builtins::{function::make_builtin_fn, property::Property, value::Value};
use crate::{exec::Interpreter, BoaProfiler, Result};
use serde_json::{self, Value as JSONValue};
#[cfg(test)]
@ -44,7 +40,7 @@ impl Json {
///
/// [spec]: https://tc39.es/ecma262/#sec-json.parse
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
pub(crate) fn parse(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn parse(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
match serde_json::from_str::<JSONValue>(
&args
.get(0)
@ -72,7 +68,12 @@ impl Json {
/// for possible transformation.
///
/// [polyfill]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
fn walk(reviver: &Value, ctx: &mut Interpreter, holder: &mut Value, key: Value) -> ResultValue {
fn walk(
reviver: &Value,
ctx: &mut Interpreter,
holder: &mut Value,
key: Value,
) -> Result<Value> {
let mut value = holder.get_field(key.clone());
let obj = value.as_object().as_deref().cloned();
@ -109,7 +110,7 @@ impl Json {
///
/// [spec]: https://tc39.es/ecma262/#sec-json.stringify
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
pub(crate) fn stringify(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn stringify(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let object = match args.get(0) {
Some(obj) if obj.is_symbol() || obj.is_function() || obj.is_undefined() => {
return Ok(Value::undefined())

18
boa/src/builtins/map/mod.rs

@ -5,10 +5,10 @@ use crate::{
builtins::{
object::{ObjectData, PROTOTYPE},
property::{Attribute, Property},
value::{ResultValue, Value},
value::Value,
},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
use ordered_map::OrderedMap;
@ -44,7 +44,7 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.set
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set
pub(crate) fn set(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn set(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let (key, value) = match args.len() {
0 => (Value::Undefined, Value::Undefined),
1 => (args[0].clone(), Value::Undefined),
@ -77,7 +77,7 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.delete
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete
pub(crate) fn delete(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn delete(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let undefined = Value::Undefined;
let key = match args.len() {
0 => &undefined,
@ -109,7 +109,7 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.get
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get
pub(crate) fn get(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn get(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let undefined = Value::Undefined;
let key = match args.len() {
0 => &undefined,
@ -140,7 +140,7 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.clear
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear
pub(crate) fn clear(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn clear(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
this.set_data(ObjectData::Map(OrderedMap::new()));
Self::set_size(this, 0);
@ -158,7 +158,7 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.has
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has
pub(crate) fn has(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn has(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let undefined = Value::Undefined;
let key = match args.len() {
0 => &undefined,
@ -189,7 +189,7 @@ impl Map {
this: &Value,
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
if args.is_empty() {
return Err(Value::from("Missing argument for Map.prototype.forEach"));
}
@ -227,7 +227,7 @@ impl Map {
}
/// Create a new map
pub(crate) fn make_map(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_map(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// Make a new Object which will internally represent the Array (mapping
// between indices and values): this creates an Object with no prototype

77
boa/src/builtins/math/mod.rs

@ -12,12 +12,9 @@
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math
use crate::{
builtins::{
function::make_builtin_fn,
value::{ResultValue, Value},
},
builtins::{function::make_builtin_fn, value::Value},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
use std::f64;
@ -40,7 +37,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.abs
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/abs
pub(crate) fn abs(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn abs(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -57,7 +54,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.acos
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/acos
pub(crate) fn acos(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn acos(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -74,7 +71,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.acosh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/acosh
pub(crate) fn acosh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn acosh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -91,7 +88,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.asin
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/asin
pub(crate) fn asin(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn asin(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -108,7 +105,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.asinh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/asinh
pub(crate) fn asinh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn asinh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -125,7 +122,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.atan
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan
pub(crate) fn atan(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn atan(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -142,7 +139,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.atanh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atanh
pub(crate) fn atanh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn atanh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -159,7 +156,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.atan2
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan2
pub(crate) fn atan2(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn atan2(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(match (
args.get(0).map(|x| x.to_number(ctx)).transpose()?,
args.get(1).map(|x| x.to_number(ctx)).transpose()?,
@ -178,7 +175,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.cbrt
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cbrt
pub(crate) fn cbrt(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn cbrt(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -195,7 +192,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.ceil
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil
pub(crate) fn ceil(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn ceil(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -212,7 +209,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.clz32
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
pub(crate) fn clz32(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn clz32(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_u32(ctx))
@ -230,7 +227,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.cos
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cos
pub(crate) fn cos(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn cos(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -247,7 +244,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.cosh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cosh
pub(crate) fn cosh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn cosh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -264,7 +261,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.exp
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/exp
pub(crate) fn exp(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn exp(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -283,7 +280,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.expm1
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/expm1
pub(crate) fn expm1(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn expm1(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -300,7 +297,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.floor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor
pub(crate) fn floor(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn floor(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -317,7 +314,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.fround
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
pub(crate) fn fround(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn fround(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -334,7 +331,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.hypot
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/hypot
pub(crate) fn hypot(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn hypot(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let mut result = 0f64;
for arg in args {
let x = arg.to_number(ctx)?;
@ -351,7 +348,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.imul
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
pub(crate) fn imul(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn imul(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(match (
args.get(0).map(|x| x.to_u32(ctx)).transpose()?,
args.get(1).map(|x| x.to_u32(ctx)).transpose()?,
@ -370,7 +367,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.log
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log
pub(crate) fn log(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn log(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -387,7 +384,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.log1p
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log1p
pub(crate) fn log1p(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn log1p(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -404,7 +401,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.log10
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log10
pub(crate) fn log10(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn log10(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -421,7 +418,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.log2
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log2
pub(crate) fn log2(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn log2(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -438,7 +435,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.max
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max
pub(crate) fn max(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn max(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let mut max = f64::NEG_INFINITY;
for arg in args {
let num = arg.to_number(ctx)?;
@ -455,7 +452,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.min
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min
pub(crate) fn min(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn min(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let mut min = f64::INFINITY;
for arg in args {
let num = arg.to_number(ctx)?;
@ -472,7 +469,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.pow
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/pow
pub(crate) fn pow(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn pow(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(match (
args.get(0).map(|x| x.to_number(ctx)).transpose()?,
args.get(1).map(|x| x.to_number(ctx)).transpose()?,
@ -491,7 +488,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.random
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
pub(crate) fn random(_: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn random(_: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
Ok(rand::random::<f64>().into())
}
@ -503,7 +500,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.round
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
pub(crate) fn round(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn round(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -520,7 +517,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.sign
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
pub(crate) fn sign(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn sign(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -546,7 +543,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.sin
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sin
pub(crate) fn sin(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn sin(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -563,7 +560,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.sinh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sinh
pub(crate) fn sinh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn sinh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -580,7 +577,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.sqrt
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt
pub(crate) fn sqrt(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn sqrt(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -597,7 +594,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.tan
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/tan
pub(crate) fn tan(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn tan(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -614,7 +611,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.tanh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/tanh
pub(crate) fn tanh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn tanh(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))
@ -631,7 +628,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.trunc
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
pub(crate) fn trunc(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn trunc(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(args
.get(0)
.map(|x| x.to_number(ctx))

2
boa/src/builtins/mod.rs

@ -40,7 +40,7 @@ pub(crate) use self::{
string::String,
symbol::Symbol,
undefined::Undefined,
value::{ResultValue, Value},
value::Value,
};
use crate::Interpreter;

50
boa/src/builtins/number/mod.rs

@ -18,11 +18,7 @@ use super::{
object::ObjectData,
value::AbstractRelation,
};
use crate::{
builtins::value::{ResultValue, Value},
exec::Interpreter,
BoaProfiler,
};
use crate::{builtins::value::Value, exec::Interpreter, BoaProfiler, Result};
use num_traits::float::FloatCore;
mod conversions;
@ -106,7 +102,7 @@ impl Number {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-thisnumbervalue
fn this_number_value(value: &Value, ctx: &mut Interpreter) -> Result<f64, Value> {
fn this_number_value(value: &Value, ctx: &mut Interpreter) -> Result<f64> {
match *value {
Value::Integer(integer) => return Ok(f64::from(integer)),
Value::Rational(rational) => return Ok(rational),
@ -133,7 +129,11 @@ impl Number {
/// `[[Construct]]` - Creates a Number instance
///
/// `[[Call]]` - Creates a number primitive
pub(crate) fn make_number(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_number(
this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> Result<Value> {
let data = match args.get(0) {
Some(ref value) => value.to_numeric_number(ctx)?,
None => 0.0,
@ -158,7 +158,7 @@ impl Number {
this: &Value,
_args: &[Value],
ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
let this_num = Self::this_number_value(this, ctx)?;
let this_str_num = Self::num_to_exponential(this_num);
Ok(Value::from(this_str_num))
@ -175,7 +175,7 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tofixed
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_fixed(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_fixed(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let this_num = Self::this_number_value(this, ctx)?;
let precision = match args.get(0) {
Some(n) => match n.to_integer(ctx)? as i32 {
@ -206,7 +206,7 @@ impl Number {
this: &Value,
_args: &[Value],
ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
let this_num = Self::this_number_value(this, ctx)?;
let this_str_num = format!("{}", this_num);
Ok(Value::from(this_str_num))
@ -223,7 +223,11 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.toexponential
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_precision(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_precision(
this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> Result<Value> {
let this_num = Self::this_number_value(this, ctx)?;
let _num_str_len = format!("{}", this_num).len();
let _precision = match args.get(0) {
@ -377,7 +381,7 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// 1. Let x be ? thisNumberValue(this value).
let x = Self::this_number_value(this, ctx)?;
@ -432,7 +436,7 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/valueOf
pub(crate) fn value_of(this: &Value, _args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn value_of(this: &Value, _args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
Ok(Value::from(Self::this_number_value(this, ctx)?))
}
@ -450,7 +454,11 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-parseint-string-radix
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
pub(crate) fn parse_int(_this: &Value, args: &[Value], _ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn parse_int(
_this: &Value,
args: &[Value],
_ctx: &mut Interpreter,
) -> Result<Value> {
if let (Some(val), r) = (args.get(0), args.get(1)) {
let mut radix = if let Some(rx) = r {
if let Value::Integer(i) = rx {
@ -520,7 +528,7 @@ impl Number {
_this: &Value,
args: &[Value],
_ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
if let Some(val) = args.get(0) {
match val {
Value::String(s) => {
@ -566,7 +574,7 @@ impl Number {
_this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
if let Some(value) = args.get(0) {
let number = value.to_number(ctx)?;
Ok(number.is_finite().into())
@ -593,7 +601,7 @@ impl Number {
_this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
if let Some(value) = args.get(0) {
let number = value.to_number(ctx)?;
Ok(number.is_nan().into())
@ -620,7 +628,7 @@ impl Number {
_this: &Value,
args: &[Value],
_ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
Ok(Value::from(if let Some(val) = args.get(0) {
match val {
Value::Integer(_) => true,
@ -646,7 +654,7 @@ impl Number {
_this: &Value,
args: &[Value],
_ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
Ok(args.get(0).map_or(false, Self::is_integer).into())
}
@ -668,7 +676,7 @@ impl Number {
_this: &Value,
args: &[Value],
_ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
Ok(Value::from(if let Some(val) = args.get(0) {
match val {
Value::Integer(_) => false,
@ -698,7 +706,7 @@ impl Number {
_this: &Value,
args: &[Value],
_ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
Ok(Value::from(match args.get(0) {
Some(Value::Integer(_)) => true,
Some(Value::Rational(number)) if Self::is_float_integer(*number) => {

33
boa/src/builtins/object/mod.rs

@ -18,15 +18,16 @@ use crate::{
function::Function,
map::ordered_map::OrderedMap,
property::Property,
value::{RcBigInt, RcString, RcSymbol, ResultValue, Value},
value::{RcBigInt, RcString, RcSymbol, Value},
BigInt, Date, RegExp,
},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
use gc::{Finalize, Trace};
use rustc_hash::FxHashMap;
use std::fmt::{Debug, Display, Error, Formatter};
use std::result::Result as StdResult;
use super::function::{make_builtin_fn, make_constructor_fn};
use crate::builtins::value::same_value;
@ -83,7 +84,7 @@ pub enum ObjectData {
}
impl Display for ObjectData {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
fn fmt(&self, f: &mut Formatter<'_>) -> StdResult<(), Error> {
write!(
f,
"{}",
@ -211,7 +212,7 @@ impl Object {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-toobject
pub fn from(value: &Value) -> Result<Self, ()> {
pub fn from(value: &Value) -> StdResult<Self, ()> {
match *value {
Value::Boolean(a) => Ok(Self::boolean(a)),
Value::Rational(a) => Ok(Self::number(a)),
@ -440,7 +441,7 @@ impl Object {
}
/// Create a new object.
pub fn make_object(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub fn make_object(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
if let Some(arg) = args.get(0) {
if !arg.is_null_or_undefined() {
return Ok(Value::object(Object::from(arg).unwrap()));
@ -463,7 +464,7 @@ pub fn make_object(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultVa
///
/// [spec]: https://tc39.es/ecma262/#sec-object.create
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
pub fn create(_: &Value, args: &[Value], interpreter: &mut Interpreter) -> ResultValue {
pub fn create(_: &Value, args: &[Value], interpreter: &mut Interpreter) -> Result<Value> {
let prototype = args.get(0).cloned().unwrap_or_else(Value::undefined);
let properties = args.get(1).cloned().unwrap_or_else(Value::undefined);
@ -484,7 +485,7 @@ pub fn create(_: &Value, args: &[Value], interpreter: &mut Interpreter) -> Resul
}
/// Uses the SameValue algorithm to check equality of objects
pub fn is(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub fn is(_: &Value, args: &[Value], _: &mut Interpreter) -> Result<Value> {
let x = args.get(0).cloned().unwrap_or_else(Value::undefined);
let y = args.get(1).cloned().unwrap_or_else(Value::undefined);
@ -492,7 +493,7 @@ pub fn is(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
}
/// Get the `prototype` of an object.
pub fn get_prototype_of(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub fn get_prototype_of(_: &Value, args: &[Value], _: &mut Interpreter) -> Result<Value> {
let obj = args.get(0).expect("Cannot get object");
Ok(obj
.as_object()
@ -500,7 +501,7 @@ pub fn get_prototype_of(_: &Value, args: &[Value], _: &mut Interpreter) -> Resul
}
/// Set the `prototype` of an object.
pub fn set_prototype_of(_: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub fn set_prototype_of(_: &Value, args: &[Value], _: &mut Interpreter) -> Result<Value> {
let obj = args.get(0).expect("Cannot get object").clone();
let proto = args.get(1).expect("Cannot get object").clone();
obj.as_object_mut().unwrap().prototype = proto;
@ -508,7 +509,7 @@ pub fn set_prototype_of(_: &Value, args: &[Value], _: &mut Interpreter) -> Resul
}
/// Define a property in an object
pub fn define_property(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub fn define_property(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let obj = args.get(0).expect("Cannot get object");
let prop = args.get(1).expect("Cannot get object").to_string(ctx)?;
let desc = Property::from(args.get(2).expect("Cannot get object"));
@ -526,9 +527,9 @@ pub fn define_property(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Resu
///
/// [spec]: https://tc39.es/ecma262/#sec-object.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
pub fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
// FIXME: it should not display the object.
Ok(Value::from(this.display().to_string()))
Ok(this.display().to_string().into())
}
/// `Object.prototype.hasOwnPrototype( property )`
@ -542,7 +543,7 @@ pub fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue
///
/// [spec]: https://tc39.es/ecma262/#sec-object.prototype.hasownproperty
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
pub fn has_own_property(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub fn has_own_property(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let prop = if args.is_empty() {
None
} else {
@ -560,7 +561,11 @@ pub fn has_own_property(this: &Value, args: &[Value], ctx: &mut Interpreter) ->
}
}
pub fn property_is_enumerable(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub fn property_is_enumerable(
this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> Result<Value> {
let key = match args.get(0) {
None => return Ok(Value::from(false)),
Some(key) => key,

32
boa/src/builtins/regexp/mod.rs

@ -16,10 +16,10 @@ use crate::{
builtins::{
object::{InternalState, ObjectData},
property::Property,
value::{RcString, ResultValue, Value},
value::{RcString, Value},
},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
use gc::{unsafe_empty_trace, Finalize, Trace};
@ -74,7 +74,7 @@ impl RegExp {
pub(crate) const LENGTH: usize = 2;
/// Create a new `RegExp`
pub(crate) fn make_regexp(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn make_regexp(this: &Value, args: &[Value], _: &mut Interpreter) -> Result<Value> {
let arg = args.get(0).ok_or_else(Value::undefined)?;
let mut regex_body = String::new();
let mut regex_flags = String::new();
@ -171,7 +171,7 @@ impl RegExp {
// ///
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.dotAll
// /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/dotAll
// fn get_dot_all(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
// fn get_dot_all(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
// this.with_internal_state_ref(|regex: &RegExp| Ok(Value::from(regex.dot_all)))
// }
@ -186,7 +186,7 @@ impl RegExp {
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
// /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags
// /// [flags]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Advanced_searching_with_flags_2
// fn get_flags(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
// fn get_flags(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
// this.with_internal_state_ref(|regex: &RegExp| Ok(Value::from(regex.flags.clone())))
// }
@ -200,7 +200,7 @@ impl RegExp {
// ///
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.global
// /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/global
// fn get_global(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
// fn get_global(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
// this.with_internal_state_ref(|regex: &RegExp| Ok(Value::from(regex.global)))
// }
@ -214,7 +214,7 @@ impl RegExp {
// ///
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.ignorecase
// /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/ignoreCase
// fn get_ignore_case(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
// fn get_ignore_case(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
// this.with_internal_state_ref(|regex: &RegExp| Ok(Value::from(regex.ignore_case)))
// }
@ -228,7 +228,7 @@ impl RegExp {
// ///
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.multiline
// /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/multiline
// fn get_multiline(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
// fn get_multiline(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
// this.with_internal_state_ref(|regex: &RegExp| Ok(Value::from(regex.multiline)))
// }
@ -243,7 +243,7 @@ impl RegExp {
// ///
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.source
// /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source
// fn get_source(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
// fn get_source(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
// Ok(this.get_internal_slot("OriginalSource"))
// }
@ -257,7 +257,7 @@ impl RegExp {
// ///
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.sticky
// /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky
// fn get_sticky(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
// fn get_sticky(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
// this.with_internal_state_ref(|regex: &RegExp| Ok(Value::from(regex.sticky)))
// }
@ -272,7 +272,7 @@ impl RegExp {
// ///
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.unicode
// /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode
// fn get_unicode(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
// fn get_unicode(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
// this.with_internal_state_ref(|regex: &RegExp| Ok(Value::from(regex.unicode)))
// }
@ -288,7 +288,7 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.test
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
pub(crate) fn test(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn test(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let arg_str = args
.get(0)
.expect("could not get argument")
@ -327,7 +327,7 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.exec
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
pub(crate) fn exec(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn exec(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let arg_str = args
.get(0)
.expect("could not get argument")
@ -383,7 +383,7 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype-@@match
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@match
pub(crate) fn r#match(this: &Value, arg: RcString, ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn r#match(this: &Value, arg: RcString, ctx: &mut Interpreter) -> Result<Value> {
let (matcher, flags) = if let Some(object) = this.as_object() {
let regex = object.as_regexp().unwrap();
(regex.matcher.clone(), regex.flags.clone())
@ -415,7 +415,7 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _: &[Value], _: &mut Interpreter) -> Result<Value> {
let (body, flags) = if let Some(object) = this.as_object() {
let regex = object.as_regexp().unwrap();
(regex.original_source.clone(), regex.flags.clone())
@ -436,7 +436,7 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-regexp-prototype-matchall
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@matchAll
// TODO: it's returning an array, it should return an iterator
pub(crate) fn match_all(this: &Value, arg_str: String) -> ResultValue {
pub(crate) fn match_all(this: &Value, arg_str: String) -> Result<Value> {
let matches = if let Some(object) = this.as_object() {
let regex = object.as_regexp().unwrap();
let mut matches = Vec::new();

70
boa/src/builtins/string/mod.rs

@ -17,11 +17,11 @@ use crate::{
builtins::{
object::{Object, ObjectData},
property::Property,
value::{RcString, ResultValue, Value},
value::{RcString, Value},
RegExp,
},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
use regex::Regex;
use std::string::String as StdString;
@ -48,7 +48,7 @@ impl String {
/// which can differ in JavaScript engines. In Boa it is `2^32 - 1`
pub(crate) const MAX_STRING_LENGTH: f64 = u32::MAX as f64;
fn this_string_value(this: &Value, ctx: &mut Interpreter) -> Result<RcString, Value> {
fn this_string_value(this: &Value, ctx: &mut Interpreter) -> Result<RcString> {
match this {
Value::String(ref string) => return Ok(string.clone()),
Value::Object(ref object) => {
@ -67,7 +67,11 @@ impl String {
///
/// [[Call]] - Returns a new native `string`
/// <https://tc39.es/ecma262/#sec-string-constructor-string-value>
pub(crate) fn make_string(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn make_string(
this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> Result<Value> {
// This value is used by console.log and other routines to match Obexpecty"failed to parse argument for String method"pe
// to its Javascript Identifier (global constructor method name)
let string = match args.get(0) {
@ -87,7 +91,7 @@ impl String {
/// Get the string value to a primitive string
#[allow(clippy::wrong_self_convention)]
#[inline]
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// Get String from String Object and send it back as a new value
Ok(Value::from(Self::this_string_value(this, ctx)?))
}
@ -108,7 +112,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt
pub(crate) fn char_at(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn char_at(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?;
@ -150,7 +154,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charcodeat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
pub(crate) fn char_code_at(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn char_code_at(
this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?;
@ -190,7 +198,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.concat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/concat
pub(crate) fn concat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn concat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let object = ctx.require_object_coercible(this)?;
let mut string = object.to_string(ctx)?.to_string();
@ -212,7 +220,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.repeat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
pub(crate) fn repeat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn repeat(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let object = ctx.require_object_coercible(this)?;
let string = object.to_string(ctx)?;
@ -246,7 +254,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.slice
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
pub(crate) fn slice(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn slice(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?;
@ -296,7 +304,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.startswith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
pub(crate) fn starts_with(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn starts_with(
this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?;
@ -339,7 +351,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.endswith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
pub(crate) fn ends_with(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn ends_with(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?;
@ -385,7 +397,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.includes
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
pub(crate) fn includes(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn includes(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?;
@ -447,7 +459,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.replace
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
pub(crate) fn replace(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn replace(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// TODO: Support Symbol replacer
let primitive_val = this.to_string(ctx)?;
if args.is_empty() {
@ -550,7 +562,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.indexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
pub(crate) fn index_of(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn index_of(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?;
@ -597,7 +609,7 @@ impl String {
this: &Value,
args: &[Value],
ctx: &mut Interpreter,
) -> ResultValue {
) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?;
@ -638,7 +650,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.match
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
/// [regex]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
pub(crate) fn r#match(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn r#match(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let re = RegExp::make_regexp(&Value::from(Object::default()), &[args[0].clone()], ctx)?;
RegExp::r#match(&re, this.to_string(ctx)?, ctx)
}
@ -652,7 +664,7 @@ impl String {
max_length: i32,
fill_string: Option<RcString>,
at_start: bool,
) -> ResultValue {
) -> Result<Value> {
let primitive_length = primitive.len() as i32;
if max_length <= primitive_length {
@ -689,7 +701,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
pub(crate) fn pad_end(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn pad_end(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let primitive = this.to_string(ctx)?;
if args.is_empty() {
return Err(Value::from("padEnd requires maxLength argument"));
@ -716,7 +728,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padstart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
pub(crate) fn pad_start(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn pad_start(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let primitive = this.to_string(ctx)?;
if args.is_empty() {
return Err(Value::from("padStart requires maxLength argument"));
@ -763,7 +775,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trim
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
pub(crate) fn trim(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn trim(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?;
Ok(Value::from(
@ -783,7 +795,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimstart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimStart
pub(crate) fn trim_start(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn trim_start(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?;
Ok(Value::from(
@ -803,7 +815,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd
pub(crate) fn trim_end(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn trim_end(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?;
Ok(Value::from(
@ -822,7 +834,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.tolowercase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_lowercase(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_lowercase(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let this_str = this.to_string(ctx)?;
@ -844,7 +856,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.toUppercase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_uppercase(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_uppercase(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let this_str = this.to_string(ctx)?;
@ -863,7 +875,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring
pub(crate) fn substring(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn substring(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?;
@ -912,7 +924,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substr
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr
/// <https://tc39.es/ecma262/#sec-string.prototype.substr>
pub(crate) fn substr(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn substr(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// First we get it the actual string a private field stored on the object only the engine has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?;
@ -968,7 +980,7 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.value_of
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/valueOf
pub(crate) fn value_of(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn value_of(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
// Use the to_string method because it is specified to do the same thing in this case
Self::to_string(this, args, ctx)
}
@ -986,7 +998,7 @@ impl String {
/// [regex]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
/// [cg]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges
// TODO: update this method to return iterator
pub(crate) fn match_all(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn match_all(this: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let re: Value = match args.get(0) {
Some(arg) => {
if arg.is_null() {

10
boa/src/builtins/symbol/mod.rs

@ -20,9 +20,9 @@ mod tests;
use super::function::{make_builtin_fn, make_constructor_fn};
use crate::{
builtins::value::{RcString, RcSymbol, ResultValue, Value},
builtins::value::{RcString, RcSymbol, Value},
exec::Interpreter,
BoaProfiler,
BoaProfiler, Result,
};
use gc::{Finalize, Trace};
@ -46,7 +46,7 @@ impl Symbol {
self.1
}
fn this_symbol_value(value: &Value, ctx: &mut Interpreter) -> Result<RcSymbol, Value> {
fn this_symbol_value(value: &Value, ctx: &mut Interpreter) -> Result<RcSymbol> {
match value {
Value::Symbol(ref symbol) => return Ok(symbol.clone()),
Value::Object(ref object) => {
@ -72,7 +72,7 @@ impl Symbol {
///
/// [spec]: https://tc39.es/ecma262/#sec-symbol-description
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/Symbol
pub(crate) fn call(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn call(_: &Value, args: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let description = match args.get(0) {
Some(ref value) if !value.is_undefined() => Some(value.to_string(ctx)?),
_ => None,
@ -92,7 +92,7 @@ impl Symbol {
/// [spec]: https://tc39.es/ecma262/#sec-symbol.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
pub(crate) fn to_string(this: &Value, _: &[Value], ctx: &mut Interpreter) -> Result<Value> {
let symbol = Self::this_symbol_value(this, ctx)?;
let description = symbol.description().unwrap_or("");
Ok(Value::from(format!("Symbol({})", description)))

12
boa/src/builtins/value/conversions.rs

@ -67,18 +67,6 @@ impl Display for TryFromCharError {
}
}
impl TryFrom<&Value> for char {
type Error = TryFromCharError;
fn try_from(value: &Value) -> Result<Self, Self::Error> {
if let Some(c) = value.display().to_string().chars().next() {
Ok(c)
} else {
Err(TryFromCharError)
}
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Self::rational(value)

2
boa/src/builtins/value/equality.rs

@ -37,7 +37,7 @@ impl Value {
/// This method is executed when doing abstract equality comparisons with the `==` operator.
/// For more information, check <https://tc39.es/ecma262/#sec-abstract-equality-comparison>
#[allow(clippy::float_cmp)]
pub fn equals(&self, other: &Self, interpreter: &mut Interpreter) -> Result<bool, Value> {
pub fn equals(&self, other: &Self, interpreter: &mut Interpreter) -> Result<bool> {
// 1. If Type(x) is the same as Type(y), then
// a. Return the result of performing Strict Equality Comparison x === y.
if self.get_type() == other.get_type() {

34
boa/src/builtins/value/mod.rs

@ -13,7 +13,7 @@ use crate::builtins::{
BigInt, Number, Symbol,
};
use crate::exec::Interpreter;
use crate::BoaProfiler;
use crate::{BoaProfiler, Result};
use gc::{Finalize, GcCellRef, GcCellRefMut, Trace};
use serde_json::{map::Map, Number as JSONNumber, Value as JSONValue};
use std::{
@ -46,10 +46,6 @@ pub use rcbigint::RcBigInt;
pub use rcstring::RcString;
pub use rcsymbol::RcSymbol;
/// The result of a Javascript expression is represented like this so it can succeed (`Ok`) or fail (`Err`)
#[must_use]
pub type ResultValue = Result<Value, Value>;
/// A Javascript value
#[derive(Trace, Finalize, Debug, Clone)]
pub enum Value {
@ -232,7 +228,7 @@ impl Value {
}
/// Converts the `Value` to `JSON`.
pub fn to_json(&self, interpreter: &mut Interpreter) -> Result<JSONValue, Value> {
pub fn to_json(&self, interpreter: &mut Interpreter) -> Result<JSONValue> {
let to_json = self.get_field("toJSON");
if to_json.is_function() {
let json_value = interpreter.call(&to_json, self, &[])?;
@ -678,7 +674,7 @@ impl Value {
&self,
ctx: &mut Interpreter,
preferred_type: PreferredType,
) -> ResultValue {
) -> Result<Value> {
// 1. Assert: input is an ECMAScript language value. (always a value not need to check)
// 2. If Type(input) is Object, then
if let Value::Object(_) = self {
@ -702,7 +698,7 @@ impl Value {
/// Converts the value to a `BigInt`.
///
/// This function is equivelent to `BigInt(value)` in JavaScript.
pub fn to_bigint(&self, ctx: &mut Interpreter) -> Result<RcBigInt, Value> {
pub fn to_bigint(&self, ctx: &mut Interpreter) -> Result<RcBigInt> {
match self {
Value::Null => Err(ctx.construct_type_error("cannot convert null to a BigInt")),
Value::Undefined => {
@ -749,7 +745,7 @@ impl Value {
/// Converts the value to a string.
///
/// This function is equivalent to `String(value)` in JavaScript.
pub fn to_string(&self, ctx: &mut Interpreter) -> Result<RcString, Value> {
pub fn to_string(&self, ctx: &mut Interpreter) -> Result<RcString> {
match self {
Value::Null => Ok("null".into()),
Value::Undefined => Ok("undefined".into()),
@ -771,7 +767,7 @@ impl Value {
/// This function is equivalent to `Object(value)` in JavaScript
///
/// See: <https://tc39.es/ecma262/#sec-toobject>
pub fn to_object(&self, ctx: &mut Interpreter) -> ResultValue {
pub fn to_object(&self, ctx: &mut Interpreter) -> Result<Value> {
match self {
Value::Undefined | Value::Null => {
ctx.throw_type_error("cannot convert 'null' or 'undefined' to object")
@ -858,7 +854,7 @@ impl Value {
/// Converts the value to a `PropertyKey`, that can be used as a key for properties.
///
/// See <https://tc39.es/ecma262/#sec-topropertykey>
pub fn to_property_key(&self, ctx: &mut Interpreter) -> Result<PropertyKey, Value> {
pub fn to_property_key(&self, ctx: &mut Interpreter) -> Result<PropertyKey> {
Ok(match self {
// Fast path:
Value::String(string) => string.clone().into(),
@ -875,7 +871,7 @@ impl Value {
/// It returns value converted to a numeric value of type `Number` or `BigInt`.
///
/// See: <https://tc39.es/ecma262/#sec-tonumeric>
pub fn to_numeric(&self, ctx: &mut Interpreter) -> Result<Numeric, Value> {
pub fn to_numeric(&self, ctx: &mut Interpreter) -> Result<Numeric> {
let primitive = self.to_primitive(ctx, PreferredType::Number)?;
if let Some(bigint) = primitive.as_bigint() {
return Ok(bigint.clone().into());
@ -888,7 +884,7 @@ impl Value {
/// This function is equivalent to `value | 0` in JavaScript
///
/// See: <https://tc39.es/ecma262/#sec-toint32>
pub fn to_u32(&self, ctx: &mut Interpreter) -> Result<u32, Value> {
pub fn to_u32(&self, ctx: &mut Interpreter) -> Result<u32> {
// This is the fast path, if the value is Integer we can just return it.
if let Value::Integer(number) = *self {
return Ok(number as u32);
@ -901,7 +897,7 @@ impl Value {
/// Converts a value to an integral 32 bit signed integer.
///
/// See: <https://tc39.es/ecma262/#sec-toint32>
pub fn to_i32(&self, ctx: &mut Interpreter) -> Result<i32, Value> {
pub fn to_i32(&self, ctx: &mut Interpreter) -> Result<i32> {
// This is the fast path, if the value is Integer we can just return it.
if let Value::Integer(number) = *self {
return Ok(number);
@ -914,7 +910,7 @@ impl Value {
/// Converts a value to a non-negative integer if it is a valid integer index value.
///
/// See: <https://tc39.es/ecma262/#sec-toindex>
pub fn to_index(&self, ctx: &mut Interpreter) -> Result<usize, Value> {
pub fn to_index(&self, ctx: &mut Interpreter) -> Result<usize> {
if self.is_undefined() {
return Ok(0);
}
@ -935,7 +931,7 @@ impl Value {
/// Converts argument to an integer suitable for use as the length of an array-like object.
///
/// See: <https://tc39.es/ecma262/#sec-tolength>
pub fn to_length(&self, ctx: &mut Interpreter) -> Result<usize, Value> {
pub fn to_length(&self, ctx: &mut Interpreter) -> Result<usize> {
// 1. Let len be ? ToInteger(argument).
let len = self.to_integer(ctx)?;
@ -951,7 +947,7 @@ impl Value {
/// Converts a value to an integral Number value.
///
/// See: <https://tc39.es/ecma262/#sec-tointeger>
pub fn to_integer(&self, ctx: &mut Interpreter) -> Result<f64, Value> {
pub fn to_integer(&self, ctx: &mut Interpreter) -> Result<f64> {
// 1. Let number be ? ToNumber(argument).
let number = self.to_number(ctx)?;
@ -975,7 +971,7 @@ impl Value {
/// This function is equivalent to the unary `+` operator (`+value`) in JavaScript
///
/// See: https://tc39.es/ecma262/#sec-tonumber
pub fn to_number(&self, ctx: &mut Interpreter) -> Result<f64, Value> {
pub fn to_number(&self, ctx: &mut Interpreter) -> Result<f64> {
match *self {
Value::Null => Ok(0.0),
Value::Undefined => Ok(f64::NAN),
@ -1003,7 +999,7 @@ impl Value {
/// This function is equivalent to `Number(value)` in JavaScript
///
/// See: <https://tc39.es/ecma262/#sec-tonumeric>
pub fn to_numeric_number(&self, ctx: &mut Interpreter) -> Result<f64, Value> {
pub fn to_numeric_number(&self, ctx: &mut Interpreter) -> Result<f64> {
let primitive = self.to_primitive(ctx, PreferredType::Number)?;
if let Some(ref bigint) = primitive.as_bigint() {
return Ok(bigint.to_f64());

38
boa/src/builtins/value/operations.rs

@ -6,7 +6,7 @@ use crate::builtins::{
impl Value {
#[inline]
pub fn add(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn add(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) + f64::from(*y)),
@ -43,7 +43,7 @@ impl Value {
}
#[inline]
pub fn sub(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn sub(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) - f64::from(*y)),
@ -71,7 +71,7 @@ impl Value {
}
#[inline]
pub fn mul(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn mul(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) * f64::from(*y)),
@ -99,7 +99,7 @@ impl Value {
}
#[inline]
pub fn div(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn div(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) / f64::from(*y)),
@ -127,7 +127,7 @@ impl Value {
}
#[inline]
pub fn rem(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn rem(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x % *y),
@ -155,7 +155,7 @@ impl Value {
}
#[inline]
pub fn pow(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn pow(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x).powi(*y)),
@ -181,7 +181,7 @@ impl Value {
}
#[inline]
pub fn bitand(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn bitand(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x & y),
@ -213,7 +213,7 @@ impl Value {
}
#[inline]
pub fn bitor(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn bitor(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x | y),
@ -245,7 +245,7 @@ impl Value {
}
#[inline]
pub fn bitxor(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn bitxor(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x ^ y),
@ -277,7 +277,7 @@ impl Value {
}
#[inline]
pub fn shl(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn shl(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x.wrapping_shl(*y as u32)),
@ -313,7 +313,7 @@ impl Value {
}
#[inline]
pub fn shr(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn shr(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x.wrapping_shr(*y as u32)),
@ -349,7 +349,7 @@ impl Value {
}
#[inline]
pub fn ushr(&self, other: &Self, ctx: &mut Interpreter) -> ResultValue {
pub fn ushr(&self, other: &Self, ctx: &mut Interpreter) -> Result<Value> {
Ok(match (self, other) {
// Fast path:
(Self::Integer(x), Self::Integer(y)) => {
@ -384,7 +384,7 @@ impl Value {
}
#[inline]
pub fn neg(&self, interpreter: &mut Interpreter) -> ResultValue {
pub fn neg(&self, interpreter: &mut Interpreter) -> Result<Value> {
Ok(match *self {
Self::Symbol(_) | Self::Undefined => Self::rational(NAN),
Self::Object(_) => Self::rational(match self.to_numeric_number(interpreter) {
@ -404,7 +404,7 @@ impl Value {
}
#[inline]
pub fn not(&self, _: &mut Interpreter) -> Result<bool, Value> {
pub fn not(&self, _: &mut Interpreter) -> Result<bool> {
Ok(!self.to_boolean())
}
@ -430,7 +430,7 @@ impl Value {
other: &Self,
left_first: bool,
ctx: &mut Interpreter,
) -> Result<AbstractRelation, Value> {
) -> Result<AbstractRelation> {
Ok(match (self, other) {
// Fast path (for some common operations):
(Self::Integer(x), Self::Integer(y)) => (x < y).into(),
@ -528,7 +528,7 @@ impl Value {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than
/// [spec]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
#[inline]
pub fn lt(&self, other: &Self, ctx: &mut Interpreter) -> Result<bool, Value> {
pub fn lt(&self, other: &Self, ctx: &mut Interpreter) -> Result<bool> {
match self.abstract_relation(other, true, ctx)? {
AbstractRelation::True => Ok(true),
AbstractRelation::False | AbstractRelation::Undefined => Ok(false),
@ -545,7 +545,7 @@ impl Value {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than_or_equal
/// [spec]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
#[inline]
pub fn le(&self, other: &Self, ctx: &mut Interpreter) -> Result<bool, Value> {
pub fn le(&self, other: &Self, ctx: &mut Interpreter) -> Result<bool> {
match other.abstract_relation(self, false, ctx)? {
AbstractRelation::False => Ok(true),
AbstractRelation::True | AbstractRelation::Undefined => Ok(false),
@ -562,7 +562,7 @@ impl Value {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than
/// [spec]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
#[inline]
pub fn gt(&self, other: &Self, ctx: &mut Interpreter) -> Result<bool, Value> {
pub fn gt(&self, other: &Self, ctx: &mut Interpreter) -> Result<bool> {
match other.abstract_relation(self, false, ctx)? {
AbstractRelation::True => Ok(true),
AbstractRelation::False | AbstractRelation::Undefined => Ok(false),
@ -579,7 +579,7 @@ impl Value {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than_or_equal
/// [spec]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
#[inline]
pub fn ge(&self, other: &Self, ctx: &mut Interpreter) -> Result<bool, Value> {
pub fn ge(&self, other: &Self, ctx: &mut Interpreter) -> Result<bool> {
match self.abstract_relation(other, true, ctx)? {
AbstractRelation::False => Ok(true),
AbstractRelation::True | AbstractRelation::Undefined => Ok(false),

6
boa/src/exec/array/mod.rs

@ -2,13 +2,13 @@
use super::{Executable, Interpreter};
use crate::{
builtins::{Array, ResultValue},
builtins::{Array, Value},
syntax::ast::node::{ArrayDecl, Node},
BoaProfiler,
BoaProfiler, Result,
};
impl Executable for ArrayDecl {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("ArrayDecl", "exec");
let array = Array::new_array(interpreter)?;
let mut elements = Vec::new();

8
boa/src/exec/block/mod.rs

@ -2,14 +2,12 @@
use super::{Executable, Interpreter, InterpreterState};
use crate::{
builtins::value::{ResultValue, Value},
environment::lexical_environment::new_declarative_environment,
syntax::ast::node::Block,
BoaProfiler,
builtins::value::Value, environment::lexical_environment::new_declarative_environment,
syntax::ast::node::Block, BoaProfiler, Result,
};
impl Executable for Block {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("Block", "exec");
{
let env = &mut interpreter.realm_mut().environment;

7
boa/src/exec/break_node/mod.rs

@ -1,14 +1,11 @@
use super::{Executable, Interpreter, InterpreterState};
use crate::{
builtins::value::{ResultValue, Value},
syntax::ast::node::Break,
};
use crate::{builtins::value::Value, syntax::ast::node::Break, Result};
#[cfg(test)]
mod tests;
impl Executable for Break {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
interpreter.set_current_state(InterpreterState::Break(self.label().map(String::from)));
Ok(Value::undefined())

6
boa/src/exec/call/mod.rs

@ -1,12 +1,12 @@
use super::{Executable, Interpreter, InterpreterState};
use crate::{
builtins::value::{ResultValue, Type},
builtins::value::{Type, Value},
syntax::ast::node::{Call, Node},
BoaProfiler,
BoaProfiler, Result,
};
impl Executable for Call {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("Call", "exec");
let (this, func) = match self.expr() {
Node::GetConstField(ref get_const_field) => {

7
boa/src/exec/conditional/mod.rs

@ -1,12 +1,9 @@
use super::{Executable, Interpreter};
use crate::{
builtins::{ResultValue, Value},
syntax::ast::node::If,
};
use crate::{builtins::Value, syntax::ast::node::If, Result};
use std::borrow::Borrow;
impl Executable for If {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
Ok(if self.cond().run(interpreter)?.borrow().to_boolean() {
self.body().run(interpreter)?
} else if let Some(ref else_e) = self.else_node() {

19
boa/src/exec/declaration/mod.rs

@ -2,19 +2,16 @@
use super::{Executable, Interpreter};
use crate::{
builtins::{
function::ThisMode,
value::{ResultValue, Value},
},
builtins::{function::ThisMode, value::Value},
environment::lexical_environment::VariableScope,
syntax::ast::node::{
ArrowFunctionDecl, ConstDeclList, FunctionDecl, FunctionExpr, LetDeclList, VarDeclList,
},
BoaProfiler,
BoaProfiler, Result,
};
impl Executable for FunctionDecl {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("FunctionDecl", "exec");
let val = interpreter.create_function(
self.parameters().to_vec(),
@ -42,7 +39,7 @@ impl Executable for FunctionDecl {
}
impl Executable for FunctionExpr {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let val = interpreter.create_function(
self.parameters().to_vec(),
self.body().to_vec(),
@ -60,7 +57,7 @@ impl Executable for FunctionExpr {
}
impl Executable for VarDeclList {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
for var in self.as_ref() {
let val = match var.init() {
Some(v) => v.run(interpreter)?,
@ -86,7 +83,7 @@ impl Executable for VarDeclList {
}
impl Executable for ConstDeclList {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
for decl in self.as_ref() {
let val = decl.init().run(interpreter)?;
@ -105,7 +102,7 @@ impl Executable for ConstDeclList {
}
impl Executable for LetDeclList {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
for var in self.as_ref() {
let val = match var.init() {
Some(v) => v.run(interpreter)?,
@ -126,7 +123,7 @@ impl Executable for LetDeclList {
}
impl Executable for ArrowFunctionDecl {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
Ok(interpreter.create_function(
self.params().to_vec(),
self.body().to_vec(),

8
boa/src/exec/exception.rs

@ -23,7 +23,7 @@ impl Interpreter {
}
/// Throws a `RangeError` with the specified message.
pub fn throw_range_error<M>(&mut self, message: M) -> ResultValue
pub fn throw_range_error<M>(&mut self, message: M) -> Result<Value>
where
M: Into<String>,
{
@ -45,7 +45,7 @@ impl Interpreter {
}
/// Throws a `TypeError` with the specified message.
pub fn throw_type_error<M>(&mut self, message: M) -> ResultValue
pub fn throw_type_error<M>(&mut self, message: M) -> Result<Value>
where
M: Into<String>,
{
@ -66,7 +66,7 @@ impl Interpreter {
}
/// Throws a `ReferenceError` with the specified message.
pub fn throw_reference_error<M>(&mut self, message: M) -> ResultValue
pub fn throw_reference_error<M>(&mut self, message: M) -> Result<Value>
where
M: Into<String>,
{
@ -87,7 +87,7 @@ impl Interpreter {
}
/// Throws a `SyntaxError` with the specified message.
pub fn throw_syntax_error<M>(&mut self, message: M) -> ResultValue
pub fn throw_syntax_error<M>(&mut self, message: M) -> Result<Value>
where
M: Into<String>,
{

7
boa/src/exec/field/mod.rs

@ -1,11 +1,12 @@
use super::{Executable, Interpreter};
use crate::{
builtins::value::{ResultValue, Type},
builtins::value::{Type, Value},
syntax::ast::node::{GetConstField, GetField},
Result,
};
impl Executable for GetConstField {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let mut obj = self.obj().run(interpreter)?;
if obj.get_type() != Type::Object {
obj = obj.to_object(interpreter)?;
@ -16,7 +17,7 @@ impl Executable for GetConstField {
}
impl Executable for GetField {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let mut obj = self.obj().run(interpreter)?;
if obj.get_type() != Type::Object {
obj = obj.to_object(interpreter)?;

4
boa/src/exec/identifier/mod.rs

@ -1,8 +1,8 @@
use super::{Executable, Interpreter};
use crate::{builtins::value::ResultValue, syntax::ast::node::identifier::Identifier};
use crate::{builtins::value::Value, syntax::ast::node::identifier::Identifier, Result};
impl Executable for Identifier {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
interpreter
.realm()
.environment

10
boa/src/exec/iteration/mod.rs

@ -2,10 +2,10 @@
use super::{Executable, Interpreter, InterpreterState};
use crate::{
builtins::value::{ResultValue, Value},
builtins::value::Value,
environment::lexical_environment::new_declarative_environment,
syntax::ast::node::{DoWhileLoop, ForLoop, WhileLoop},
BoaProfiler,
BoaProfiler, Result,
};
use std::borrow::Borrow;
@ -13,7 +13,7 @@ use std::borrow::Borrow;
mod tests;
impl Executable for ForLoop {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
// Create the block environment.
let _timer = BoaProfiler::global().start_event("ForLoop", "exec");
{
@ -64,7 +64,7 @@ impl Executable for ForLoop {
}
impl Executable for WhileLoop {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let mut result = Value::undefined();
while self.cond().run(interpreter)?.borrow().to_boolean() {
result = self.expr().run(interpreter)?;
@ -89,7 +89,7 @@ impl Executable for WhileLoop {
}
impl Executable for DoWhileLoop {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let mut result = self.body().run(interpreter)?;
match interpreter.get_current_state() {
InterpreterState::Break(_label) => {

23
boa/src/exec/mod.rs

@ -28,7 +28,7 @@ use crate::{
function::{Function as FunctionObject, FunctionBody, ThisMode},
object::{Object, ObjectData, PROTOTYPE},
property::PropertyKey,
value::{PreferredType, ResultValue, Type, Value},
value::{PreferredType, Type, Value},
Console,
},
realm::Realm,
@ -36,12 +36,13 @@ use crate::{
constant::Const,
node::{FormalParameter, Node, StatementList},
},
BoaProfiler,
BoaProfiler, Result,
};
use std::result::Result as StdResult;
pub trait Executable {
/// Runs this executable in the given executor.
fn run(&self, interpreter: &mut Interpreter) -> ResultValue;
fn run(&self, interpreter: &mut Interpreter) -> Result<Value>;
}
#[derive(Debug, Eq, PartialEq)]
@ -174,7 +175,7 @@ impl Interpreter {
f: &Value,
this: &Value,
arguments_list: &[Value],
) -> ResultValue {
) -> Result<Value> {
match *f {
Value::Object(ref obj) => {
let obj = obj.borrow();
@ -190,7 +191,7 @@ impl Interpreter {
/// Converts an array object into a rust vector of values.
///
/// This is useful for the spread operator, for any other object an `Err` is returned
pub(crate) fn extract_array_properties(&mut self, value: &Value) -> Result<Vec<Value>, ()> {
pub(crate) fn extract_array_properties(&mut self, value: &Value) -> StdResult<Vec<Value>, ()> {
if let Value::Object(ref x) = value {
// Check if object is array
if let ObjectData::Array = x.borrow().data {
@ -242,7 +243,11 @@ impl Interpreter {
/// - [ECMAScript][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinarytoprimitive
pub(crate) fn ordinary_to_primitive(&mut self, o: &Value, hint: PreferredType) -> ResultValue {
pub(crate) fn ordinary_to_primitive(
&mut self,
o: &Value,
hint: PreferredType,
) -> Result<Value> {
// 1. Assert: Type(O) is Object.
debug_assert!(o.get_type() == Type::Object);
// 2. Assert: Type(hint) is String and its value is either "string" or "number".
@ -286,7 +291,7 @@ impl Interpreter {
}
}
fn set_value(&mut self, node: &Node, value: Value) -> ResultValue {
fn set_value(&mut self, node: &Node, value: Value) -> Result<Value> {
match node {
Node::Identifier(ref name) => {
self.realm
@ -329,7 +334,7 @@ impl Interpreter {
/// [table]: https://tc39.es/ecma262/#table-14
/// [spec]: https://tc39.es/ecma262/#sec-requireobjectcoercible
#[inline]
pub fn require_object_coercible<'a>(&mut self, value: &'a Value) -> Result<&'a Value, Value> {
pub fn require_object_coercible<'a>(&mut self, value: &'a Value) -> Result<&'a Value> {
if value.is_null_or_undefined() {
Err(self.construct_type_error("cannot convert null or undefined to Object"))
} else {
@ -349,7 +354,7 @@ impl Interpreter {
}
impl Executable for Node {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("Executable", "exec");
match *self {
Node::Const(Const::Null) => Ok(Value::null()),

6
boa/src/exec/new/mod.rs

@ -2,14 +2,14 @@ use super::{Executable, Interpreter};
use crate::{
builtins::{
object::{ObjectData, PROTOTYPE},
value::{ResultValue, Value},
value::Value,
},
syntax::ast::node::New,
BoaProfiler,
BoaProfiler, Result,
};
impl Executable for New {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("New", "exec");
// let (callee, args) = match call.as_ref() {
// Node::Call(callee, args) => (callee, args),

5
boa/src/exec/object/mod.rs

@ -2,15 +2,16 @@
use super::{Executable, Interpreter};
use crate::{
builtins::value::{ResultValue, Value},
builtins::value::Value,
syntax::ast::node::MethodDefinitionKind,
syntax::ast::node::{Object, PropertyDefinition},
Result,
};
use std::borrow::Borrow;
impl Executable for Object {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let global_val = &interpreter
.realm()
.environment

17
boa/src/exec/operator/mod.rs

@ -4,17 +4,17 @@ mod tests;
use super::{Executable, Interpreter};
use crate::{
builtins::value::{ResultValue, Value},
builtins::value::Value,
environment::lexical_environment::VariableScope,
syntax::ast::{
node::{Assign, BinOp, Node, UnaryOp},
op::{self, AssignOp, BitOp, CompOp, LogOp, NumOp},
},
BoaProfiler,
BoaProfiler, Result,
};
impl Executable for Assign {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("Assign", "exec");
let val = self.rhs().run(interpreter)?;
match self.lhs() {
@ -50,7 +50,7 @@ impl Executable for Assign {
}
impl Executable for BinOp {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
match self.op() {
op::BinOp::Num(op) => {
let x = self.lhs().run(interpreter)?;
@ -150,7 +150,12 @@ impl Executable for BinOp {
impl BinOp {
/// Runs the assignment operators.
fn run_assign(op: AssignOp, x: Value, y: Value, interpreter: &mut Interpreter) -> ResultValue {
fn run_assign(
op: AssignOp,
x: Value,
y: Value,
interpreter: &mut Interpreter,
) -> Result<Value> {
match op {
AssignOp::Add => x.add(&y, interpreter),
AssignOp::Sub => x.sub(&y, interpreter),
@ -168,7 +173,7 @@ impl BinOp {
}
impl Executable for UnaryOp {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let x = self.target().run(interpreter)?;
Ok(match self.op() {

7
boa/src/exec/return_smt/mod.rs

@ -1,11 +1,8 @@
use super::{Executable, Interpreter, InterpreterState};
use crate::{
builtins::value::{ResultValue, Value},
syntax::ast::node::Return,
};
use crate::{builtins::value::Value, syntax::ast::node::Return, Result};
impl Executable for Return {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let result = match self.expr() {
Some(ref v) => v.run(interpreter),
None => Ok(Value::undefined()),

4
boa/src/exec/spread/mod.rs

@ -1,8 +1,8 @@
use super::{Executable, Interpreter};
use crate::{builtins::value::ResultValue, syntax::ast::node::Spread};
use crate::{builtins::value::Value, syntax::ast::node::Spread, Result};
impl Executable for Spread {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
// TODO: for now we can do nothing but return the value as-is
self.val().run(interpreter)
}

8
boa/src/exec/statement_list.rs

@ -1,14 +1,10 @@
//! Statement list execution.
use super::{Executable, Interpreter, InterpreterState};
use crate::{
builtins::value::{ResultValue, Value},
syntax::ast::node::StatementList,
BoaProfiler,
};
use crate::{builtins::value::Value, syntax::ast::node::StatementList, BoaProfiler, Result};
impl Executable for StatementList {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("StatementList", "exec");
let mut obj = Value::null();
interpreter.set_current_state(InterpreterState::Executing);

7
boa/src/exec/switch/mod.rs

@ -1,14 +1,11 @@
use super::{Executable, Interpreter, InterpreterState};
use crate::{
builtins::value::{ResultValue, Value},
syntax::ast::node::Switch,
};
use crate::{builtins::value::Value, syntax::ast::node::Switch, Result};
#[cfg(test)]
mod tests;
impl Executable for Switch {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let default = self.default();
let val = self.val().run(interpreter)?;
let mut result = Value::null();

4
boa/src/exec/throw/mod.rs

@ -1,9 +1,9 @@
use super::{Executable, Interpreter};
use crate::{builtins::value::ResultValue, syntax::ast::node::Throw};
use crate::{builtins::value::Value, syntax::ast::node::Throw, Result};
impl Executable for Throw {
#[inline]
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
Err(self.expr().run(interpreter)?)
}
}

6
boa/src/exec/try_node/mod.rs

@ -2,17 +2,17 @@
use super::{Executable, Interpreter};
use crate::{
builtins::value::ResultValue,
builtins::value::Value,
environment::lexical_environment::{new_declarative_environment, VariableScope},
syntax::ast::node::Try,
BoaProfiler,
BoaProfiler, Result,
};
#[cfg(test)]
mod tests;
impl Executable for Try {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue {
fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let _timer = BoaProfiler::global().start_event("Try", "exec");
let res = self.block().run(interpreter).map_or_else(
|err| {

11
boa/src/lib.rs

@ -41,15 +41,20 @@ pub mod profiler;
pub mod realm;
pub mod syntax;
use crate::{builtins::value::ResultValue, syntax::ast::node::StatementList};
use crate::{builtins::value::Value, syntax::ast::node::StatementList};
pub use crate::{
exec::{Executable, Interpreter},
profiler::BoaProfiler,
realm::Realm,
syntax::{lexer::Lexer, parser::Parser},
};
use std::result::Result as StdResult;
fn parser_expr(src: &str) -> Result<StatementList, String> {
/// The result of a Javascript expression is represented like this so it can succeed (`Ok`) or fail (`Err`)
#[must_use]
pub type Result<T> = StdResult<T, Value>;
fn parser_expr(src: &str) -> StdResult<StatementList, String> {
let mut lexer = Lexer::new(src);
lexer.lex().map_err(|e| format!("Syntax Error: {}", e))?;
let tokens = lexer.tokens;
@ -77,7 +82,7 @@ pub fn forward(engine: &mut Interpreter, src: &str) -> String {
/// Similar to `forward`, except the current value is returned instad of the string
/// If the interpreter fails parsing an error value is returned instead (error object)
#[allow(clippy::unit_arg, clippy::drop_copy)]
pub fn forward_val(engine: &mut Interpreter, src: &str) -> ResultValue {
pub fn forward_val(engine: &mut Interpreter, src: &str) -> Result<Value> {
let main_timer = BoaProfiler::global().start_event("Main", "Main");
// Setup executor
let result = match parser_expr(src) {

Loading…
Cancel
Save