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

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

@ -16,10 +16,10 @@ use crate::{
builtins::{ builtins::{
function::{make_builtin_fn, make_constructor_fn}, function::{make_builtin_fn, make_constructor_fn},
object::ObjectData, object::ObjectData,
value::{RcBigInt, ResultValue, Value}, value::{RcBigInt, Value},
}, },
exec::Interpreter, exec::Interpreter,
BoaProfiler, BoaProfiler, Result,
}; };
use gc::{unsafe_empty_trace, Finalize, Trace}; use gc::{unsafe_empty_trace, Finalize, Trace};
@ -61,7 +61,7 @@ impl BigInt {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-thisbigintvalue /// [spec]: https://tc39.es/ecma262/#sec-thisbigintvalue
#[inline] #[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 { match value {
// 1. If Type(value) is BigInt, return value. // 1. If Type(value) is BigInt, return value.
Value::BigInt(ref bigint) => return Ok(bigint.clone()), Value::BigInt(ref bigint) => return Ok(bigint.clone()),
@ -91,7 +91,7 @@ impl BigInt {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-bigint-objects /// [spec]: https://tc39.es/ecma262/#sec-bigint-objects
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/BigInt /// [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) { let data = match args.get(0) {
Some(ref value) => value.to_bigint(ctx)?, Some(ref value) => value.to_bigint(ctx)?,
None => RcBigInt::from(Self::from(0)), None => RcBigInt::from(Self::from(0)),
@ -110,7 +110,7 @@ impl BigInt {
/// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.tostring /// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/toString /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/toString
#[allow(clippy::wrong_self_convention)] #[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() { let radix = if !args.is_empty() {
args[0].to_integer(ctx)? as i32 args[0].to_integer(ctx)? as i32
} else { } else {
@ -135,7 +135,7 @@ impl BigInt {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.valueof /// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/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)?)) Ok(Value::from(Self::this_bigint_value(this, ctx)?))
} }
@ -146,7 +146,7 @@ impl BigInt {
/// [spec]: https://tc39.es/ecma262/#sec-bigint.asintn /// [spec]: https://tc39.es/ecma262/#sec-bigint.asintn
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asIntN /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asIntN
#[allow(clippy::wrong_self_convention)] #[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)?; let (modulo, bits) = Self::calculate_as_uint_n(args, ctx)?;
if bits > 0 && modulo >= BigInt::from(2).pow(&BigInt::from(bits as i64 - 1)) { 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 /// [spec]: https://tc39.es/ecma262/#sec-bigint.asuintn
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asUintN /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asUintN
#[allow(clippy::wrong_self_convention)] #[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)?; let (modulo, _) = Self::calculate_as_uint_n(args, ctx)?;
Ok(Value::from(modulo)) 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`. /// 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 /// Additionally to the wrapped unsigned value it returns the converted `bits` argument, so it
/// can be reused from the `as_int_n` method. /// 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; use std::convert::TryFrom;
let undefined_value = Value::undefined(); 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 super::function::{make_builtin_fn, make_constructor_fn};
use crate::{ use crate::{
builtins::{ builtins::{object::ObjectData, value::Value},
object::ObjectData,
value::{ResultValue, Value},
},
exec::Interpreter, exec::Interpreter,
BoaProfiler, BoaProfiler, Result,
}; };
/// Boolean implementation. /// Boolean implementation.
@ -39,7 +36,7 @@ impl Boolean {
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-thisbooleanvalue /// [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 { match value {
Value::Boolean(boolean) => return Ok(*boolean), Value::Boolean(boolean) => return Ok(*boolean),
Value::Object(ref object) => { Value::Object(ref object) => {
@ -61,7 +58,7 @@ impl Boolean {
this: &Value, this: &Value,
args: &[Value], args: &[Value],
_: &mut Interpreter, _: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
// Get the argument, if any // Get the argument, if any
let data = args.get(0).map(|x| x.to_boolean()).unwrap_or(false); let data = args.get(0).map(|x| x.to_boolean()).unwrap_or(false);
this.set_data(ObjectData::Boolean(data)); this.set_data(ObjectData::Boolean(data));
@ -78,7 +75,7 @@ impl Boolean {
/// [spec]: https://tc39.es/ecma262/#sec-boolean-object /// [spec]: https://tc39.es/ecma262/#sec-boolean-object
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString
#[allow(clippy::wrong_self_convention)] #[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)?; let boolean = Self::this_boolean_value(this, ctx)?;
Ok(Value::from(boolean.to_string())) Ok(Value::from(boolean.to_string()))
} }
@ -92,7 +89,7 @@ impl Boolean {
/// [spec]: https://tc39.es/ecma262/#sec-boolean.prototype.valueof /// [spec]: https://tc39.es/ecma262/#sec-boolean.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/valueOf /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/valueOf
#[inline] #[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)?)) Ok(Value::from(Self::this_boolean_value(this, ctx)?))
} }

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

@ -19,10 +19,10 @@ mod tests;
use crate::{ use crate::{
builtins::{ builtins::{
function::make_builtin_fn, function::make_builtin_fn,
value::{display_obj, RcString, ResultValue, Value}, value::{display_obj, RcString, Value},
}, },
exec::Interpreter, exec::Interpreter,
BoaProfiler, BoaProfiler, Result,
}; };
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::time::SystemTime; use std::time::SystemTime;
@ -59,8 +59,9 @@ pub(crate) fn logger(msg: LogMessage, console_state: &Console) {
} }
/// This represents the `console` formatter. /// 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)?; let target = data.get(0).cloned().unwrap_or_default().to_string(ctx)?;
match data.len() { match data.len() {
0 => Ok(String::new()), 0 => Ok(String::new()),
1 => Ok(target.to_string()), 1 => Ok(target.to_string()),
@ -153,7 +154,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#assert /// [spec]: https://console.spec.whatwg.org/#assert
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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(); let assertion = get_arg_at_index::<bool>(args, 0).unwrap_or_default();
if !assertion { if !assertion {
@ -184,7 +185,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#clear /// [spec]: https://console.spec.whatwg.org/#clear
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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(); ctx.console_mut().groups.clear();
Ok(Value::undefined()) Ok(Value::undefined())
} }
@ -199,7 +200,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#debug /// [spec]: https://console.spec.whatwg.org/#debug
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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()); logger(LogMessage::Log(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined()) Ok(Value::undefined())
} }
@ -214,7 +215,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#error /// [spec]: https://console.spec.whatwg.org/#error
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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()); logger(LogMessage::Error(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined()) Ok(Value::undefined())
} }
@ -229,7 +230,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#info /// [spec]: https://console.spec.whatwg.org/#info
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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()); logger(LogMessage::Info(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined()) Ok(Value::undefined())
} }
@ -244,7 +245,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#log /// [spec]: https://console.spec.whatwg.org/#log
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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()); logger(LogMessage::Log(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined()) Ok(Value::undefined())
} }
@ -259,7 +260,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#trace /// [spec]: https://console.spec.whatwg.org/#trace
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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() { if !args.is_empty() {
logger(LogMessage::Log(formatter(args, ctx)?), ctx.console()); logger(LogMessage::Log(formatter(args, ctx)?), ctx.console());
@ -283,7 +284,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#warn /// [spec]: https://console.spec.whatwg.org/#warn
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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()); logger(LogMessage::Warn(formatter(args, ctx)?), ctx.console());
Ok(Value::undefined()) Ok(Value::undefined())
} }
@ -298,7 +299,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#count /// [spec]: https://console.spec.whatwg.org/#count
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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) { let label = match args.get(0) {
Some(value) => value.to_string(ctx)?, Some(value) => value.to_string(ctx)?,
None => "default".into(), None => "default".into(),
@ -322,7 +323,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#countreset /// [spec]: https://console.spec.whatwg.org/#countreset
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/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) { let label = match args.get(0) {
Some(value) => value.to_string(ctx)?, Some(value) => value.to_string(ctx)?,
None => "default".into(), None => "default".into(),
@ -356,7 +357,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#time /// [spec]: https://console.spec.whatwg.org/#time
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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) { let label = match args.get(0) {
Some(value) => value.to_string(ctx)?, Some(value) => value.to_string(ctx)?,
None => "default".into(), None => "default".into(),
@ -385,7 +386,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#timelog /// [spec]: https://console.spec.whatwg.org/#timelog
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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) { let label = match args.get(0) {
Some(value) => value.to_string(ctx)?, Some(value) => value.to_string(ctx)?,
None => "default".into(), None => "default".into(),
@ -418,7 +419,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#timeend /// [spec]: https://console.spec.whatwg.org/#timeend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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) { let label = match args.get(0) {
Some(value) => value.to_string(ctx)?, Some(value) => value.to_string(ctx)?,
None => "default".into(), None => "default".into(),
@ -450,7 +451,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#group /// [spec]: https://console.spec.whatwg.org/#group
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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)?; let group_label = formatter(args, ctx)?;
logger( logger(
@ -472,7 +473,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#groupend /// [spec]: https://console.spec.whatwg.org/#groupend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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(); ctx.console_mut().groups.pop();
Ok(Value::undefined()) Ok(Value::undefined())
@ -488,7 +489,7 @@ impl Console {
/// ///
/// [spec]: https://console.spec.whatwg.org/#dir /// [spec]: https://console.spec.whatwg.org/#dir
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/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(); let undefined = Value::undefined();
logger( logger(
LogMessage::Info(display_obj(args.get(0).unwrap_or(&undefined), true)), 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}, function::{make_builtin_fn, make_constructor_fn},
object::ObjectData, object::ObjectData,
value::PreferredType, value::PreferredType,
ResultValue, Value, Value,
}, },
BoaProfiler, Interpreter, BoaProfiler, Interpreter, Result,
}; };
use chrono::{prelude::*, Duration, LocalResult}; use chrono::{prelude::*, Duration, LocalResult};
use gc::{unsafe_empty_trace, Finalize, Trace}; use gc::{unsafe_empty_trace, Finalize, Trace};
@ -40,13 +40,13 @@ fn ignore_ambiguity<T>(result: LocalResult<T>) -> Option<T> {
macro_rules! getter_method { macro_rules! getter_method {
($name:ident) => {{ ($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())) Ok(Value::from(this_time_value(this, ctx)?.$name()))
} }
get_value get_value
}}; }};
(Self::$name:ident) => {{ (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())) Ok(Value::from(Date::$name()))
} }
get_value get_value
@ -55,7 +55,7 @@ macro_rules! getter_method {
macro_rules! setter_method { macro_rules! setter_method {
($name:ident($($e:expr),* $(,)?)) => {{ ($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)?; let mut result = this_time_value(this, ctx)?;
result.$name( result.$name(
$( $(
@ -246,7 +246,7 @@ impl Date {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor /// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date /// [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() { if this.is_global() {
Self::make_date_string() Self::make_date_string()
} else if args.is_empty() { } else if args.is_empty() {
@ -268,7 +268,7 @@ impl Date {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor /// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date /// [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())) Ok(Value::from(Local::now().to_rfc3339()))
} }
@ -282,7 +282,7 @@ impl Date {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor /// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date /// [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(); let date = Date::default();
this.set_data(ObjectData::Date(date)); this.set_data(ObjectData::Date(date));
Ok(this.clone()) Ok(this.clone())
@ -302,7 +302,7 @@ impl Date {
this: &Value, this: &Value,
args: &[Value], args: &[Value],
ctx: &mut Interpreter, ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
let value = &args[0]; let value = &args[0];
let tv = match this_time_value(value, ctx) { let tv = match this_time_value(value, ctx) {
Ok(dt) => dt.0, Ok(dt) => dt.0,
@ -339,7 +339,7 @@ impl Date {
this: &Value, this: &Value,
args: &[Value], args: &[Value],
ctx: &mut Interpreter, ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
let year = args[0].to_number(ctx)?; let year = args[0].to_number(ctx)?;
let month = args[1].to_number(ctx)?; let month = args[1].to_number(ctx)?;
let day = args.get(2).map_or(Ok(1f64), |value| value.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 /// [spec]: https://tc39.es/ecma262/#sec-date.now
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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)) Ok(Value::from(Utc::now().timestamp_millis() as f64))
} }
@ -1180,7 +1180,7 @@ impl Date {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-date.parse /// [spec]: https://tc39.es/ecma262/#sec-date.parse
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 // This method is implementation-defined and discouraged, so we just require the same format as the string
// constructor. // constructor.
@ -1204,7 +1204,7 @@ impl Date {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-date.utc /// [spec]: https://tc39.es/ecma262/#sec-date.utc
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 let year = args
.get(0) .get(0)
.map_or(Ok(f64::NAN), |value| value.to_number(ctx))?; .map_or(Ok(f64::NAN), |value| value.to_number(ctx))?;
@ -1581,7 +1581,7 @@ impl Date {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-thistimevalue /// [spec]: https://tc39.es/ecma262/#sec-thistimevalue
#[inline] #[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 Value::Object(ref object) = value {
if let ObjectData::Date(ref date) = object.borrow().data { if let ObjectData::Date(ref date) = object.borrow().data {
return Ok(*date); return Ok(*date);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -5,10 +5,10 @@ use crate::{
builtins::{ builtins::{
object::{ObjectData, PROTOTYPE}, object::{ObjectData, PROTOTYPE},
property::{Attribute, Property}, property::{Attribute, Property},
value::{ResultValue, Value}, value::Value,
}, },
exec::Interpreter, exec::Interpreter,
BoaProfiler, BoaProfiler, Result,
}; };
use ordered_map::OrderedMap; use ordered_map::OrderedMap;
@ -44,7 +44,7 @@ impl Map {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.set /// [spec]: https://tc39.es/ecma262/#sec-map.prototype.set
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/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() { let (key, value) = match args.len() {
0 => (Value::Undefined, Value::Undefined), 0 => (Value::Undefined, Value::Undefined),
1 => (args[0].clone(), Value::Undefined), 1 => (args[0].clone(), Value::Undefined),
@ -77,7 +77,7 @@ impl Map {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.delete /// [spec]: https://tc39.es/ecma262/#sec-map.prototype.delete
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/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 undefined = Value::Undefined;
let key = match args.len() { let key = match args.len() {
0 => &undefined, 0 => &undefined,
@ -109,7 +109,7 @@ impl Map {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.get /// [spec]: https://tc39.es/ecma262/#sec-map.prototype.get
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/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 undefined = Value::Undefined;
let key = match args.len() { let key = match args.len() {
0 => &undefined, 0 => &undefined,
@ -140,7 +140,7 @@ impl Map {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.clear /// [spec]: https://tc39.es/ecma262/#sec-map.prototype.clear
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/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())); this.set_data(ObjectData::Map(OrderedMap::new()));
Self::set_size(this, 0); Self::set_size(this, 0);
@ -158,7 +158,7 @@ impl Map {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.has /// [spec]: https://tc39.es/ecma262/#sec-map.prototype.has
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/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 undefined = Value::Undefined;
let key = match args.len() { let key = match args.len() {
0 => &undefined, 0 => &undefined,
@ -189,7 +189,7 @@ impl Map {
this: &Value, this: &Value,
args: &[Value], args: &[Value],
interpreter: &mut Interpreter, interpreter: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
if args.is_empty() { if args.is_empty() {
return Err(Value::from("Missing argument for Map.prototype.forEach")); return Err(Value::from("Missing argument for Map.prototype.forEach"));
} }
@ -227,7 +227,7 @@ impl Map {
} }
/// Create a new 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 // Make a new Object which will internally represent the Array (mapping
// between indices and values): this creates an Object with no prototype // 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 //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math
use crate::{ use crate::{
builtins::{ builtins::{function::make_builtin_fn, value::Value},
function::make_builtin_fn,
value::{ResultValue, Value},
},
exec::Interpreter, exec::Interpreter,
BoaProfiler, BoaProfiler, Result,
}; };
use std::f64; use std::f64;
@ -40,7 +37,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.abs /// [spec]: https://tc39.es/ecma262/#sec-math.abs
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -57,7 +54,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.acos /// [spec]: https://tc39.es/ecma262/#sec-math.acos
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -74,7 +71,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.acosh /// [spec]: https://tc39.es/ecma262/#sec-math.acosh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -91,7 +88,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.asin /// [spec]: https://tc39.es/ecma262/#sec-math.asin
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -108,7 +105,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.asinh /// [spec]: https://tc39.es/ecma262/#sec-math.asinh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -125,7 +122,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.atan /// [spec]: https://tc39.es/ecma262/#sec-math.atan
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -142,7 +139,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.atanh /// [spec]: https://tc39.es/ecma262/#sec-math.atanh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -159,7 +156,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.atan2 /// [spec]: https://tc39.es/ecma262/#sec-math.atan2
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 ( Ok(match (
args.get(0).map(|x| x.to_number(ctx)).transpose()?, args.get(0).map(|x| x.to_number(ctx)).transpose()?,
args.get(1).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 /// [spec]: https://tc39.es/ecma262/#sec-math.cbrt
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -195,7 +192,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.ceil /// [spec]: https://tc39.es/ecma262/#sec-math.ceil
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -212,7 +209,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.clz32 /// [spec]: https://tc39.es/ecma262/#sec-math.clz32
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_u32(ctx)) .map(|x| x.to_u32(ctx))
@ -230,7 +227,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.cos /// [spec]: https://tc39.es/ecma262/#sec-math.cos
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -247,7 +244,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.cosh /// [spec]: https://tc39.es/ecma262/#sec-math.cosh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -264,7 +261,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.exp /// [spec]: https://tc39.es/ecma262/#sec-math.exp
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -283,7 +280,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.expm1 /// [spec]: https://tc39.es/ecma262/#sec-math.expm1
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -300,7 +297,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.floor /// [spec]: https://tc39.es/ecma262/#sec-math.floor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -317,7 +314,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.fround /// [spec]: https://tc39.es/ecma262/#sec-math.fround
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -334,7 +331,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.hypot /// [spec]: https://tc39.es/ecma262/#sec-math.hypot
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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; let mut result = 0f64;
for arg in args { for arg in args {
let x = arg.to_number(ctx)?; let x = arg.to_number(ctx)?;
@ -351,7 +348,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.imul /// [spec]: https://tc39.es/ecma262/#sec-math.imul
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 ( Ok(match (
args.get(0).map(|x| x.to_u32(ctx)).transpose()?, args.get(0).map(|x| x.to_u32(ctx)).transpose()?,
args.get(1).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 /// [spec]: https://tc39.es/ecma262/#sec-math.log
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -387,7 +384,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.log1p /// [spec]: https://tc39.es/ecma262/#sec-math.log1p
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -404,7 +401,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.log10 /// [spec]: https://tc39.es/ecma262/#sec-math.log10
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -421,7 +418,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.log2 /// [spec]: https://tc39.es/ecma262/#sec-math.log2
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -438,7 +435,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.max /// [spec]: https://tc39.es/ecma262/#sec-math.max
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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; let mut max = f64::NEG_INFINITY;
for arg in args { for arg in args {
let num = arg.to_number(ctx)?; let num = arg.to_number(ctx)?;
@ -455,7 +452,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.min /// [spec]: https://tc39.es/ecma262/#sec-math.min
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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; let mut min = f64::INFINITY;
for arg in args { for arg in args {
let num = arg.to_number(ctx)?; let num = arg.to_number(ctx)?;
@ -472,7 +469,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.pow /// [spec]: https://tc39.es/ecma262/#sec-math.pow
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 ( Ok(match (
args.get(0).map(|x| x.to_number(ctx)).transpose()?, args.get(0).map(|x| x.to_number(ctx)).transpose()?,
args.get(1).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 /// [spec]: https://tc39.es/ecma262/#sec-math.random
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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()) Ok(rand::random::<f64>().into())
} }
@ -503,7 +500,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.round /// [spec]: https://tc39.es/ecma262/#sec-math.round
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -520,7 +517,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.sign /// [spec]: https://tc39.es/ecma262/#sec-math.sign
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -546,7 +543,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.sin /// [spec]: https://tc39.es/ecma262/#sec-math.sin
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -563,7 +560,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.sinh /// [spec]: https://tc39.es/ecma262/#sec-math.sinh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -580,7 +577,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.sqrt /// [spec]: https://tc39.es/ecma262/#sec-math.sqrt
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -597,7 +594,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.tan /// [spec]: https://tc39.es/ecma262/#sec-math.tan
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -614,7 +611,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.tanh /// [spec]: https://tc39.es/ecma262/#sec-math.tanh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))
@ -631,7 +628,7 @@ impl Math {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-math.trunc /// [spec]: https://tc39.es/ecma262/#sec-math.trunc
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 Ok(args
.get(0) .get(0)
.map(|x| x.to_number(ctx)) .map(|x| x.to_number(ctx))

2
boa/src/builtins/mod.rs

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

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

@ -18,11 +18,7 @@ use super::{
object::ObjectData, object::ObjectData,
value::AbstractRelation, value::AbstractRelation,
}; };
use crate::{ use crate::{builtins::value::Value, exec::Interpreter, BoaProfiler, Result};
builtins::value::{ResultValue, Value},
exec::Interpreter,
BoaProfiler,
};
use num_traits::float::FloatCore; use num_traits::float::FloatCore;
mod conversions; mod conversions;
@ -106,7 +102,7 @@ impl Number {
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-thisnumbervalue /// [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 { match *value {
Value::Integer(integer) => return Ok(f64::from(integer)), Value::Integer(integer) => return Ok(f64::from(integer)),
Value::Rational(rational) => return Ok(rational), Value::Rational(rational) => return Ok(rational),
@ -133,7 +129,11 @@ impl Number {
/// `[[Construct]]` - Creates a Number instance /// `[[Construct]]` - Creates a Number instance
/// ///
/// `[[Call]]` - Creates a number primitive /// `[[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) { let data = match args.get(0) {
Some(ref value) => value.to_numeric_number(ctx)?, Some(ref value) => value.to_numeric_number(ctx)?,
None => 0.0, None => 0.0,
@ -158,7 +158,7 @@ impl Number {
this: &Value, this: &Value,
_args: &[Value], _args: &[Value],
ctx: &mut Interpreter, ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
let this_num = Self::this_number_value(this, ctx)?; let this_num = Self::this_number_value(this, ctx)?;
let this_str_num = Self::num_to_exponential(this_num); let this_str_num = Self::num_to_exponential(this_num);
Ok(Value::from(this_str_num)) Ok(Value::from(this_str_num))
@ -175,7 +175,7 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tofixed /// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tofixed
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed
#[allow(clippy::wrong_self_convention)] #[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 this_num = Self::this_number_value(this, ctx)?;
let precision = match args.get(0) { let precision = match args.get(0) {
Some(n) => match n.to_integer(ctx)? as i32 { Some(n) => match n.to_integer(ctx)? as i32 {
@ -206,7 +206,7 @@ impl Number {
this: &Value, this: &Value,
_args: &[Value], _args: &[Value],
ctx: &mut Interpreter, ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
let this_num = Self::this_number_value(this, ctx)?; let this_num = Self::this_number_value(this, ctx)?;
let this_str_num = format!("{}", this_num); let this_str_num = format!("{}", this_num);
Ok(Value::from(this_str_num)) Ok(Value::from(this_str_num))
@ -223,7 +223,11 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.toexponential /// [spec]: https://tc39.es/ecma262/#sec-number.prototype.toexponential
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision
#[allow(clippy::wrong_self_convention)] #[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 this_num = Self::this_number_value(this, ctx)?;
let _num_str_len = format!("{}", this_num).len(); let _num_str_len = format!("{}", this_num).len();
let _precision = match args.get(0) { let _precision = match args.get(0) {
@ -377,7 +381,7 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tostring /// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString
#[allow(clippy::wrong_self_convention)] #[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). // 1. Let x be ? thisNumberValue(this value).
let x = Self::this_number_value(this, ctx)?; let x = Self::this_number_value(this, ctx)?;
@ -432,7 +436,7 @@ impl Number {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.valueof /// [spec]: https://tc39.es/ecma262/#sec-number.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/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)?)) Ok(Value::from(Self::this_number_value(this, ctx)?))
} }
@ -450,7 +454,11 @@ impl Number {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-parseint-string-radix /// [spec]: https://tc39.es/ecma262/#sec-parseint-string-radix
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt /// [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)) { if let (Some(val), r) = (args.get(0), args.get(1)) {
let mut radix = if let Some(rx) = r { let mut radix = if let Some(rx) = r {
if let Value::Integer(i) = rx { if let Value::Integer(i) = rx {
@ -520,7 +528,7 @@ impl Number {
_this: &Value, _this: &Value,
args: &[Value], args: &[Value],
_ctx: &mut Interpreter, _ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
if let Some(val) = args.get(0) { if let Some(val) = args.get(0) {
match val { match val {
Value::String(s) => { Value::String(s) => {
@ -566,7 +574,7 @@ impl Number {
_this: &Value, _this: &Value,
args: &[Value], args: &[Value],
ctx: &mut Interpreter, ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
if let Some(value) = args.get(0) { if let Some(value) = args.get(0) {
let number = value.to_number(ctx)?; let number = value.to_number(ctx)?;
Ok(number.is_finite().into()) Ok(number.is_finite().into())
@ -593,7 +601,7 @@ impl Number {
_this: &Value, _this: &Value,
args: &[Value], args: &[Value],
ctx: &mut Interpreter, ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
if let Some(value) = args.get(0) { if let Some(value) = args.get(0) {
let number = value.to_number(ctx)?; let number = value.to_number(ctx)?;
Ok(number.is_nan().into()) Ok(number.is_nan().into())
@ -620,7 +628,7 @@ impl Number {
_this: &Value, _this: &Value,
args: &[Value], args: &[Value],
_ctx: &mut Interpreter, _ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
Ok(Value::from(if let Some(val) = args.get(0) { Ok(Value::from(if let Some(val) = args.get(0) {
match val { match val {
Value::Integer(_) => true, Value::Integer(_) => true,
@ -646,7 +654,7 @@ impl Number {
_this: &Value, _this: &Value,
args: &[Value], args: &[Value],
_ctx: &mut Interpreter, _ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
Ok(args.get(0).map_or(false, Self::is_integer).into()) Ok(args.get(0).map_or(false, Self::is_integer).into())
} }
@ -668,7 +676,7 @@ impl Number {
_this: &Value, _this: &Value,
args: &[Value], args: &[Value],
_ctx: &mut Interpreter, _ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
Ok(Value::from(if let Some(val) = args.get(0) { Ok(Value::from(if let Some(val) = args.get(0) {
match val { match val {
Value::Integer(_) => false, Value::Integer(_) => false,
@ -698,7 +706,7 @@ impl Number {
_this: &Value, _this: &Value,
args: &[Value], args: &[Value],
_ctx: &mut Interpreter, _ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
Ok(Value::from(match args.get(0) { Ok(Value::from(match args.get(0) {
Some(Value::Integer(_)) => true, Some(Value::Integer(_)) => true,
Some(Value::Rational(number)) if Self::is_float_integer(*number) => { 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, function::Function,
map::ordered_map::OrderedMap, map::ordered_map::OrderedMap,
property::Property, property::Property,
value::{RcBigInt, RcString, RcSymbol, ResultValue, Value}, value::{RcBigInt, RcString, RcSymbol, Value},
BigInt, Date, RegExp, BigInt, Date, RegExp,
}, },
exec::Interpreter, exec::Interpreter,
BoaProfiler, BoaProfiler, Result,
}; };
use gc::{Finalize, Trace}; use gc::{Finalize, Trace};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::fmt::{Debug, Display, Error, Formatter}; use std::fmt::{Debug, Display, Error, Formatter};
use std::result::Result as StdResult;
use super::function::{make_builtin_fn, make_constructor_fn}; use super::function::{make_builtin_fn, make_constructor_fn};
use crate::builtins::value::same_value; use crate::builtins::value::same_value;
@ -83,7 +84,7 @@ pub enum ObjectData {
} }
impl Display for ObjectData { impl Display for ObjectData {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { fn fmt(&self, f: &mut Formatter<'_>) -> StdResult<(), Error> {
write!( write!(
f, f,
"{}", "{}",
@ -211,7 +212,7 @@ impl Object {
/// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-toobject /// [spec]: https://tc39.es/ecma262/#sec-toobject
pub fn from(value: &Value) -> Result<Self, ()> { pub fn from(value: &Value) -> StdResult<Self, ()> {
match *value { match *value {
Value::Boolean(a) => Ok(Self::boolean(a)), Value::Boolean(a) => Ok(Self::boolean(a)),
Value::Rational(a) => Ok(Self::number(a)), Value::Rational(a) => Ok(Self::number(a)),
@ -440,7 +441,7 @@ impl Object {
} }
/// Create a new 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 let Some(arg) = args.get(0) {
if !arg.is_null_or_undefined() { if !arg.is_null_or_undefined() {
return Ok(Value::object(Object::from(arg).unwrap())); 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 /// [spec]: https://tc39.es/ecma262/#sec-object.create
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/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 prototype = args.get(0).cloned().unwrap_or_else(Value::undefined);
let properties = args.get(1).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 /// 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 x = args.get(0).cloned().unwrap_or_else(Value::undefined);
let y = args.get(1).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. /// 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"); let obj = args.get(0).expect("Cannot get object");
Ok(obj Ok(obj
.as_object() .as_object()
@ -500,7 +501,7 @@ pub fn get_prototype_of(_: &Value, args: &[Value], _: &mut Interpreter) -> Resul
} }
/// Set the `prototype` of an object. /// 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 obj = args.get(0).expect("Cannot get object").clone();
let proto = args.get(1).expect("Cannot get object").clone(); let proto = args.get(1).expect("Cannot get object").clone();
obj.as_object_mut().unwrap().prototype = proto; 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 /// 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 obj = args.get(0).expect("Cannot get object");
let prop = args.get(1).expect("Cannot get object").to_string(ctx)?; let prop = args.get(1).expect("Cannot get object").to_string(ctx)?;
let desc = Property::from(args.get(2).expect("Cannot get object")); 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 /// [spec]: https://tc39.es/ecma262/#sec-object.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/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. // FIXME: it should not display the object.
Ok(Value::from(this.display().to_string())) Ok(this.display().to_string().into())
} }
/// `Object.prototype.hasOwnPrototype( property )` /// `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 /// [spec]: https://tc39.es/ecma262/#sec-object.prototype.hasownproperty
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/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() { let prop = if args.is_empty() {
None None
} else { } 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) { let key = match args.get(0) {
None => return Ok(Value::from(false)), None => return Ok(Value::from(false)),
Some(key) => key, Some(key) => key,

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

@ -16,10 +16,10 @@ use crate::{
builtins::{ builtins::{
object::{InternalState, ObjectData}, object::{InternalState, ObjectData},
property::Property, property::Property,
value::{RcString, ResultValue, Value}, value::{RcString, Value},
}, },
exec::Interpreter, exec::Interpreter,
BoaProfiler, BoaProfiler, Result,
}; };
use gc::{unsafe_empty_trace, Finalize, Trace}; use gc::{unsafe_empty_trace, Finalize, Trace};
@ -74,7 +74,7 @@ impl RegExp {
pub(crate) const LENGTH: usize = 2; pub(crate) const LENGTH: usize = 2;
/// Create a new `RegExp` /// 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 arg = args.get(0).ok_or_else(Value::undefined)?;
let mut regex_body = String::new(); let mut regex_body = String::new();
let mut regex_flags = String::new(); let mut regex_flags = String::new();
@ -171,7 +171,7 @@ impl RegExp {
// /// // ///
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.dotAll // /// [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 // /// [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))) // 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 // /// [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 // /// [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 // /// [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()))) // 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 // /// [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 // /// [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))) // 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 // /// [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 // /// [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))) // 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 // /// [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 // /// [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))) // 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 // /// [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 // /// [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")) // Ok(this.get_internal_slot("OriginalSource"))
// } // }
@ -257,7 +257,7 @@ impl RegExp {
// /// // ///
// /// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.sticky // /// [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 // /// [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))) // 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 // /// [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 // /// [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))) // 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 /// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.test
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/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 let arg_str = args
.get(0) .get(0)
.expect("could not get argument") .expect("could not get argument")
@ -327,7 +327,7 @@ impl RegExp {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.exec /// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.exec
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/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 let arg_str = args
.get(0) .get(0)
.expect("could not get argument") .expect("could not get argument")
@ -383,7 +383,7 @@ impl RegExp {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype-@@match /// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype-@@match
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@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 (matcher, flags) = if let Some(object) = this.as_object() {
let regex = object.as_regexp().unwrap(); let regex = object.as_regexp().unwrap();
(regex.matcher.clone(), regex.flags.clone()) (regex.matcher.clone(), regex.flags.clone())
@ -415,7 +415,7 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.tostring /// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/toString /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/toString
#[allow(clippy::wrong_self_convention)] #[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 (body, flags) = if let Some(object) = this.as_object() {
let regex = object.as_regexp().unwrap(); let regex = object.as_regexp().unwrap();
(regex.original_source.clone(), regex.flags.clone()) (regex.original_source.clone(), regex.flags.clone())
@ -436,7 +436,7 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-regexp-prototype-matchall /// [spec]: https://tc39.es/ecma262/#sec-regexp-prototype-matchall
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@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 // 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 matches = if let Some(object) = this.as_object() {
let regex = object.as_regexp().unwrap(); let regex = object.as_regexp().unwrap();
let mut matches = Vec::new(); let mut matches = Vec::new();

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

@ -17,11 +17,11 @@ use crate::{
builtins::{ builtins::{
object::{Object, ObjectData}, object::{Object, ObjectData},
property::Property, property::Property,
value::{RcString, ResultValue, Value}, value::{RcString, Value},
RegExp, RegExp,
}, },
exec::Interpreter, exec::Interpreter,
BoaProfiler, BoaProfiler, Result,
}; };
use regex::Regex; use regex::Regex;
use std::string::String as StdString; 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` /// which can differ in JavaScript engines. In Boa it is `2^32 - 1`
pub(crate) const MAX_STRING_LENGTH: f64 = u32::MAX as f64; 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 { match this {
Value::String(ref string) => return Ok(string.clone()), Value::String(ref string) => return Ok(string.clone()),
Value::Object(ref object) => { Value::Object(ref object) => {
@ -67,7 +67,11 @@ impl String {
/// ///
/// [[Call]] - Returns a new native `string` /// [[Call]] - Returns a new native `string`
/// <https://tc39.es/ecma262/#sec-string-constructor-string-value> /// <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 // 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) // to its Javascript Identifier (global constructor method name)
let string = match args.get(0) { let string = match args.get(0) {
@ -87,7 +91,7 @@ impl String {
/// Get the string value to a primitive string /// Get the string value to a primitive string
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
#[inline] #[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 // Get String from String Object and send it back as a new value
Ok(Value::from(Self::this_string_value(this, ctx)?)) Ok(Value::from(Self::this_string_value(this, ctx)?))
} }
@ -108,7 +112,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charat /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
@ -150,7 +154,11 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charcodeat /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charcodeat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
@ -190,7 +198,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.concat /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.concat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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 object = ctx.require_object_coercible(this)?;
let mut string = object.to_string(ctx)?.to_string(); let mut string = object.to_string(ctx)?.to_string();
@ -212,7 +220,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.repeat /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.repeat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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 object = ctx.require_object_coercible(this)?;
let string = object.to_string(ctx)?; let string = object.to_string(ctx)?;
@ -246,7 +254,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.slice /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.slice
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
@ -296,7 +304,11 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.startswith /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.startswith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
@ -339,7 +351,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.endswith /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.endswith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
@ -385,7 +397,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.includes /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.includes
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
@ -447,7 +459,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.replace /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.replace
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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 // TODO: Support Symbol replacer
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
if args.is_empty() { if args.is_empty() {
@ -550,7 +562,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.indexof /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.indexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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 this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?; let string = this.to_string(ctx)?;
@ -597,7 +609,7 @@ impl String {
this: &Value, this: &Value,
args: &[Value], args: &[Value],
ctx: &mut Interpreter, ctx: &mut Interpreter,
) -> ResultValue { ) -> Result<Value> {
let this = ctx.require_object_coercible(this)?; let this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?; let string = this.to_string(ctx)?;
@ -638,7 +650,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.match /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.match
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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 /// [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)?; let re = RegExp::make_regexp(&Value::from(Object::default()), &[args[0].clone()], ctx)?;
RegExp::r#match(&re, this.to_string(ctx)?, ctx) RegExp::r#match(&re, this.to_string(ctx)?, ctx)
} }
@ -652,7 +664,7 @@ impl String {
max_length: i32, max_length: i32,
fill_string: Option<RcString>, fill_string: Option<RcString>,
at_start: bool, at_start: bool,
) -> ResultValue { ) -> Result<Value> {
let primitive_length = primitive.len() as i32; let primitive_length = primitive.len() as i32;
if max_length <= primitive_length { if max_length <= primitive_length {
@ -689,7 +701,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padend /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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)?; let primitive = this.to_string(ctx)?;
if args.is_empty() { if args.is_empty() {
return Err(Value::from("padEnd requires maxLength argument")); return Err(Value::from("padEnd requires maxLength argument"));
@ -716,7 +728,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padstart /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padstart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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)?; let primitive = this.to_string(ctx)?;
if args.is_empty() { if args.is_empty() {
return Err(Value::from("padStart requires maxLength argument")); return Err(Value::from("padStart requires maxLength argument"));
@ -763,7 +775,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trim /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trim
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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 this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?; let string = this.to_string(ctx)?;
Ok(Value::from( Ok(Value::from(
@ -783,7 +795,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimstart /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimstart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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 this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?; let string = this.to_string(ctx)?;
Ok(Value::from( Ok(Value::from(
@ -803,7 +815,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimend /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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 this = ctx.require_object_coercible(this)?;
let string = this.to_string(ctx)?; let string = this.to_string(ctx)?;
Ok(Value::from( Ok(Value::from(
@ -822,7 +834,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.tolowercase /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.tolowercase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase
#[allow(clippy::wrong_self_convention)] #[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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let this_str = this.to_string(ctx)?; let this_str = this.to_string(ctx)?;
@ -844,7 +856,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.toUppercase /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.toUppercase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase
#[allow(clippy::wrong_self_convention)] #[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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let this_str = this.to_string(ctx)?; let this_str = this.to_string(ctx)?;
@ -863,7 +875,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substring /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
@ -912,7 +924,7 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substr /// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substr
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr
/// <https://tc39.es/ecma262/#sec-string.prototype.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. // 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 // Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(ctx)?; let primitive_val = this.to_string(ctx)?;
@ -968,7 +980,7 @@ impl String {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.value_of /// [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 /// [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 // Use the to_string method because it is specified to do the same thing in this case
Self::to_string(this, args, ctx) 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 /// [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 /// [cg]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges
// TODO: update this method to return iterator // 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) { let re: Value = match args.get(0) {
Some(arg) => { Some(arg) => {
if arg.is_null() { 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 super::function::{make_builtin_fn, make_constructor_fn};
use crate::{ use crate::{
builtins::value::{RcString, RcSymbol, ResultValue, Value}, builtins::value::{RcString, RcSymbol, Value},
exec::Interpreter, exec::Interpreter,
BoaProfiler, BoaProfiler, Result,
}; };
use gc::{Finalize, Trace}; use gc::{Finalize, Trace};
@ -46,7 +46,7 @@ impl Symbol {
self.1 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 { match value {
Value::Symbol(ref symbol) => return Ok(symbol.clone()), Value::Symbol(ref symbol) => return Ok(symbol.clone()),
Value::Object(ref object) => { Value::Object(ref object) => {
@ -72,7 +72,7 @@ impl Symbol {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-symbol-description /// [spec]: https://tc39.es/ecma262/#sec-symbol-description
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/Symbol /// [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) { let description = match args.get(0) {
Some(ref value) if !value.is_undefined() => Some(value.to_string(ctx)?), Some(ref value) if !value.is_undefined() => Some(value.to_string(ctx)?),
_ => None, _ => None,
@ -92,7 +92,7 @@ impl Symbol {
/// [spec]: https://tc39.es/ecma262/#sec-symbol.prototype.tostring /// [spec]: https://tc39.es/ecma262/#sec-symbol.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toString /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toString
#[allow(clippy::wrong_self_convention)] #[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 symbol = Self::this_symbol_value(this, ctx)?;
let description = symbol.description().unwrap_or(""); let description = symbol.description().unwrap_or("");
Ok(Value::from(format!("Symbol({})", description))) 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 { impl From<f64> for Value {
fn from(value: f64) -> Self { fn from(value: f64) -> Self {
Self::rational(value) 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. /// This method is executed when doing abstract equality comparisons with the `==` operator.
/// For more information, check <https://tc39.es/ecma262/#sec-abstract-equality-comparison> /// For more information, check <https://tc39.es/ecma262/#sec-abstract-equality-comparison>
#[allow(clippy::float_cmp)] #[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 // 1. If Type(x) is the same as Type(y), then
// a. Return the result of performing Strict Equality Comparison x === y. // a. Return the result of performing Strict Equality Comparison x === y.
if self.get_type() == other.get_type() { if self.get_type() == other.get_type() {

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

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

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

@ -6,7 +6,7 @@ use crate::builtins::{
impl Value { impl Value {
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) + f64::from(*y)), (Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) + f64::from(*y)),
@ -43,7 +43,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) - f64::from(*y)), (Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) - f64::from(*y)),
@ -71,7 +71,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) * f64::from(*y)), (Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) * f64::from(*y)),
@ -99,7 +99,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) / f64::from(*y)), (Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x) / f64::from(*y)),
@ -127,7 +127,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x % *y), (Self::Integer(x), Self::Integer(y)) => Self::integer(x % *y),
@ -155,7 +155,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x).powi(*y)), (Self::Integer(x), Self::Integer(y)) => Self::rational(f64::from(*x).powi(*y)),
@ -181,7 +181,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x & y), (Self::Integer(x), Self::Integer(y)) => Self::integer(x & y),
@ -213,7 +213,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x | y), (Self::Integer(x), Self::Integer(y)) => Self::integer(x | y),
@ -245,7 +245,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x ^ y), (Self::Integer(x), Self::Integer(y)) => Self::integer(x ^ y),
@ -277,7 +277,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x.wrapping_shl(*y as u32)), (Self::Integer(x), Self::Integer(y)) => Self::integer(x.wrapping_shl(*y as u32)),
@ -313,7 +313,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => Self::integer(x.wrapping_shr(*y as u32)), (Self::Integer(x), Self::Integer(y)) => Self::integer(x.wrapping_shr(*y as u32)),
@ -349,7 +349,7 @@ impl Value {
} }
#[inline] #[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) { Ok(match (self, other) {
// Fast path: // Fast path:
(Self::Integer(x), Self::Integer(y)) => { (Self::Integer(x), Self::Integer(y)) => {
@ -384,7 +384,7 @@ impl Value {
} }
#[inline] #[inline]
pub fn neg(&self, interpreter: &mut Interpreter) -> ResultValue { pub fn neg(&self, interpreter: &mut Interpreter) -> Result<Value> {
Ok(match *self { Ok(match *self {
Self::Symbol(_) | Self::Undefined => Self::rational(NAN), Self::Symbol(_) | Self::Undefined => Self::rational(NAN),
Self::Object(_) => Self::rational(match self.to_numeric_number(interpreter) { Self::Object(_) => Self::rational(match self.to_numeric_number(interpreter) {
@ -404,7 +404,7 @@ impl Value {
} }
#[inline] #[inline]
pub fn not(&self, _: &mut Interpreter) -> Result<bool, Value> { pub fn not(&self, _: &mut Interpreter) -> Result<bool> {
Ok(!self.to_boolean()) Ok(!self.to_boolean())
} }
@ -430,7 +430,7 @@ impl Value {
other: &Self, other: &Self,
left_first: bool, left_first: bool,
ctx: &mut Interpreter, ctx: &mut Interpreter,
) -> Result<AbstractRelation, Value> { ) -> Result<AbstractRelation> {
Ok(match (self, other) { Ok(match (self, other) {
// Fast path (for some common operations): // Fast path (for some common operations):
(Self::Integer(x), Self::Integer(y)) => (x < y).into(), (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 /// [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 /// [spec]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
#[inline] #[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)? { match self.abstract_relation(other, true, ctx)? {
AbstractRelation::True => Ok(true), AbstractRelation::True => Ok(true),
AbstractRelation::False | AbstractRelation::Undefined => Ok(false), 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 /// [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 /// [spec]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
#[inline] #[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)? { match other.abstract_relation(self, false, ctx)? {
AbstractRelation::False => Ok(true), AbstractRelation::False => Ok(true),
AbstractRelation::True | AbstractRelation::Undefined => Ok(false), 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 /// [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 /// [spec]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
#[inline] #[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)? { match other.abstract_relation(self, false, ctx)? {
AbstractRelation::True => Ok(true), AbstractRelation::True => Ok(true),
AbstractRelation::False | AbstractRelation::Undefined => Ok(false), 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 /// [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 /// [spec]: https://tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation
#[inline] #[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)? { match self.abstract_relation(other, true, ctx)? {
AbstractRelation::False => Ok(true), AbstractRelation::False => Ok(true),
AbstractRelation::True | AbstractRelation::Undefined => Ok(false), AbstractRelation::True | AbstractRelation::Undefined => Ok(false),

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

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

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

@ -2,14 +2,12 @@
use super::{Executable, Interpreter, InterpreterState}; use super::{Executable, Interpreter, InterpreterState};
use crate::{ use crate::{
builtins::value::{ResultValue, Value}, builtins::value::Value, environment::lexical_environment::new_declarative_environment,
environment::lexical_environment::new_declarative_environment, syntax::ast::node::Block, BoaProfiler, Result,
syntax::ast::node::Block,
BoaProfiler,
}; };
impl Executable for Block { 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 _timer = BoaProfiler::global().start_event("Block", "exec");
{ {
let env = &mut interpreter.realm_mut().environment; 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 super::{Executable, Interpreter, InterpreterState};
use crate::{ use crate::{builtins::value::Value, syntax::ast::node::Break, Result};
builtins::value::{ResultValue, Value},
syntax::ast::node::Break,
};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
impl Executable for Break { 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))); interpreter.set_current_state(InterpreterState::Break(self.label().map(String::from)));
Ok(Value::undefined()) Ok(Value::undefined())

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

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

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

@ -1,12 +1,9 @@
use super::{Executable, Interpreter}; use super::{Executable, Interpreter};
use crate::{ use crate::{builtins::Value, syntax::ast::node::If, Result};
builtins::{ResultValue, Value},
syntax::ast::node::If,
};
use std::borrow::Borrow; use std::borrow::Borrow;
impl Executable for If { 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() { Ok(if self.cond().run(interpreter)?.borrow().to_boolean() {
self.body().run(interpreter)? self.body().run(interpreter)?
} else if let Some(ref else_e) = self.else_node() { } 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 super::{Executable, Interpreter};
use crate::{ use crate::{
builtins::{ builtins::{function::ThisMode, value::Value},
function::ThisMode,
value::{ResultValue, Value},
},
environment::lexical_environment::VariableScope, environment::lexical_environment::VariableScope,
syntax::ast::node::{ syntax::ast::node::{
ArrowFunctionDecl, ConstDeclList, FunctionDecl, FunctionExpr, LetDeclList, VarDeclList, ArrowFunctionDecl, ConstDeclList, FunctionDecl, FunctionExpr, LetDeclList, VarDeclList,
}, },
BoaProfiler, BoaProfiler, Result,
}; };
impl Executable for FunctionDecl { 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 _timer = BoaProfiler::global().start_event("FunctionDecl", "exec");
let val = interpreter.create_function( let val = interpreter.create_function(
self.parameters().to_vec(), self.parameters().to_vec(),
@ -42,7 +39,7 @@ impl Executable for FunctionDecl {
} }
impl Executable for FunctionExpr { impl Executable for FunctionExpr {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue { fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
let val = interpreter.create_function( let val = interpreter.create_function(
self.parameters().to_vec(), self.parameters().to_vec(),
self.body().to_vec(), self.body().to_vec(),
@ -60,7 +57,7 @@ impl Executable for FunctionExpr {
} }
impl Executable for VarDeclList { 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() { for var in self.as_ref() {
let val = match var.init() { let val = match var.init() {
Some(v) => v.run(interpreter)?, Some(v) => v.run(interpreter)?,
@ -86,7 +83,7 @@ impl Executable for VarDeclList {
} }
impl Executable for ConstDeclList { 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() { for decl in self.as_ref() {
let val = decl.init().run(interpreter)?; let val = decl.init().run(interpreter)?;
@ -105,7 +102,7 @@ impl Executable for ConstDeclList {
} }
impl Executable for LetDeclList { 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() { for var in self.as_ref() {
let val = match var.init() { let val = match var.init() {
Some(v) => v.run(interpreter)?, Some(v) => v.run(interpreter)?,
@ -126,7 +123,7 @@ impl Executable for LetDeclList {
} }
impl Executable for ArrowFunctionDecl { impl Executable for ArrowFunctionDecl {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue { fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
Ok(interpreter.create_function( Ok(interpreter.create_function(
self.params().to_vec(), self.params().to_vec(),
self.body().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. /// 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 where
M: Into<String>, M: Into<String>,
{ {
@ -45,7 +45,7 @@ impl Interpreter {
} }
/// Throws a `TypeError` with the specified message. /// 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 where
M: Into<String>, M: Into<String>,
{ {
@ -66,7 +66,7 @@ impl Interpreter {
} }
/// Throws a `ReferenceError` with the specified message. /// 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 where
M: Into<String>, M: Into<String>,
{ {
@ -87,7 +87,7 @@ impl Interpreter {
} }
/// Throws a `SyntaxError` with the specified message. /// 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 where
M: Into<String>, M: Into<String>,
{ {

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

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

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

@ -1,8 +1,8 @@
use super::{Executable, Interpreter}; 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 { impl Executable for Identifier {
fn run(&self, interpreter: &mut Interpreter) -> ResultValue { fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
interpreter interpreter
.realm() .realm()
.environment .environment

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

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

23
boa/src/exec/mod.rs

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

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

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

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

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

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

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

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

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

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

@ -1,8 +1,8 @@
use super::{Executable, Interpreter}; 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 { 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 // TODO: for now we can do nothing but return the value as-is
self.val().run(interpreter) self.val().run(interpreter)
} }

8
boa/src/exec/statement_list.rs

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

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

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

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

@ -1,9 +1,9 @@
use super::{Executable, Interpreter}; 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 { impl Executable for Throw {
#[inline] #[inline]
fn run(&self, interpreter: &mut Interpreter) -> ResultValue { fn run(&self, interpreter: &mut Interpreter) -> Result<Value> {
Err(self.expr().run(interpreter)?) Err(self.expr().run(interpreter)?)
} }
} }

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

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

11
boa/src/lib.rs

@ -41,15 +41,20 @@ pub mod profiler;
pub mod realm; pub mod realm;
pub mod syntax; pub mod syntax;
use crate::{builtins::value::ResultValue, syntax::ast::node::StatementList}; use crate::{builtins::value::Value, syntax::ast::node::StatementList};
pub use crate::{ pub use crate::{
exec::{Executable, Interpreter}, exec::{Executable, Interpreter},
profiler::BoaProfiler, profiler::BoaProfiler,
realm::Realm, realm::Realm,
syntax::{lexer::Lexer, parser::Parser}, 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); let mut lexer = Lexer::new(src);
lexer.lex().map_err(|e| format!("Syntax Error: {}", e))?; lexer.lex().map_err(|e| format!("Syntax Error: {}", e))?;
let tokens = lexer.tokens; 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 /// 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) /// If the interpreter fails parsing an error value is returned instead (error object)
#[allow(clippy::unit_arg, clippy::drop_copy)] #[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"); let main_timer = BoaProfiler::global().start_event("Main", "Main");
// Setup executor // Setup executor
let result = match parser_expr(src) { let result = match parser_expr(src) {

Loading…
Cancel
Save