Browse Source

Rename `Value` to `JsValue` (#1457)

pull/1451/head
Halid Odat 3 years ago committed by GitHub
parent
commit
62ad20cfde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      boa/examples/classes.rs
  2. 4
      boa/examples/closures.rs
  3. 8
      boa/src/bigint.rs
  4. 34
      boa/src/builtins/array/array_iterator.rs
  5. 258
      boa/src/builtins/array/mod.rs
  6. 80
      boa/src/builtins/array/tests.rs
  7. 52
      boa/src/builtins/bigint/mod.rs
  8. 36
      boa/src/builtins/boolean/mod.rs
  9. 4
      boa/src/builtins/boolean/tests.rs
  10. 94
      boa/src/builtins/console/mod.rs
  11. 27
      boa/src/builtins/console/tests.rs
  12. 64
      boa/src/builtins/date/mod.rs
  13. 110
      boa/src/builtins/date/tests.rs
  14. 12
      boa/src/builtins/error/eval.rs
  15. 18
      boa/src/builtins/error/mod.rs
  16. 12
      boa/src/builtins/error/range.rs
  17. 12
      boa/src/builtins/error/reference.rs
  18. 12
      boa/src/builtins/error/syntax.rs
  19. 12
      boa/src/builtins/error/type.rs
  20. 12
      boa/src/builtins/error/uri.rs
  21. 32
      boa/src/builtins/function/mod.rs
  22. 4
      boa/src/builtins/global_this/mod.rs
  23. 4
      boa/src/builtins/infinity/mod.rs
  24. 24
      boa/src/builtins/iterable/mod.rs
  25. 60
      boa/src/builtins/json/mod.rs
  26. 13
      boa/src/builtins/json/tests.rs
  27. 34
      boa/src/builtins/map/map_iterator.rs
  28. 106
      boa/src/builtins/map/mod.rs
  29. 18
      boa/src/builtins/map/ordered_map.rs
  30. 74
      boa/src/builtins/math/mod.rs
  31. 4
      boa/src/builtins/mod.rs
  32. 4
      boa/src/builtins/nan/mod.rs
  33. 184
      boa/src/builtins/number/mod.rs
  34. 26
      boa/src/builtins/object/for_in_iterator.rs
  35. 122
      boa/src/builtins/object/mod.rs
  36. 6
      boa/src/builtins/object/tests.rs
  37. 86
      boa/src/builtins/reflect/mod.rs
  38. 185
      boa/src/builtins/regexp/mod.rs
  39. 30
      boa/src/builtins/regexp/regexp_string_iterator.rs
  40. 70
      boa/src/builtins/set/mod.rs
  41. 34
      boa/src/builtins/set/set_iterator.rs
  42. 312
      boa/src/builtins/string/mod.rs
  43. 30
      boa/src/builtins/string/string_iterator.rs
  44. 36
      boa/src/builtins/symbol/mod.rs
  45. 6
      boa/src/builtins/undefined/mod.rs
  46. 6
      boa/src/bytecompiler.rs
  47. 18
      boa/src/class.rs
  48. 53
      boa/src/context.rs
  49. 19
      boa/src/environment/declarative_environment_record.rs
  50. 21
      boa/src/environment/environment_record_trait.rs
  51. 35
      boa/src/environment/function_environment_record.rs
  52. 25
      boa/src/environment/global_environment_record.rs
  53. 10
      boa/src/environment/lexical_environment.rs
  54. 27
      boa/src/environment/object_environment_record.rs
  55. 4
      boa/src/exec/mod.rs
  56. 66
      boa/src/exec/tests.rs
  57. 6
      boa/src/lib.rs
  58. 50
      boa/src/object/gcobject.rs
  59. 46
      boa/src/object/internal_methods.rs
  60. 56
      boa/src/object/mod.rs
  61. 56
      boa/src/property/mod.rs
  62. 4
      boa/src/syntax/ast/node/array/mod.rs
  63. 6
      boa/src/syntax/ast/node/await_expr/mod.rs
  64. 6
      boa/src/syntax/ast/node/block/mod.rs
  65. 6
      boa/src/syntax/ast/node/break_node/mod.rs
  66. 9
      boa/src/syntax/ast/node/call/mod.rs
  67. 4
      boa/src/syntax/ast/node/conditional/conditional_op/mod.rs
  68. 6
      boa/src/syntax/ast/node/conditional/if_node/mod.rs
  69. 4
      boa/src/syntax/ast/node/declaration/arrow_function_decl/mod.rs
  70. 6
      boa/src/syntax/ast/node/declaration/async_function_decl/mod.rs
  71. 6
      boa/src/syntax/ast/node/declaration/async_function_expr/mod.rs
  72. 6
      boa/src/syntax/ast/node/declaration/function_decl/mod.rs
  73. 4
      boa/src/syntax/ast/node/declaration/function_expr/mod.rs
  74. 8
      boa/src/syntax/ast/node/declaration/mod.rs
  75. 7
      boa/src/syntax/ast/node/field/get_const_field/mod.rs
  76. 7
      boa/src/syntax/ast/node/field/get_field/mod.rs
  77. 4
      boa/src/syntax/ast/node/identifier/mod.rs
  78. 6
      boa/src/syntax/ast/node/iteration/continue_node/mod.rs
  79. 4
      boa/src/syntax/ast/node/iteration/do_while_loop/mod.rs
  80. 8
      boa/src/syntax/ast/node/iteration/for_in_loop/mod.rs
  81. 6
      boa/src/syntax/ast/node/iteration/for_loop/mod.rs
  82. 6
      boa/src/syntax/ast/node/iteration/for_of_loop/mod.rs
  83. 6
      boa/src/syntax/ast/node/iteration/while_loop/mod.rs
  84. 20
      boa/src/syntax/ast/node/mod.rs
  85. 8
      boa/src/syntax/ast/node/new/mod.rs
  86. 6
      boa/src/syntax/ast/node/object/mod.rs
  87. 4
      boa/src/syntax/ast/node/operator/assign/mod.rs
  88. 10
      boa/src/syntax/ast/node/operator/bin_op/mod.rs
  89. 22
      boa/src/syntax/ast/node/operator/unary_op/mod.rs
  90. 6
      boa/src/syntax/ast/node/return_smt/mod.rs
  91. 4
      boa/src/syntax/ast/node/spread/mod.rs
  92. 6
      boa/src/syntax/ast/node/statement_list/mod.rs
  93. 6
      boa/src/syntax/ast/node/switch/mod.rs
  94. 14
      boa/src/syntax/ast/node/template/mod.rs
  95. 4
      boa/src/syntax/ast/node/throw/mod.rs
  96. 4
      boa/src/syntax/ast/node/try_node/mod.rs
  97. 132
      boa/src/value/conversions.rs
  98. 40
      boa/src/value/display.rs
  99. 46
      boa/src/value/equality.rs
  100. 6
      boa/src/value/hash.rs
  101. Some files were not shown because too many files have changed in this diff Show More

8
boa/examples/classes.rs

@ -2,7 +2,7 @@ use boa::{
class::{Class, ClassBuilder},
gc::{Finalize, Trace},
property::Attribute,
Context, Result, Value,
Context, JsValue, Result,
};
// We create a new struct that is going to represent a person.
@ -26,7 +26,7 @@ struct Person {
// or any function that matches that signature.
impl Person {
/// This function says hello
fn say_hello(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
fn say_hello(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
// We check if this is an object.
if let Some(object) = this.as_object() {
// If it is we downcast the type to type `Person`.
@ -37,7 +37,7 @@ impl Person {
person.name,
person.age // Here we can access the native rust fields of Person struct.
);
return Ok(Value::undefined());
return Ok(JsValue::undefined());
}
}
// If `this` was not an object or the type was not an native object `Person`,
@ -57,7 +57,7 @@ impl Class for Person {
const LENGTH: usize = 2;
// This is what is called when we do `new Person()`
fn constructor(_this: &Value, args: &[Value], context: &mut Context) -> Result<Self> {
fn constructor(_this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<Self> {
// We get the first argument. If it is unavailable we get `undefined`. And, then call `to_string()`.
//
// This is equivalent to `String(arg)`.

4
boa/examples/closures.rs

@ -1,6 +1,6 @@
use boa::{Context, JsString, Value};
use boa::{Context, JsString, JsValue};
fn main() -> Result<(), Value> {
fn main() -> Result<(), JsValue> {
let mut context = Context::new();
let variable = JsString::new("I am a captured variable");

8
boa/src/bigint.rs

@ -3,7 +3,7 @@
use crate::{
builtins::Number,
gc::{empty_trace, Finalize, Trace},
Context, Value,
Context, JsValue,
};
use std::{
@ -162,7 +162,7 @@ impl JsBigInt {
}
#[inline]
pub fn pow(x: &Self, y: &Self, context: &mut Context) -> Result<Self, Value> {
pub fn pow(x: &Self, y: &Self, context: &mut Context) -> Result<Self, JsValue> {
let y = if let Some(y) = y.inner.to_biguint() {
y
} else {
@ -173,7 +173,7 @@ impl JsBigInt {
}
#[inline]
pub fn shift_right(x: &Self, y: &Self, context: &mut Context) -> Result<Self, Value> {
pub fn shift_right(x: &Self, y: &Self, context: &mut Context) -> Result<Self, JsValue> {
if let Some(n) = y.inner.to_i32() {
let inner = if n > 0 {
x.inner.as_ref().clone().shr(n as usize)
@ -188,7 +188,7 @@ impl JsBigInt {
}
#[inline]
pub fn shift_left(x: &Self, y: &Self, context: &mut Context) -> Result<Self, Value> {
pub fn shift_left(x: &Self, y: &Self, context: &mut Context) -> Result<Self, JsValue> {
if let Some(n) = y.inner.to_i32() {
let inner = if n > 0 {
x.inner.as_ref().clone().shl(n as usize)

34
boa/src/builtins/array/array_iterator.rs

@ -1,5 +1,5 @@
use crate::{
builtins::{function::make_builtin_fn, iterable::create_iter_result_object, Array, Value},
builtins::{function::make_builtin_fn, iterable::create_iter_result_object, Array, JsValue},
gc::{Finalize, Trace},
object::{GcObject, ObjectData},
property::PropertyDescriptor,
@ -22,7 +22,7 @@ pub enum ArrayIterationKind {
/// [spec]: https://tc39.es/ecma262/#sec-array-iterator-objects
#[derive(Debug, Clone, Finalize, Trace)]
pub struct ArrayIterator {
array: Value,
array: JsValue,
next_index: u32,
kind: ArrayIterationKind,
}
@ -30,7 +30,7 @@ pub struct ArrayIterator {
impl ArrayIterator {
pub(crate) const NAME: &'static str = "ArrayIterator";
fn new(array: Value, kind: ArrayIterationKind) -> Self {
fn new(array: JsValue, kind: ArrayIterationKind) -> Self {
ArrayIterator {
array,
kind,
@ -48,10 +48,10 @@ impl ArrayIterator {
/// [spec]: https://tc39.es/ecma262/#sec-createarrayiterator
pub(crate) fn create_array_iterator(
context: &Context,
array: Value,
array: JsValue,
kind: ArrayIterationKind,
) -> Value {
let array_iterator = Value::new_object(context);
) -> JsValue {
let array_iterator = JsValue::new_object(context);
array_iterator.set_data(ObjectData::ArrayIterator(Self::new(array, kind)));
array_iterator
.as_object()
@ -68,13 +68,17 @@ impl ArrayIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
pub(crate) fn next(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
if let Value::Object(ref object) = this {
pub(crate) fn next(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
if let JsValue::Object(ref object) = this {
let mut object = object.borrow_mut();
if let Some(array_iterator) = object.as_array_iterator_mut() {
let index = array_iterator.next_index;
if array_iterator.array.is_undefined() {
return Ok(create_iter_result_object(context, Value::undefined(), true));
return Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
));
}
let len = array_iterator
.array
@ -83,8 +87,12 @@ impl ArrayIterator {
.ok_or_else(|| context.construct_type_error("Not an array"))?
as u32;
if array_iterator.next_index >= len {
array_iterator.array = Value::undefined();
return Ok(create_iter_result_object(context, Value::undefined(), true));
array_iterator.array = JsValue::undefined();
return Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
));
}
array_iterator.next_index = index + 1;
match array_iterator.kind {
@ -98,7 +106,7 @@ impl ArrayIterator {
ArrayIterationKind::KeyAndValue => {
let element_value = array_iterator.array.get_field(index, context)?;
let result = Array::constructor(
&Value::new_object(context),
&JsValue::new_object(context),
&[index.into(), element_value],
context,
)?;
@ -119,7 +127,7 @@ impl ArrayIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%arrayiteratorprototype%-object
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: Value) -> GcObject {
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: JsValue) -> GcObject {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// Create prototype

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

@ -20,7 +20,7 @@ use crate::{
object::{ConstructorBuilder, FunctionBuilder, GcObject, ObjectData, PROTOTYPE},
property::{Attribute, PropertyDescriptor},
symbol::WellKnownSymbols,
value::{IntegerOrInfinity, Value},
value::{IntegerOrInfinity, JsValue},
BoaProfiler, Context, JsString, Result,
};
use std::cmp::{max, min};
@ -36,7 +36,7 @@ impl BuiltIn for Array {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let symbol_iterator = WellKnownSymbols::iterator();
@ -119,7 +119,11 @@ impl BuiltIn for Array {
impl Array {
const LENGTH: usize = 1;
fn constructor(new_target: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
fn constructor(
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
// 2. Let proto be ? GetPrototypeFromConstructor(newTarget, "%Array.prototype%").
let prototype = new_target
@ -160,7 +164,7 @@ impl Array {
// i. Let intLen be ! ToUint32(len).
let int_len = len.to_u32(context).unwrap();
// ii. If SameValueZero(intLen, len) is false, throw a RangeError exception.
if !Value::same_value_zero(&int_len.into(), len) {
if !JsValue::same_value_zero(&int_len.into(), len) {
return Err(context.construct_range_error("invalid array length"));
}
int_len
@ -240,8 +244,8 @@ impl Array {
}
/// Creates a new `Array` instance.
pub(crate) fn new_array(context: &Context) -> Value {
let array = Value::new_object(context);
pub(crate) fn new_array(context: &Context) -> JsValue {
let array = JsValue::new_object(context);
array.set_data(ObjectData::Array);
array
.as_object()
@ -264,10 +268,10 @@ impl Array {
/// `array_obj` can be any array with prototype already set (it will be wiped and
/// recreated from `array_contents`)
pub(crate) fn construct_array(
array_obj: &Value,
array_contents: &[Value],
array_obj: &JsValue,
array_contents: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let array_obj_ptr = array_obj.clone();
// Wipe existing contents of the array object
@ -305,7 +309,7 @@ impl Array {
/// Returns a Boolean valued property that if `true` indicates that
/// an object should be flattened to its array elements
/// by `Array.prototype.concat`.
fn is_concat_spreadable(this: &Value, context: &mut Context) -> Result<bool> {
fn is_concat_spreadable(this: &JsValue, context: &mut Context) -> Result<bool> {
// 1. If Type(O) is not Object, return false.
if !this.is_object() {
return Ok(false);
@ -334,7 +338,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-array-@@species
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/@@species
fn get_species(this: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> Result<JsValue> {
// 1. Return the this value.
Ok(this.clone())
}
@ -369,7 +373,7 @@ impl Array {
let c = c.get(WellKnownSymbols::species(), context)?;
// 5.b. If C is null, set C to undefined.
if c.is_null_or_undefined() {
Value::undefined()
JsValue::undefined()
} else {
c
}
@ -389,7 +393,7 @@ impl Array {
}
// 8. Return ? Construct(C, « 𝔽(length) »).
Ok(
c.construct(&[Value::from(length)], &c.clone().into(), context)?
c.construct(&[JsValue::new(length)], &c.clone().into(), context)?
.as_object()
.unwrap(),
)
@ -401,10 +405,10 @@ impl Array {
/// Utility function which takes an existing array object and puts additional
/// values on the end, correctly rewriting the length
pub(crate) fn add_to_array_object(
array_ptr: &Value,
add_values: &[Value],
array_ptr: &JsValue,
add_values: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let orig_length = array_ptr.get_field("length", context)?.to_length(context)?;
for (n, value) in add_values.iter().enumerate() {
@ -421,7 +425,7 @@ impl Array {
array_ptr.set_field(
"length",
Value::from(orig_length.wrapping_add(add_values.len())),
JsValue::new(orig_length.wrapping_add(add_values.len())),
false,
context,
)?;
@ -440,10 +444,10 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.isarray
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
pub(crate) fn is_array(_: &Value, args: &[Value], _: &mut Context) -> Result<Value> {
pub(crate) fn is_array(_: &JsValue, args: &[JsValue], _: &mut Context) -> Result<JsValue> {
match args.get(0).and_then(|x| x.as_object()) {
Some(object) => Ok(Value::from(object.borrow().is_array())),
None => Ok(Value::from(false)),
Some(object) => Ok(JsValue::new(object.borrow().is_array())),
None => Ok(JsValue::new(false)),
}
}
@ -458,7 +462,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.of
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/of
pub(crate) fn of(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn of(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let len be the number of elements in items.
// 2. Let lenNumber be 𝔽(len).
let len = args.len();
@ -505,7 +509,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.concat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
pub(crate) fn concat(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn concat(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let obj = this.to_object(context)?;
// 2. Let A be ? ArraySpeciesCreate(O, 0).
@ -514,7 +522,7 @@ impl Array {
let mut n = 0;
// 4. Prepend O to items.
// 5. For each element E of items, do
for item in [Value::from(obj)].iter().chain(args.iter()) {
for item in [JsValue::new(obj)].iter().chain(args.iter()) {
// a. Let spreadable be ? IsConcatSpreadable(E).
let spreadable = Self::is_concat_spreadable(item, context)?;
// b. If spreadable is true, then
@ -565,7 +573,7 @@ impl Array {
arr.set("length", n, true, context)?;
// 7. Return A.
Ok(Value::from(arr))
Ok(JsValue::new(arr))
}
/// `Array.prototype.push( ...items )`
@ -580,7 +588,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.push
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
pub(crate) fn push(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn push(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -616,7 +624,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.pop
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop
pub(crate) fn pop(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn pop(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -626,7 +634,7 @@ impl Array {
// a. Perform ? Set(O, "length", +0𝔽, true).
o.set("length", 0, true, context)?;
// b. Return undefined.
Ok(Value::undefined())
Ok(JsValue::undefined())
// 4. Else,
} else {
// a. Assert: len > 0.
@ -655,7 +663,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.foreach
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
pub(crate) fn for_each(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn for_each(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -663,7 +675,7 @@ impl Array {
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
let callback = if let Some(arg) = args
.get(0)
.and_then(Value::as_object)
.and_then(JsValue::as_object)
.filter(GcObject::is_callable)
{
arg
@ -682,13 +694,13 @@ impl Array {
// i. Let kValue be ? Get(O, Pk).
let k_value = o.get(pk, context)?;
// ii. Perform ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
let this_arg = args.get(1).cloned().unwrap_or_else(Value::undefined);
let this_arg = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
callback.call(&this_arg, &[k_value, k.into(), o.clone().into()], context)?;
}
// d. Set k to k + 1.
}
// 6. Return undefined.
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `Array.prototype.join( separator )`
@ -703,7 +715,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.join
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join
pub(crate) fn join(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn join(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -754,7 +766,11 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_string(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let array be ? ToObject(this value).
let array = this.to_object(context)?;
// 2. Let func be ? Get(array, "join").
@ -780,7 +796,7 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.reverse
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse
#[allow(clippy::else_if_without_else)]
pub(crate) fn reverse(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn reverse(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -798,7 +814,7 @@ impl Array {
// d. Let lowerExists be ? HasProperty(O, lowerP).
let lower_exists = o.has_property(lower, context)?;
// e. If lowerExists is true, then
let mut lower_value = Value::undefined();
let mut lower_value = JsValue::undefined();
if lower_exists {
// i. Let lowerValue be ? Get(O, lowerP).
lower_value = o.get(lower, context)?;
@ -806,7 +822,7 @@ impl Array {
// f. Let upperExists be ? HasProperty(O, upperP).
let upper_exists = o.has_property(upper, context)?;
// g. If upperExists is true, then
let mut upper_value = Value::undefined();
let mut upper_value = JsValue::undefined();
if upper_exists {
// i. Let upperValue be ? Get(O, upperP).
upper_value = o.get(upper, context)?;
@ -857,7 +873,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.shift
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
pub(crate) fn shift(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn shift(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -867,7 +883,7 @@ impl Array {
// a. Perform ? Set(O, "length", +0𝔽, true).
o.set("length", 0, true, context)?;
// b. Return undefined.
return Ok(Value::undefined());
return Ok(JsValue::undefined());
}
// 4. Let first be ? Get(O, "0").
let first = o.get(0, context)?;
@ -914,7 +930,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.unshift
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
pub(crate) fn unshift(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn unshift(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -981,7 +1001,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.every
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every
pub(crate) fn every(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn every(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -989,7 +1013,7 @@ impl Array {
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
let callback = if let Some(arg) = args
.get(0)
.and_then(Value::as_object)
.and_then(JsValue::as_object)
.filter(GcObject::is_callable)
{
arg
@ -1015,13 +1039,13 @@ impl Array {
.to_boolean();
// iii. If testResult is false, return false.
if !test_result {
return Ok(Value::from(false));
return Ok(JsValue::new(false));
}
}
// d. Set k to k + 1.
}
// 6. Return true.
Ok(Value::from(true))
Ok(JsValue::new(true))
}
/// `Array.prototype.map( callback, [ thisArg ] )`
@ -1035,7 +1059,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.map
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
pub(crate) fn map(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn map(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -1081,7 +1105,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.indexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
pub(crate) fn index_of(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn index_of(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1090,7 +1118,7 @@ impl Array {
// 3. If len is 0, return -1𝔽.
if len == 0 {
return Ok(Value::from(-1));
return Ok(JsValue::new(-1));
}
// 4. Let n be ? ToIntegerOrInfinity(fromIndex).
@ -1102,7 +1130,7 @@ impl Array {
// 5. Assert: If fromIndex is undefined, then n is 0.
let n = match n {
// 6. If n is +∞, return -1𝔽.
IntegerOrInfinity::PositiveInfinity => return Ok(Value::from(-1)),
IntegerOrInfinity::PositiveInfinity => return Ok(JsValue::new(-1)),
// 7. Else if n is -∞, set n to 0.
IntegerOrInfinity::NegativeInfinity => 0,
IntegerOrInfinity::Integer(value) => value,
@ -1136,14 +1164,14 @@ impl Array {
// ii. Let same be IsStrictlyEqual(searchElement, elementK).
// iii. If same is true, return 𝔽(k).
if search_element.strict_equals(&element_k) {
return Ok(Value::from(k));
return Ok(JsValue::new(k));
}
}
// c. Set k to k + 1.
k += 1;
}
// 11. Return -1𝔽.
Ok(Value::from(-1))
Ok(JsValue::new(-1))
}
/// `Array.prototype.lastIndexOf( searchElement[, fromIndex ] )`
@ -1165,10 +1193,10 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.lastindexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf
pub(crate) fn last_index_of(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1177,7 +1205,7 @@ impl Array {
// 3. If len is 0, return -1𝔽.
if len == 0 {
return Ok(Value::from(-1));
return Ok(JsValue::new(-1));
}
// 4. If fromIndex is present, let n be ? ToIntegerOrInfinity(fromIndex); else let n be len - 1.
@ -1189,7 +1217,7 @@ impl Array {
let mut k = match n {
// 5. If n is -∞, return -1𝔽.
IntegerOrInfinity::NegativeInfinity => return Ok(Value::from(-1)),
IntegerOrInfinity::NegativeInfinity => return Ok(JsValue::new(-1)),
// 6. If n ≥ 0, then
// a. Let k be min(n, len - 1).
IntegerOrInfinity::Integer(n) if n >= 0 => min(n, len - 1),
@ -1211,15 +1239,15 @@ impl Array {
let element_k = o.get(k, context)?;
// ii. Let same be IsStrictlyEqual(searchElement, elementK).
// iii. If same is true, return 𝔽(k).
if Value::strict_equals(&search_element, &element_k) {
return Ok(Value::from(k));
if JsValue::strict_equals(&search_element, &element_k) {
return Ok(JsValue::new(k));
}
}
// c. Set k to k - 1.
k -= 1;
}
// 9. Return -1𝔽.
Ok(Value::from(-1))
Ok(JsValue::new(-1))
}
/// `Array.prototype.find( callback, [thisArg] )`
@ -1234,7 +1262,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.find
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
pub(crate) fn find(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn find(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1242,7 +1270,7 @@ impl Array {
let len = o.length_of_array_like(context)?;
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
let predicate = match args.get(0).and_then(Value::as_object) {
let predicate = match args.get(0).and_then(JsValue::as_object) {
Some(predicate) if predicate.is_callable() => predicate,
_ => {
return context.throw_type_error("Array.prototype.find: predicate is not callable")
@ -1275,7 +1303,7 @@ impl Array {
k += 1;
}
// 6. Return undefined.
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `Array.prototype.findIndex( predicate [ , thisArg ] )`
@ -1290,7 +1318,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.findindex
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
pub(crate) fn find_index(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn find_index(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1298,7 +1330,7 @@ impl Array {
let len = o.length_of_array_like(context)?;
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
let predicate = match args.get(0).and_then(Value::as_object) {
let predicate = match args.get(0).and_then(JsValue::as_object) {
Some(predicate) if predicate.is_callable() => predicate,
_ => {
return context
@ -1322,13 +1354,13 @@ impl Array {
.to_boolean();
// d. If testResult is true, return 𝔽(k).
if test_result {
return Ok(Value::from(k));
return Ok(JsValue::new(k));
}
// e. Set k to k + 1.
k += 1;
}
// 6. Return -1𝔽.
Ok(Value::from(-1))
Ok(JsValue::new(-1))
}
/// `Array.prototype.flat( [depth] )`
@ -1342,7 +1374,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.flat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
pub(crate) fn flat(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn flat(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ToObject(this value)
let o = this.to_object(context)?;
@ -1374,7 +1406,7 @@ impl Array {
0,
depth_num,
None,
&Value::undefined(),
&JsValue::undefined(),
context,
)?;
@ -1394,7 +1426,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.flatMap
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
pub(crate) fn flat_map(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn flat_map(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ToObject(this value)
let o = this.to_object(context)?;
@ -1440,7 +1476,7 @@ impl Array {
start: u64,
depth: u64,
mapper_function: Option<GcObject>,
this_arg: &Value,
this_arg: &JsValue,
context: &mut Context,
) -> Result<u64> {
// 1. Assert target is Object
@ -1512,7 +1548,7 @@ impl Array {
target_index,
new_depth,
None,
&Value::undefined(),
&JsValue::undefined(),
context,
)?;
@ -1550,7 +1586,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.fill
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill
pub(crate) fn fill(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn fill(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1595,10 +1631,10 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.includes
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
pub(crate) fn includes_value(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1607,7 +1643,7 @@ impl Array {
// 3. If len is 0, return false.
if len == 0 {
return Ok(Value::from(false));
return Ok(JsValue::new(false));
}
// 4. Let n be ? ToIntegerOrInfinity(fromIndex).
@ -1620,7 +1656,7 @@ impl Array {
// 6. If n is +∞, return false.
// 7. Else if n is -∞, set n to 0.
let n = match n {
IntegerOrInfinity::PositiveInfinity => return Ok(Value::from(false)),
IntegerOrInfinity::PositiveInfinity => return Ok(JsValue::new(false)),
IntegerOrInfinity::NegativeInfinity => 0,
IntegerOrInfinity::Integer(value) => value,
};
@ -1647,14 +1683,14 @@ impl Array {
// a. Let elementK be ? Get(O, ! ToString(𝔽(k))).
let element_k = o.get(k, context)?;
// b. If SameValueZero(searchElement, elementK) is true, return true.
if Value::same_value_zero(&search_element, &element_k) {
return Ok(Value::from(true));
if JsValue::same_value_zero(&search_element, &element_k) {
return Ok(JsValue::new(true));
}
// c. Set k to k + 1.
k += 1;
}
// 11. Return false.
Ok(Value::from(false))
Ok(JsValue::new(false))
}
/// `Array.prototype.slice( [begin[, end]] )`
@ -1671,7 +1707,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.slice
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
pub(crate) fn slice(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn slice(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1735,7 +1775,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.filter
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
pub(crate) fn filter(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn filter(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1752,7 +1796,7 @@ impl Array {
"missing argument 0 when calling function Array.prototype.filter",
)
})?;
let this_val = args.get(1).cloned().unwrap_or_else(Value::undefined);
let this_val = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
if !callback.is_callable() {
return context.throw_type_error("the callback must be callable");
@ -1773,7 +1817,7 @@ impl Array {
// i. Let kValue be ? Get(O, Pk).
let element = o.get(idx, context)?;
let args = [element.clone(), Value::from(idx), Value::from(o.clone())];
let args = [element.clone(), JsValue::new(idx), JsValue::new(o.clone())];
// ii. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
let selected = callback.call(&this_val, &args, context)?.to_boolean();
@ -1807,7 +1851,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.some
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
pub(crate) fn some(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn some(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
@ -1815,7 +1859,7 @@ impl Array {
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
let callback = if let Some(arg) = args
.get(0)
.and_then(Value::as_object)
.and_then(JsValue::as_object)
.filter(GcObject::is_callable)
{
arg
@ -1840,13 +1884,13 @@ impl Array {
.to_boolean();
// iii. If testResult is true, return true.
if test_result {
return Ok(Value::from(true));
return Ok(JsValue::new(true));
}
}
// d. Set k to k + 1.
}
// 6. Return false.
Ok(Value::from(false))
Ok(JsValue::new(false))
}
/// `Array.prototype.reduce( callbackFn [ , initialValue ] )`
@ -1857,7 +1901,11 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.reduce
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
pub(crate) fn reduce(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn reduce(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1865,7 +1913,7 @@ impl Array {
let len = o.length_of_array_like(context)?;
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
let callback = match args.get(0).and_then(Value::as_object) {
let callback = match args.get(0).and_then(JsValue::as_object) {
Some(callback) if callback.is_callable() => callback,
_ => {
return context
@ -1883,7 +1931,7 @@ impl Array {
// 5. Let k be 0.
let mut k = 0;
// 6. Let accumulator be undefined.
let mut accumulator = Value::undefined();
let mut accumulator = JsValue::undefined();
// 7. If initialValue is present, then
if let Some(initial_value) = args.get(1) {
@ -1927,7 +1975,7 @@ impl Array {
let k_value = o.get(pk, context)?;
// ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »).
accumulator = callback.call(
&Value::undefined(),
&JsValue::undefined(),
&[accumulator, k_value, k.into(), o.clone().into()],
context,
)?;
@ -1952,10 +2000,10 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.reduceright
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight
pub(crate) fn reduce_right(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -1963,7 +2011,7 @@ impl Array {
let len = o.length_of_array_like(context)?;
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
let callback = match args.get(0).and_then(Value::as_object) {
let callback = match args.get(0).and_then(JsValue::as_object) {
Some(callback) if callback.is_callable() => callback,
_ => {
return context.throw_type_error(
@ -1982,7 +2030,7 @@ impl Array {
// 5. Let k be len - 1.
let mut k = len as i64 - 1;
// 6. Let accumulator be undefined.
let mut accumulator = Value::undefined();
let mut accumulator = JsValue::undefined();
// 7. If initialValue is present, then
if let Some(initial_value) = args.get(1) {
// a. Set accumulator to initialValue.
@ -2025,7 +2073,7 @@ impl Array {
let k_value = o.get(pk, context)?;
// ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »).
accumulator = callback.call(
&Value::undefined(),
&JsValue::undefined(),
&[accumulator.clone(), k_value, k.into(), o.clone().into()],
context,
)?;
@ -2050,10 +2098,10 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.copywithin
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin
pub(crate) fn copy_within(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// 1. Let O be ? ToObject(this value).
let o = this.to_object(context)?;
@ -2139,7 +2187,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.values
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values
pub(crate) fn values(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn values(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(ArrayIterator::create_array_iterator(
context,
this.clone(),
@ -2157,7 +2205,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.values
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values
pub(crate) fn keys(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn keys(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(ArrayIterator::create_array_iterator(
context,
this.clone(),
@ -2175,7 +2223,7 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.values
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values
pub(crate) fn entries(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn entries(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(ArrayIterator::create_array_iterator(
context,
this.clone(),
@ -2186,7 +2234,7 @@ impl Array {
/// Represents the algorithm to calculate `relativeStart` (or `k`) in array functions.
pub(super) fn get_relative_start(
context: &mut Context,
arg: Option<&Value>,
arg: Option<&JsValue>,
len: usize,
) -> Result<usize> {
// 1. Let relativeStart be ? ToIntegerOrInfinity(start).
@ -2211,10 +2259,10 @@ impl Array {
/// Represents the algorithm to calculate `relativeEnd` (or `final`) in array functions.
pub(super) fn get_relative_end(
context: &mut Context,
arg: Option<&Value>,
arg: Option<&JsValue>,
len: usize,
) -> Result<usize> {
let default_value = Value::undefined();
let default_value = JsValue::undefined();
let value = arg.unwrap_or(&default_value);
// 1. If end is undefined, let relativeEnd be len [and return it]
if value.is_undefined() {

80
boa/src/builtins/array/tests.rs

@ -1,6 +1,6 @@
use super::Array;
use crate::builtins::Number;
use crate::{forward, Context, Value};
use crate::{forward, Context, JsValue};
#[test]
fn is_array() {
@ -13,58 +13,58 @@ fn is_array() {
context.eval(init).unwrap();
assert_eq!(
context.eval("Array.isArray(empty)").unwrap(),
Value::Boolean(true)
JsValue::new(true)
);
assert_eq!(
context.eval("Array.isArray(new_arr)").unwrap(),
Value::Boolean(true)
JsValue::new(true)
);
assert_eq!(
context.eval("Array.isArray(many)").unwrap(),
Value::Boolean(true)
JsValue::new(true)
);
assert_eq!(
context.eval("Array.isArray([1, 2, 3])").unwrap(),
Value::Boolean(true)
JsValue::new(true)
);
assert_eq!(
context.eval("Array.isArray([])").unwrap(),
Value::Boolean(true)
JsValue::new(true)
);
assert_eq!(
context.eval("Array.isArray({})").unwrap(),
Value::Boolean(false)
JsValue::new(false)
);
// assert_eq!(context.eval("Array.isArray(new Array)"), "true");
assert_eq!(
context.eval("Array.isArray()").unwrap(),
Value::Boolean(false)
JsValue::new(false)
);
assert_eq!(
context
.eval("Array.isArray({ constructor: Array })")
.unwrap(),
Value::Boolean(false)
JsValue::new(false)
);
assert_eq!(
context
.eval("Array.isArray({ push: Array.prototype.push, concat: Array.prototype.concat })")
.unwrap(),
Value::Boolean(false)
JsValue::new(false)
);
assert_eq!(
context.eval("Array.isArray(17)").unwrap(),
Value::Boolean(false)
JsValue::new(false)
);
assert_eq!(
context
.eval("Array.isArray({ __proto__: Array.prototype })")
.unwrap(),
Value::Boolean(false)
JsValue::new(false)
);
assert_eq!(
context.eval("Array.isArray({ length: 0 })").unwrap(),
Value::Boolean(false)
JsValue::new(false)
);
}
@ -109,12 +109,12 @@ fn of() {
.unwrap();
assert_eq!(
context.eval("a instanceof Date").unwrap(),
Value::from(true)
JsValue::new(true)
);
assert_eq!(context.eval("a[0]").unwrap(), Value::from("a"));
assert_eq!(context.eval("a[1]").unwrap(), Value::undefined());
assert_eq!(context.eval("a[2]").unwrap(), Value::from(3));
assert_eq!(context.eval("a.length").unwrap(), Value::from(3));
assert_eq!(context.eval("a[0]").unwrap(), JsValue::new("a"));
assert_eq!(context.eval("a[1]").unwrap(), JsValue::undefined());
assert_eq!(context.eval("a[2]").unwrap(), JsValue::new(3));
assert_eq!(context.eval("a.length").unwrap(), JsValue::new(3));
}
#[ignore]
@ -1424,47 +1424,47 @@ fn get_relative_start() {
assert_eq!(Array::get_relative_start(&mut context, None, 10), Ok(0));
assert_eq!(
Array::get_relative_start(&mut context, Some(&Value::undefined()), 10),
Array::get_relative_start(&mut context, Some(&JsValue::undefined()), 10),
Ok(0)
);
assert_eq!(
Array::get_relative_start(&mut context, Some(&Value::from(f64::NEG_INFINITY)), 10),
Array::get_relative_start(&mut context, Some(&JsValue::new(f64::NEG_INFINITY)), 10),
Ok(0)
);
assert_eq!(
Array::get_relative_start(&mut context, Some(&Value::from(f64::INFINITY)), 10),
Array::get_relative_start(&mut context, Some(&JsValue::new(f64::INFINITY)), 10),
Ok(10)
);
assert_eq!(
Array::get_relative_start(&mut context, Some(&Value::from(-1)), 10),
Array::get_relative_start(&mut context, Some(&JsValue::new(-1)), 10),
Ok(9)
);
assert_eq!(
Array::get_relative_start(&mut context, Some(&Value::from(1)), 10),
Array::get_relative_start(&mut context, Some(&JsValue::new(1)), 10),
Ok(1)
);
assert_eq!(
Array::get_relative_start(&mut context, Some(&Value::from(-11)), 10),
Array::get_relative_start(&mut context, Some(&JsValue::new(-11)), 10),
Ok(0)
);
assert_eq!(
Array::get_relative_start(&mut context, Some(&Value::from(11)), 10),
Array::get_relative_start(&mut context, Some(&JsValue::new(11)), 10),
Ok(10)
);
assert_eq!(
Array::get_relative_start(&mut context, Some(&Value::from(f64::MIN)), 10),
Array::get_relative_start(&mut context, Some(&JsValue::new(f64::MIN)), 10),
Ok(0)
);
assert_eq!(
Array::get_relative_start(
&mut context,
Some(&Value::from(Number::MIN_SAFE_INTEGER)),
Some(&JsValue::new(Number::MIN_SAFE_INTEGER)),
10
),
Ok(0)
);
assert_eq!(
Array::get_relative_start(&mut context, Some(&Value::from(f64::MAX)), 10),
Array::get_relative_start(&mut context, Some(&JsValue::new(f64::MAX)), 10),
Ok(10)
);
@ -1472,7 +1472,7 @@ fn get_relative_start() {
assert_eq!(
Array::get_relative_start(
&mut context,
Some(&Value::from(Number::MAX_SAFE_INTEGER)),
Some(&JsValue::new(Number::MAX_SAFE_INTEGER)),
10
),
Ok(10)
@ -1485,47 +1485,47 @@ fn get_relative_end() {
assert_eq!(Array::get_relative_end(&mut context, None, 10), Ok(10));
assert_eq!(
Array::get_relative_end(&mut context, Some(&Value::undefined()), 10),
Array::get_relative_end(&mut context, Some(&JsValue::undefined()), 10),
Ok(10)
);
assert_eq!(
Array::get_relative_end(&mut context, Some(&Value::from(f64::NEG_INFINITY)), 10),
Array::get_relative_end(&mut context, Some(&JsValue::new(f64::NEG_INFINITY)), 10),
Ok(0)
);
assert_eq!(
Array::get_relative_end(&mut context, Some(&Value::from(f64::INFINITY)), 10),
Array::get_relative_end(&mut context, Some(&JsValue::new(f64::INFINITY)), 10),
Ok(10)
);
assert_eq!(
Array::get_relative_end(&mut context, Some(&Value::from(-1)), 10),
Array::get_relative_end(&mut context, Some(&JsValue::new(-1)), 10),
Ok(9)
);
assert_eq!(
Array::get_relative_end(&mut context, Some(&Value::from(1)), 10),
Array::get_relative_end(&mut context, Some(&JsValue::new(1)), 10),
Ok(1)
);
assert_eq!(
Array::get_relative_end(&mut context, Some(&Value::from(-11)), 10),
Array::get_relative_end(&mut context, Some(&JsValue::new(-11)), 10),
Ok(0)
);
assert_eq!(
Array::get_relative_end(&mut context, Some(&Value::from(11)), 10),
Array::get_relative_end(&mut context, Some(&JsValue::new(11)), 10),
Ok(10)
);
assert_eq!(
Array::get_relative_end(&mut context, Some(&Value::from(f64::MIN)), 10),
Array::get_relative_end(&mut context, Some(&JsValue::new(f64::MIN)), 10),
Ok(0)
);
assert_eq!(
Array::get_relative_end(
&mut context,
Some(&Value::from(Number::MIN_SAFE_INTEGER)),
Some(&JsValue::new(Number::MIN_SAFE_INTEGER)),
10
),
Ok(0)
);
assert_eq!(
Array::get_relative_end(&mut context, Some(&Value::from(f64::MAX)), 10),
Array::get_relative_end(&mut context, Some(&JsValue::new(f64::MAX)), 10),
Ok(10)
);
@ -1533,7 +1533,7 @@ fn get_relative_end() {
assert_eq!(
Array::get_relative_end(
&mut context,
Some(&Value::from(Number::MAX_SAFE_INTEGER)),
Some(&JsValue::new(Number::MAX_SAFE_INTEGER)),
10
),
Ok(10)

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

@ -17,7 +17,7 @@ use crate::{
object::{ConstructorBuilder, ObjectData},
property::Attribute,
symbol::WellKnownSymbols,
BoaProfiler, Context, JsBigInt, Result, Value,
BoaProfiler, Context, JsBigInt, JsValue, Result,
};
#[cfg(test)]
mod tests;
@ -33,7 +33,7 @@ impl BuiltIn for BigInt {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let to_string_tag = WellKnownSymbols::to_string_tag();
@ -76,12 +76,12 @@ impl BigInt {
///
/// [spec]: https://tc39.es/ecma262/#sec-bigint-objects
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/BigInt
fn constructor(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
fn constructor(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let data = match args.get(0) {
Some(value) => value.to_bigint(context)?,
None => JsBigInt::zero(),
};
Ok(Value::from(data))
Ok(JsValue::new(data))
}
/// The abstract operation thisBigIntValue takes argument value.
@ -95,15 +95,15 @@ impl BigInt {
///
/// [spec]: https://tc39.es/ecma262/#sec-thisbigintvalue
#[inline]
fn this_bigint_value(value: &Value, context: &mut Context) -> Result<JsBigInt> {
fn this_bigint_value(value: &JsValue, context: &mut Context) -> Result<JsBigInt> {
match value {
// 1. If Type(value) is BigInt, return value.
Value::BigInt(ref bigint) => return Ok(bigint.clone()),
JsValue::BigInt(ref bigint) => return Ok(bigint.clone()),
// 2. If Type(value) is Object and value has a [[BigIntData]] internal slot, then
// a. Assert: Type(value.[[BigIntData]]) is BigInt.
// b. Return value.[[BigIntData]].
Value::Object(ref object) => {
JsValue::Object(ref object) => {
if let ObjectData::BigInt(ref bigint) = object.borrow().data {
return Ok(bigint.clone());
}
@ -126,7 +126,11 @@ impl BigInt {
/// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_string(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let radix = if !args.is_empty() {
args[0].to_integer(context)? as i32
} else {
@ -136,7 +140,7 @@ impl BigInt {
return context
.throw_range_error("radix must be an integer at least 2 and no greater than 36");
}
Ok(Value::from(
Ok(JsValue::new(
Self::this_bigint_value(this, context)?.to_string_radix(radix as u32),
))
}
@ -151,8 +155,12 @@ impl BigInt {
///
/// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/valueOf
pub(crate) fn value_of(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
Ok(Value::from(Self::this_bigint_value(this, context)?))
pub(crate) fn value_of(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
Ok(JsValue::new(Self::this_bigint_value(this, context)?))
}
/// `BigInt.asIntN()`
@ -162,18 +170,22 @@ impl BigInt {
/// [spec]: https://tc39.es/ecma262/#sec-bigint.asintn
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asIntN
#[allow(clippy::wrong_self_convention)]
pub(crate) fn as_int_n(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn as_int_n(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let (modulo, bits) = Self::calculate_as_uint_n(args, context)?;
if bits > 0
&& modulo >= JsBigInt::pow(&JsBigInt::new(2), &JsBigInt::new(bits as i64 - 1), context)?
{
Ok(Value::from(JsBigInt::sub(
Ok(JsValue::new(JsBigInt::sub(
&modulo,
&JsBigInt::pow(&JsBigInt::new(2), &JsBigInt::new(bits as i64), context)?,
)))
} else {
Ok(Value::from(modulo))
Ok(JsValue::new(modulo))
}
}
@ -184,10 +196,14 @@ impl BigInt {
/// [spec]: https://tc39.es/ecma262/#sec-bigint.asuintn
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asUintN
#[allow(clippy::wrong_self_convention)]
pub(crate) fn as_uint_n(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn as_uint_n(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let (modulo, _) = Self::calculate_as_uint_n(args, context)?;
Ok(Value::from(modulo))
Ok(JsValue::new(modulo))
}
/// Helper function to wrap the value of a `BigInt` to an unsigned integer.
@ -195,10 +211,10 @@ impl BigInt {
/// This function expects the same arguments as `as_uint_n` and wraps the value of a `BigInt`.
/// Additionally to the wrapped unsigned value it returns the converted `bits` argument, so it
/// can be reused from the `as_int_n` method.
fn calculate_as_uint_n(args: &[Value], context: &mut Context) -> Result<(JsBigInt, u32)> {
fn calculate_as_uint_n(args: &[JsValue], context: &mut Context) -> Result<(JsBigInt, u32)> {
use std::convert::TryFrom;
let undefined_value = Value::undefined();
let undefined_value = JsValue::undefined();
let bits_arg = args.get(0).unwrap_or(&undefined_value);
let bigint_arg = args.get(1).unwrap_or(&undefined_value);

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

@ -16,7 +16,7 @@ use crate::{
builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
property::Attribute,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
/// Boolean implementation.
@ -31,7 +31,7 @@ impl BuiltIn for Boolean {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let boolean_object = ConstructorBuilder::with_standard_object(
@ -57,14 +57,14 @@ impl Boolean {
///
/// `[[Call]]` Creates a new boolean primitive
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// Get the argument, if any
let data = args.get(0).map(|x| x.to_boolean()).unwrap_or(false);
if new_target.is_undefined() {
return Ok(Value::from(data));
return Ok(JsValue::new(data));
}
let prototype = new_target
.as_object()
@ -75,7 +75,7 @@ impl Boolean {
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let boolean = Value::new_object(context);
let boolean = JsValue::new_object(context);
boolean
.as_object()
@ -92,10 +92,10 @@ impl Boolean {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-thisbooleanvalue
fn this_boolean_value(value: &Value, context: &mut Context) -> Result<bool> {
fn this_boolean_value(value: &JsValue, context: &mut Context) -> Result<bool> {
match value {
Value::Boolean(boolean) => return Ok(*boolean),
Value::Object(ref object) => {
JsValue::Boolean(boolean) => return Ok(*boolean),
JsValue::Object(ref object) => {
let object = object.borrow();
if let Some(boolean) = object.as_boolean() {
return Ok(boolean);
@ -116,9 +116,13 @@ impl Boolean {
/// [spec]: https://tc39.es/ecma262/#sec-boolean-object
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_string(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let boolean = Self::this_boolean_value(this, context)?;
Ok(Value::from(boolean.to_string()))
Ok(JsValue::new(boolean.to_string()))
}
/// The valueOf() method returns the primitive value of a `Boolean` object.
@ -130,7 +134,11 @@ impl Boolean {
/// [spec]: https://tc39.es/ecma262/#sec-boolean.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/valueOf
#[inline]
pub(crate) fn value_of(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
Ok(Value::from(Self::this_boolean_value(this, context)?))
pub(crate) fn value_of(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
Ok(JsValue::new(Self::this_boolean_value(this, context)?))
}
}

4
boa/src/builtins/boolean/tests.rs

@ -1,4 +1,4 @@
use crate::{forward, forward_val, Context, Value};
use crate::{forward, forward_val, Context, JsValue};
/// Test the correct type is returned from call and construct
#[allow(clippy::unwrap_used)]
@ -58,7 +58,7 @@ fn instances_have_correct_proto_set() {
let bool_instance = forward_val(&mut context, "boolInstance").expect("value expected");
let bool_prototype = forward_val(&mut context, "boolProto").expect("value expected");
assert!(Value::same_value(
assert!(JsValue::same_value(
&bool_instance.as_object().unwrap().prototype_instance(),
&bool_prototype
));

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

@ -20,7 +20,7 @@ use crate::{
builtins::BuiltIn,
object::ObjectInitializer,
property::Attribute,
value::{display::display_obj, Value},
value::{display::display_obj, JsValue},
BoaProfiler, Context, JsString, Result,
};
use rustc_hash::FxHashMap;
@ -50,7 +50,7 @@ pub(crate) fn logger(msg: LogMessage, console_state: &Console) {
}
/// This represents the `console` formatter.
pub fn formatter(data: &[Value], context: &mut Context) -> Result<String> {
pub fn formatter(data: &[JsValue], context: &mut Context) -> Result<String> {
let target = data
.get(0)
.cloned()
@ -141,7 +141,7 @@ impl BuiltIn for Console {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let console = ObjectInitializer::new(context)
.function(Self::assert, "assert", 0)
@ -184,19 +184,19 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#assert
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/assert
pub(crate) fn assert(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let assertion = args.get(0).map(Value::to_boolean).unwrap_or(false);
pub(crate) fn assert(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let assertion = args.get(0).map(JsValue::to_boolean).unwrap_or(false);
if !assertion {
let mut args: Vec<Value> = args.iter().skip(1).cloned().collect();
let mut args: Vec<JsValue> = args.iter().skip(1).cloned().collect();
let message = "Assertion failed".to_string();
if args.is_empty() {
args.push(Value::from(message));
args.push(JsValue::new(message));
} else if !args[0].is_string() {
args.insert(0, Value::from(message));
args.insert(0, JsValue::new(message));
} else {
let concat = format!("{}: {}", message, args[0].display());
args[0] = Value::from(concat);
args[0] = JsValue::new(concat);
}
logger(
@ -205,7 +205,7 @@ impl Console {
);
}
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.clear()`
@ -218,9 +218,9 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#clear
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/clear
pub(crate) fn clear(_: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn clear(_: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
context.console_mut().groups.clear();
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.debug(...data)`
@ -233,12 +233,12 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#debug
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/debug
pub(crate) fn debug(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn debug(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
logger(
LogMessage::Log(formatter(args, context)?),
context.console(),
);
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.error(...data)`
@ -251,12 +251,12 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#error
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/error
pub(crate) fn error(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn error(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
logger(
LogMessage::Error(formatter(args, context)?),
context.console(),
);
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.info(...data)`
@ -269,12 +269,12 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#info
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/info
pub(crate) fn info(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn info(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
logger(
LogMessage::Info(formatter(args, context)?),
context.console(),
);
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.log(...data)`
@ -287,12 +287,12 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#log
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/log
pub(crate) fn log(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn log(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
logger(
LogMessage::Log(formatter(args, context)?),
context.console(),
);
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.trace(...data)`
@ -305,7 +305,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#trace
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/trace
pub(crate) fn trace(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn trace(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
if !args.is_empty() {
logger(
LogMessage::Log(formatter(args, context)?),
@ -319,7 +319,7 @@ impl Console {
)
}
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.warn(...data)`
@ -332,12 +332,12 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#warn
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/warn
pub(crate) fn warn(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn warn(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
logger(
LogMessage::Warn(formatter(args, context)?),
context.console(),
);
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.count(label)`
@ -350,7 +350,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#count
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/count
pub(crate) fn count(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn count(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let label = match args.get(0) {
Some(value) => value.to_string(context)?,
None => "default".into(),
@ -364,7 +364,7 @@ impl Console {
LogMessage::Info(format!("{} {}", msg, c)),
context.console(),
);
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.countReset(label)`
@ -377,7 +377,11 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#countreset
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/countReset
pub(crate) fn count_reset(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn count_reset(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let label = match args.get(0) {
Some(value) => value.to_string(context)?,
None => "default".into(),
@ -390,7 +394,7 @@ impl Console {
context.console(),
);
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// Returns current system time in ms.
@ -411,7 +415,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#time
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/time
pub(crate) fn time(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn time(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let label = match args.get(0) {
Some(value) => value.to_string(context)?,
None => "default".into(),
@ -427,7 +431,7 @@ impl Console {
context.console_mut().timer_map.insert(label, time);
}
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.timeLog(label, ...data)`
@ -440,7 +444,11 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#timelog
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/timeLog
pub(crate) fn time_log(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn time_log(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let label = match args.get(0) {
Some(value) => value.to_string(context)?,
None => "default".into(),
@ -460,7 +468,7 @@ impl Console {
);
}
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.timeEnd(label)`
@ -473,7 +481,11 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#timeend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/timeEnd
pub(crate) fn time_end(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn time_end(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let label = match args.get(0) {
Some(value) => value.to_string(context)?,
None => "default".into(),
@ -492,7 +504,7 @@ impl Console {
);
}
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.group(...data)`
@ -505,7 +517,7 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#group
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/group
pub(crate) fn group(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn group(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let group_label = formatter(args, context)?;
logger(
@ -514,7 +526,7 @@ impl Console {
);
context.console_mut().groups.push(group_label);
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.groupEnd(label)`
@ -527,10 +539,10 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#groupend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/groupEnd
pub(crate) fn group_end(_: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn group_end(_: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
context.console_mut().groups.pop();
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `console.dir(item, options)`
@ -543,13 +555,13 @@ impl Console {
///
/// [spec]: https://console.spec.whatwg.org/#dir
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/dir
pub(crate) fn dir(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::undefined();
pub(crate) fn dir(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let undefined = JsValue::undefined();
logger(
LogMessage::Info(display_obj(args.get(0).unwrap_or(&undefined), true)),
context.console(),
);
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}

27
boa/src/builtins/console/tests.rs

@ -1,4 +1,4 @@
use crate::{builtins::console::formatter, Context, Value};
use crate::{builtins::console::formatter, Context, JsValue};
#[test]
fn formatter_no_args_is_empty_string() {
@ -9,14 +9,14 @@ fn formatter_no_args_is_empty_string() {
#[test]
fn formatter_empty_format_string_is_empty_string() {
let mut context = Context::new();
let val = Value::string("".to_string());
let val = JsValue::new("");
assert_eq!(formatter(&[val], &mut context).unwrap(), "");
}
#[test]
fn formatter_format_without_args_renders_verbatim() {
let mut context = Context::new();
let val = [Value::string("%d %s %% %f")];
let val = [JsValue::new("%d %s %% %f")];
let res = formatter(&val, &mut context).unwrap();
assert_eq!(res, "%d %s %% %f");
}
@ -26,9 +26,9 @@ fn formatter_empty_format_string_concatenates_rest_of_args() {
let mut context = Context::new();
let val = [
Value::string(""),
Value::string("to powinno zostać"),
Value::string("połączone"),
JsValue::new(""),
JsValue::new("to powinno zostać"),
JsValue::new("połączone"),
];
let res = formatter(&val, &mut context).unwrap();
assert_eq!(res, " to powinno zostać połączone");
@ -39,10 +39,10 @@ fn formatter_utf_8_checks() {
let mut context = Context::new();
let val = [
Value::string("Są takie chwile %dą %są tu%sów %привет%ź".to_string()),
Value::integer(123),
Value::rational(1.23),
Value::string("ł".to_string()),
JsValue::new("Są takie chwile %dą %są tu%sów %привет%ź".to_string()),
JsValue::new(123),
JsValue::new(1.23),
JsValue::new("ł"),
];
let res = formatter(&val, &mut context).unwrap();
assert_eq!(res, "Są takie chwile 123ą 1.23ą tułów %привет%ź");
@ -52,10 +52,7 @@ fn formatter_utf_8_checks() {
fn formatter_trailing_format_leader_renders() {
let mut context = Context::new();
let val = [
Value::string("%%%%%".to_string()),
Value::string("|".to_string()),
];
let val = [JsValue::new("%%%%%"), JsValue::new("|")];
let res = formatter(&val, &mut context).unwrap();
assert_eq!(res, "%%% |");
}
@ -65,7 +62,7 @@ fn formatter_trailing_format_leader_renders() {
fn formatter_float_format_works() {
let mut context = Context::new();
let val = [Value::string("%f".to_string()), Value::rational(3.1415)];
let val = [JsValue::new("%f"), JsValue::new(3.1415)];
let res = formatter(&val, &mut context).unwrap();
assert_eq!(res, "3.141500");
}

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

@ -6,7 +6,7 @@ use crate::{
gc::{empty_trace, Finalize, Trace},
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
property::Attribute,
value::{PreferredType, Value},
value::{JsValue, PreferredType},
BoaProfiler, Context, Result,
};
use chrono::{prelude::*, Duration, LocalResult};
@ -45,14 +45,14 @@ fn ignore_ambiguity<T>(result: LocalResult<T>) -> Option<T> {
macro_rules! getter_method {
($name:ident) => {{
fn get_value(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
Ok(Value::from(this_time_value(this, context)?.$name()))
fn get_value(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(JsValue::new(this_time_value(this, context)?.$name()))
}
get_value
}};
(Self::$name:ident) => {{
fn get_value(_: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
Ok(Value::from(Date::$name()))
fn get_value(_: &JsValue, _: &[JsValue], _: &mut Context) -> Result<JsValue> {
Ok(JsValue::new(Date::$name()))
}
get_value
}};
@ -60,7 +60,7 @@ macro_rules! getter_method {
macro_rules! setter_method {
($name:ident($($e:expr),* $(,)?)) => {{
fn set_value(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
fn set_value(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let mut result = this_time_value(this, context)?;
result.$name(
$(
@ -82,7 +82,7 @@ macro_rules! setter_method {
);
this.set_data(ObjectData::Date(result));
Ok(Value::from(result.get_time()))
Ok(JsValue::new(result.get_time()))
}
set_value
}};
@ -119,7 +119,7 @@ impl BuiltIn for Date {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let date_object = ConstructorBuilder::new(context, Self::constructor)
@ -366,10 +366,10 @@ impl Date {
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
if new_target.is_undefined() {
Ok(Self::make_date_string())
} else {
@ -405,8 +405,8 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date_string() -> Value {
Value::from(Local::now().to_rfc3339())
pub(crate) fn make_date_string() -> JsValue {
JsValue::new(Local::now().to_rfc3339())
}
/// `Date()`
@ -419,7 +419,7 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date_now(this: &Value) -> Value {
pub(crate) fn make_date_now(this: &JsValue) -> JsValue {
let date = Date::default();
this.set_data(ObjectData::Date(date));
this.clone()
@ -436,15 +436,15 @@ impl Date {
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date_single(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let value = &args[0];
let tv = match this_time_value(value, context) {
Ok(dt) => dt.0,
_ => match value.to_primitive(context, PreferredType::Default)? {
Value::String(ref str) => match chrono::DateTime::parse_from_rfc3339(str) {
JsValue::String(ref str) => match chrono::DateTime::parse_from_rfc3339(str) {
Ok(dt) => Some(dt.naive_utc()),
_ => None,
},
@ -474,10 +474,10 @@ impl Date {
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
pub(crate) fn make_date_multiple(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let year = args[0].to_number(context)?;
let month = args[1].to_number(context)?;
let day = args
@ -1313,8 +1313,8 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date.now
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now
pub(crate) fn now(_: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
Ok(Value::from(Utc::now().timestamp_millis() as f64))
pub(crate) fn now(_: &JsValue, _: &[JsValue], _: &mut Context) -> Result<JsValue> {
Ok(JsValue::new(Utc::now().timestamp_millis() as f64))
}
/// `Date.parse()`
@ -1329,17 +1329,17 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date.parse
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
pub(crate) fn parse(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn parse(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// This method is implementation-defined and discouraged, so we just require the same format as the string
// constructor.
if args.is_empty() {
return Ok(Value::number(f64::NAN));
return Ok(JsValue::nan());
}
match DateTime::parse_from_rfc3339(&args[0].to_string(context)?) {
Ok(v) => Ok(Value::number(v.naive_utc().timestamp_millis() as f64)),
_ => Ok(Value::number(f64::NAN)),
Ok(v) => Ok(JsValue::new(v.naive_utc().timestamp_millis() as f64)),
_ => Ok(JsValue::new(f64::NAN)),
}
}
@ -1353,7 +1353,7 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-date.utc
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC
pub(crate) fn utc(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn utc(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let year = args
.get(0)
.map_or(Ok(f64::NAN), |value| value.to_number(context))?;
@ -1377,7 +1377,7 @@ impl Date {
.map_or(Ok(0f64), |value| value.to_number(context))?;
if !check_normal_opt!(year, month, day, hour, min, sec, milli) {
return Ok(Value::number(f64::NAN));
return Ok(JsValue::nan());
}
let year = year as i32;
@ -1397,7 +1397,7 @@ impl Date {
NaiveDate::from_ymd_opt(year, month + 1, day)
.and_then(|f| f.and_hms_milli_opt(hour, min, sec, milli))
.and_then(|f| Self::time_clip(f.timestamp_millis() as f64))
.map_or(Ok(Value::number(f64::NAN)), |time| Ok(Value::number(time)))
.map_or(Ok(JsValue::nan()), |time| Ok(JsValue::new(time)))
}
}
@ -1414,8 +1414,8 @@ impl Date {
///
/// [spec]: https://tc39.es/ecma262/#sec-thistimevalue
#[inline]
pub fn this_time_value(value: &Value, context: &mut Context) -> Result<Date> {
if let Value::Object(ref object) = value {
pub fn this_time_value(value: &JsValue, context: &mut Context) -> Result<Date> {
if let JsValue::Object(ref object) = value {
if let ObjectData::Date(ref date) = object.borrow().data {
return Ok(*date);
}

110
boa/src/builtins/date/tests.rs

@ -1,6 +1,6 @@
#![allow(clippy::zero_prefixed_literal)]
use crate::{forward, forward_val, object::ObjectData, Context, Value};
use crate::{forward, forward_val, object::ObjectData, Context, JsValue};
use chrono::prelude::*;
// NOTE: Javascript Uses 0-based months, where chrono uses 1-based months. Many of the assertions look wrong because of
@ -13,7 +13,7 @@ fn forward_dt_utc(context: &mut Context, src: &str) -> Option<NaiveDateTime> {
panic!("expected success")
};
if let Value::Object(ref date_time) = date_time {
if let JsValue::Object(ref date_time) = date_time {
if let ObjectData::Date(ref date_time) = date_time.borrow().data {
date_time.0
} else {
@ -66,7 +66,7 @@ fn date_this_time_value() {
.expect_value()
.clone();
assert_eq!(Value::string("\'this\' is not a Date"), *message_property);
assert_eq!(JsValue::new("\'this\' is not a Date"), *message_property);
}
#[test]
@ -212,7 +212,7 @@ fn date_ctor_parse_call() -> Result<(), Box<dyn std::error::Error>> {
let date_time = forward_val(&mut context, "Date.parse('2020-06-08T09:16:15.779-07:30')");
assert_eq!(Ok(Value::Rational(1591634775779f64)), date_time);
assert_eq!(Ok(JsValue::new(1591634775779f64)), date_time);
Ok(())
}
@ -222,7 +222,7 @@ fn date_ctor_utc_call() -> Result<(), Box<dyn std::error::Error>> {
let date_time = forward_val(&mut context, "Date.UTC(2020, 06, 08, 09, 16, 15, 779)");
assert_eq!(Ok(Value::Rational(1594199775779f64)), date_time);
assert_eq!(Ok(JsValue::new(1594199775779f64)), date_time);
Ok(())
}
@ -231,7 +231,7 @@ fn date_ctor_utc_call_nan() -> Result<(), Box<dyn std::error::Error>> {
fn check(src: &str) {
let mut context = Context::new();
let date_time = forward_val(&mut context, src).expect("Expected Success");
assert_eq!(Value::Rational(f64::NAN), date_time);
assert_eq!(JsValue::nan(), date_time);
}
check("Date.UTC(1/0, 06, 08, 09, 16, 15, 779)");
@ -253,10 +253,10 @@ fn date_proto_get_date_call() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(2020, 06, 08, 09, 16, 15, 779).getDate()",
);
assert_eq!(Ok(Value::Rational(08f64)), actual);
assert_eq!(Ok(JsValue::new(08f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getDate()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -269,10 +269,10 @@ fn date_proto_get_day_call() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(2020, 06, 08, 09, 16, 15, 779).getDay()",
);
assert_eq!(Ok(Value::Rational(3f64)), actual);
assert_eq!(Ok(JsValue::new(3f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getDay()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -284,10 +284,10 @@ fn date_proto_get_full_year_call() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(2020, 06, 08, 09, 16, 15, 779).getFullYear()",
);
assert_eq!(Ok(Value::Rational(2020f64)), actual);
assert_eq!(Ok(JsValue::new(2020f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getFullYear()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -299,10 +299,10 @@ fn date_proto_get_hours_call() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(2020, 06, 08, 09, 16, 15, 779).getHours()",
);
assert_eq!(Ok(Value::Rational(09f64)), actual);
assert_eq!(Ok(JsValue::new(09f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getHours()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -314,10 +314,10 @@ fn date_proto_get_milliseconds_call() -> Result<(), Box<dyn std::error::Error>>
&mut context,
"new Date(2020, 06, 08, 09, 16, 15, 779).getMilliseconds()",
);
assert_eq!(Ok(Value::Rational(779f64)), actual);
assert_eq!(Ok(JsValue::new(779f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getMilliseconds()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -329,10 +329,10 @@ fn date_proto_get_minutes_call() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(2020, 06, 08, 09, 16, 15, 779).getMinutes()",
);
assert_eq!(Ok(Value::Rational(16f64)), actual);
assert_eq!(Ok(JsValue::new(16f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getMinutes()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -344,10 +344,10 @@ fn date_proto_get_month() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(2020, 06, 08, 09, 16, 15, 779).getMonth()",
);
assert_eq!(Ok(Value::Rational(06f64)), actual);
assert_eq!(Ok(JsValue::new(06f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getMonth()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -360,10 +360,10 @@ fn date_proto_get_seconds() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(2020, 06, 08, 09, 16, 15, 779).getSeconds()",
);
assert_eq!(Ok(Value::Rational(15f64)), actual);
assert_eq!(Ok(JsValue::new(15f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getSeconds()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -380,10 +380,10 @@ fn date_proto_get_time() -> Result<(), Box<dyn std::error::Error>> {
.ymd(2020, 07, 08)
.and_hms_milli(09, 16, 15, 779)
.timestamp_millis() as f64;
assert_eq!(Ok(Value::Rational(ts)), actual);
assert_eq!(Ok(JsValue::new(ts)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getTime()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -395,10 +395,10 @@ fn date_proto_get_year() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(2020, 06, 08, 09, 16, 15, 779).getYear()",
);
assert_eq!(Ok(Value::Rational(120f64)), actual);
assert_eq!(Ok(JsValue::new(120f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getYear()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -412,7 +412,7 @@ fn date_proto_get_timezone_offset() -> Result<(), Box<dyn std::error::Error>> {
);
// NB: Host Settings, not TZ specified in the DateTime.
assert_eq!(Ok(Value::Boolean(true)), actual);
assert_eq!(Ok(JsValue::new(true)), actual);
let actual = forward_val(
&mut context,
@ -422,13 +422,13 @@ fn date_proto_get_timezone_offset() -> Result<(), Box<dyn std::error::Error>> {
// The value of now().offset() depends on the host machine, so we have to replicate the method code here.
let offset_seconds = chrono::Local::now().offset().local_minus_utc() as f64;
let offset_minutes = offset_seconds / 60f64;
assert_eq!(Ok(Value::Rational(offset_minutes)), actual);
assert_eq!(Ok(JsValue::new(offset_minutes)), actual);
let actual = forward_val(
&mut context,
"new Date(1/0, 06, 08, 09, 16, 15, 779).getTimezoneOffset()",
);
assert_eq!(Ok(Value::Rational(offset_minutes)), actual);
assert_eq!(Ok(JsValue::new(offset_minutes)), actual);
Ok(())
}
@ -440,10 +440,10 @@ fn date_proto_get_utc_date_call() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)).getUTCDate()",
);
assert_eq!(Ok(Value::Rational(08f64)), actual);
assert_eq!(Ok(JsValue::new(08f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getUTCDate()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -456,10 +456,10 @@ fn date_proto_get_utc_day_call() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)).getUTCDay()",
);
assert_eq!(Ok(Value::Rational(3f64)), actual);
assert_eq!(Ok(JsValue::new(3f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getUTCDay()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -471,10 +471,10 @@ fn date_proto_get_utc_full_year_call() -> Result<(), Box<dyn std::error::Error>>
&mut context,
"new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)).getUTCFullYear()",
);
assert_eq!(Ok(Value::Rational(2020f64)), actual);
assert_eq!(Ok(JsValue::new(2020f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getUTCFullYear()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -486,10 +486,10 @@ fn date_proto_get_utc_hours_call() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)).getUTCHours()",
);
assert_eq!(Ok(Value::Rational(09f64)), actual);
assert_eq!(Ok(JsValue::new(09f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getUTCHours()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -501,10 +501,10 @@ fn date_proto_get_utc_milliseconds_call() -> Result<(), Box<dyn std::error::Erro
&mut context,
"new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)).getUTCMilliseconds()",
);
assert_eq!(Ok(Value::Rational(779f64)), actual);
assert_eq!(Ok(JsValue::new(779f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getUTCMilliseconds()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -516,10 +516,10 @@ fn date_proto_get_utc_minutes_call() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)).getUTCMinutes()",
);
assert_eq!(Ok(Value::Rational(16f64)), actual);
assert_eq!(Ok(JsValue::new(16f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getUTCMinutes()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -531,10 +531,10 @@ fn date_proto_get_utc_month() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)).getUTCMonth()",
);
assert_eq!(Ok(Value::Rational(06f64)), actual);
assert_eq!(Ok(JsValue::new(06f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getUTCMonth()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -547,10 +547,10 @@ fn date_proto_get_utc_seconds() -> Result<(), Box<dyn std::error::Error>> {
&mut context,
"new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)).getUTCSeconds()",
);
assert_eq!(Ok(Value::Rational(15f64)), actual);
assert_eq!(Ok(JsValue::new(15f64)), actual);
let actual = forward_val(&mut context, "new Date(1/0).getUTCSeconds()");
assert_eq!(Ok(Value::Rational(f64::NAN)), actual);
assert_eq!(Ok(JsValue::nan()), actual);
Ok(())
}
@ -1216,7 +1216,7 @@ fn date_proto_to_date_string() -> Result<(), Box<dyn std::error::Error>> {
"let dt = new Date(2020, 06, 08, 09, 16, 15, 779); dt.toDateString()",
)
.expect("Successful eval");
assert_eq!(Value::string("Wed Jul 08 2020"), actual);
assert_eq!(JsValue::new("Wed Jul 08 2020"), actual);
Ok(())
}
@ -1230,7 +1230,7 @@ fn date_proto_to_gmt_string() -> Result<(), Box<dyn std::error::Error>> {
"let dt = new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)); dt.toGMTString()",
)
.expect("Successful eval");
assert_eq!(Value::string("Wed, 08 Jul 2020 09:16:15 GMT"), actual);
assert_eq!(JsValue::new("Wed, 08 Jul 2020 09:16:15 GMT"), actual);
Ok(())
}
@ -1244,7 +1244,7 @@ fn date_proto_to_iso_string() -> Result<(), Box<dyn std::error::Error>> {
"let dt = new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)); dt.toISOString()",
)
.expect("Successful eval");
assert_eq!(Value::string("2020-07-08T09:16:15.779Z"), actual);
assert_eq!(JsValue::new("2020-07-08T09:16:15.779Z"), actual);
Ok(())
}
@ -1258,7 +1258,7 @@ fn date_proto_to_json() -> Result<(), Box<dyn std::error::Error>> {
"let dt = new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)); dt.toJSON()",
)
.expect("Successful eval");
assert_eq!(Value::string("2020-07-08T09:16:15.779Z"), actual);
assert_eq!(JsValue::new("2020-07-08T09:16:15.779Z"), actual);
Ok(())
}
@ -1274,7 +1274,7 @@ fn date_proto_to_string() -> Result<(), Box<dyn std::error::Error>> {
.ok();
assert_eq!(
Some(Value::string(
Some(JsValue::new(
Local
.from_local_datetime(&NaiveDateTime::new(
NaiveDate::from_ymd(2020, 6, 8),
@ -1302,7 +1302,7 @@ fn date_proto_to_time_string() -> Result<(), Box<dyn std::error::Error>> {
.ok();
assert_eq!(
Some(Value::string(
Some(JsValue::new(
Local
.from_local_datetime(&NaiveDateTime::new(
NaiveDate::from_ymd(2020, 6, 8),
@ -1328,7 +1328,7 @@ fn date_proto_to_utc_string() -> Result<(), Box<dyn std::error::Error>> {
"let dt = new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)); dt.toUTCString()",
)
.expect("Successful eval");
assert_eq!(Value::string("Wed, 08 Jul 2020 09:16:15 GMT"), actual);
assert_eq!(JsValue::new("Wed, 08 Jul 2020 09:16:15 GMT"), actual);
Ok(())
}
@ -1342,7 +1342,7 @@ fn date_proto_value_of() -> Result<(), Box<dyn std::error::Error>> {
"new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779)).valueOf()",
)
.expect("Successful eval");
assert_eq!(Value::number(1594199775779f64), actual);
assert_eq!(JsValue::new(1594199775779f64), actual);
Ok(())
}
@ -1356,7 +1356,7 @@ fn date_neg() -> Result<(), Box<dyn std::error::Error>> {
"-new Date(Date.UTC(2020, 06, 08, 09, 16, 15, 779))",
)
.expect("Successful eval");
assert_eq!(Value::number(-1594199775779f64), actual);
assert_eq!(JsValue::new(-1594199775779f64), actual);
Ok(())
}
@ -1371,7 +1371,7 @@ fn date_json() -> Result<(), Box<dyn std::error::Error>> {
)
.expect("Successful eval");
assert_eq!(
Value::string(r#"{"date":"2020-07-08T09:16:15.779Z"}"#),
JsValue::new(r#"{"date":"2020-07-08T09:16:15.779Z"}"#),
actual
);

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

@ -17,7 +17,7 @@ use crate::{
object::{ConstructorBuilder, ObjectData},
profiler::BoaProfiler,
property::Attribute,
Context, Result, Value,
Context, JsValue, Result,
};
/// JavaScript `EvalError` impleentation.
@ -31,7 +31,7 @@ impl BuiltIn for EvalError {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let error_prototype = context.standard_objects().error_object().prototype();
@ -58,10 +58,10 @@ impl EvalError {
/// Create a new error object.
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let prototype = new_target
.as_object()
.and_then(|obj| {
@ -73,7 +73,7 @@ impl EvalError {
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = Value::from(obj);
let this = JsValue::new(obj);
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;

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

@ -15,7 +15,7 @@ use crate::{
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
profiler::BoaProfiler,
property::Attribute,
Context, Result, Value,
Context, JsValue, Result,
};
pub(crate) mod eval;
@ -46,7 +46,7 @@ impl BuiltIn for Error {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
@ -74,10 +74,10 @@ impl Error {
///
/// Create a new error object.
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let prototype = new_target
.as_object()
.and_then(|obj| {
@ -89,7 +89,7 @@ impl Error {
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = Value::from(obj);
let this = JsValue::new(obj);
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;
@ -113,7 +113,11 @@ impl Error {
/// [spec]: https://tc39.es/ecma262/#sec-error.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_string(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
if !this.is_object() {
return context.throw_type_error("'this' is not an Object");
}

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

@ -14,7 +14,7 @@ use crate::{
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
profiler::BoaProfiler,
property::Attribute,
Context, Result, Value,
Context, JsValue, Result,
};
/// JavaScript `RangeError` implementation.
@ -28,7 +28,7 @@ impl BuiltIn for RangeError {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let error_prototype = context.standard_objects().error_object().prototype();
@ -55,10 +55,10 @@ impl RangeError {
/// Create a new error object.
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let prototype = new_target
.as_object()
.and_then(|obj| {
@ -70,7 +70,7 @@ impl RangeError {
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = Value::from(obj);
let this = JsValue::new(obj);
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;

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

@ -14,7 +14,7 @@ use crate::{
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
profiler::BoaProfiler,
property::Attribute,
Context, Result, Value,
Context, JsValue, Result,
};
#[derive(Debug, Clone, Copy)]
@ -27,7 +27,7 @@ impl BuiltIn for ReferenceError {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let error_prototype = context.standard_objects().error_object().prototype();
@ -54,10 +54,10 @@ impl ReferenceError {
/// Create a new error object.
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let prototype = new_target
.as_object()
.and_then(|obj| {
@ -69,7 +69,7 @@ impl ReferenceError {
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = Value::from(obj);
let this = JsValue::new(obj);
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;

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

@ -16,7 +16,7 @@ use crate::{
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
profiler::BoaProfiler,
property::Attribute,
Context, Result, Value,
Context, JsValue, Result,
};
/// JavaScript `SyntaxError` impleentation.
@ -30,7 +30,7 @@ impl BuiltIn for SyntaxError {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let error_prototype = context.standard_objects().error_object().prototype();
@ -57,10 +57,10 @@ impl SyntaxError {
/// Create a new error object.
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let prototype = new_target
.as_object()
.and_then(|obj| {
@ -72,7 +72,7 @@ impl SyntaxError {
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = Value::from(obj);
let this = JsValue::new(obj);
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;

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

@ -19,7 +19,7 @@ use crate::{
builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
property::Attribute,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
/// JavaScript `TypeError` implementation.
@ -33,7 +33,7 @@ impl BuiltIn for TypeError {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let error_prototype = context.standard_objects().error_object().prototype();
@ -60,10 +60,10 @@ impl TypeError {
/// Create a new error object.
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let prototype = new_target
.as_object()
.and_then(|obj| {
@ -75,7 +75,7 @@ impl TypeError {
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = Value::from(obj);
let this = JsValue::new(obj);
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;

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

@ -15,7 +15,7 @@ use crate::{
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
profiler::BoaProfiler,
property::Attribute,
Context, Result, Value,
Context, JsValue, Result,
};
/// JavaScript `URIError` impleentation.
@ -29,7 +29,7 @@ impl BuiltIn for UriError {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let error_prototype = context.standard_objects().error_object().prototype();
@ -56,10 +56,10 @@ impl UriError {
/// Create a new error object.
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let prototype = new_target
.as_object()
.and_then(|obj| {
@ -71,7 +71,7 @@ impl UriError {
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = Value::from(obj);
let this = JsValue::new(obj);
if let Some(message) = args.get(0) {
if !message.is_undefined() {
this.set_field("message", message.to_string(context)?, false, context)?;

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

@ -19,7 +19,7 @@ use crate::{
object::{ConstructorBuilder, FunctionBuilder, GcObject, Object, ObjectData},
property::{Attribute, PropertyDescriptor},
syntax::ast::node::{FormalParameter, RcStatementList},
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use bitflags::bitflags;
use std::fmt::{self, Debug};
@ -29,10 +29,10 @@ use std::rc::Rc;
mod tests;
/// _fn(this, arguments, context) -> ResultValue_ - The signature of a native built-in function
pub type NativeFunction = fn(&Value, &[Value], &mut Context) -> Result<Value>;
pub type NativeFunction = fn(&JsValue, &[JsValue], &mut Context) -> Result<JsValue>;
/// _fn(this, arguments, context) -> ResultValue_ - The signature of a closure built-in function
pub type ClosureFunction = dyn Fn(&Value, &[Value], &mut Context) -> Result<Value>;
pub type ClosureFunction = dyn Fn(&JsValue, &[JsValue], &mut Context) -> Result<JsValue>;
#[derive(Clone, Copy, Finalize)]
pub struct BuiltInFunction(pub(crate) NativeFunction);
@ -124,7 +124,7 @@ impl Function {
&self,
param: &FormalParameter,
index: usize,
args_list: &[Value],
args_list: &[JsValue],
context: &mut Context,
local_env: &Environment,
) {
@ -149,7 +149,7 @@ impl Function {
pub(crate) fn add_arguments_to_environment(
&self,
param: &FormalParameter,
value: Value,
value: JsValue,
local_env: &Environment,
context: &mut Context,
) {
@ -177,7 +177,7 @@ impl Function {
/// Arguments.
///
/// <https://tc39.es/ecma262/#sec-createunmappedargumentsobject>
pub fn create_unmapped_arguments_object(arguments_list: &[Value]) -> Value {
pub fn create_unmapped_arguments_object(arguments_list: &[JsValue]) -> JsValue {
let len = arguments_list.len();
let obj = GcObject::new(Object::default());
// Set length
@ -201,7 +201,7 @@ pub fn create_unmapped_arguments_object(arguments_list: &[Value]) -> Value {
index += 1;
}
Value::from(obj)
JsValue::new(obj)
}
/// Creates a new member function of a `Object` or `prototype`.
@ -268,7 +268,7 @@ pub struct BuiltInFunctionObject;
impl BuiltInFunctionObject {
pub const LENGTH: usize = 1;
fn constructor(new_target: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
fn constructor(new_target: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
let prototype = new_target
.as_object()
.and_then(|obj| {
@ -278,21 +278,21 @@ impl BuiltInFunctionObject {
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let this = Value::new_object(context);
let this = JsValue::new_object(context);
this.as_object()
.expect("this should be an object")
.set_prototype_instance(prototype.into());
this.set_data(ObjectData::Function(Function::Native {
function: BuiltInFunction(|_, _, _| Ok(Value::undefined())),
function: BuiltInFunction(|_, _, _| Ok(JsValue::undefined())),
constructable: true,
}));
Ok(this)
}
fn prototype(_: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
Ok(Value::undefined())
fn prototype(_: &JsValue, _: &[JsValue], _: &mut Context) -> Result<JsValue> {
Ok(JsValue::undefined())
}
/// `Function.prototype.call`
@ -305,11 +305,11 @@ impl BuiltInFunctionObject {
///
/// [spec]: https://tc39.es/ecma262/#sec-function.prototype.call
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
fn call(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
fn call(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
if !this.is_function() {
return context.throw_type_error(format!("{} is not a function", this.display()));
}
let this_arg: Value = args.get(0).cloned().unwrap_or_default();
let this_arg: JsValue = args.get(0).cloned().unwrap_or_default();
// TODO?: 3. Perform PrepareForTailCall
let start = if !args.is_empty() { 1 } else { 0 };
context.call(this, &this_arg, &args[start..])
@ -326,7 +326,7 @@ impl BuiltInFunctionObject {
///
/// [spec]: https://tc39.es/ecma262/#sec-function.prototype.apply
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
fn apply(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
fn apply(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
if !this.is_function() {
return context.throw_type_error(format!("{} is not a function", this.display()));
}
@ -352,7 +352,7 @@ impl BuiltIn for BuiltInFunctionObject {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event("function", "init");
let function_prototype = context.standard_objects().function_object().prototype();

4
boa/src/builtins/global_this/mod.rs

@ -10,7 +10,7 @@
//! [spec]: https://tc39.es/ecma262/#sec-globalthis
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis
use crate::{builtins::BuiltIn, property::Attribute, BoaProfiler, Context, Value};
use crate::{builtins::BuiltIn, property::Attribute, BoaProfiler, Context, JsValue};
#[cfg(test)]
mod tests;
@ -25,7 +25,7 @@ impl BuiltIn for GlobalThis {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(

4
boa/src/builtins/infinity/mod.rs

@ -12,7 +12,7 @@
#[cfg(test)]
mod tests;
use crate::{builtins::BuiltIn, property::Attribute, BoaProfiler, Context, Value};
use crate::{builtins::BuiltIn, property::Attribute, BoaProfiler, Context, JsValue};
/// JavaScript global `Infinity` property.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -25,7 +25,7 @@ impl BuiltIn for Infinity {
Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT
}
fn init(_: &mut Context) -> (&'static str, Value, Attribute) {
fn init(_: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, f64::INFINITY.into(), Self::attribute())

24
boa/src/builtins/iterable/mod.rs

@ -6,7 +6,7 @@ use crate::{
},
object::{GcObject, ObjectInitializer},
symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
#[derive(Debug, Default)]
@ -85,7 +85,7 @@ impl IteratorPrototypes {
/// CreateIterResultObject( value, done )
///
/// Generates an object supporting the IteratorResult interface.
pub fn create_iter_result_object(context: &mut Context, value: Value, done: bool) -> Value {
pub fn create_iter_result_object(context: &mut Context, value: JsValue, done: bool) -> JsValue {
// 1. Assert: Type(done) is Boolean.
// 2. Let obj be ! OrdinaryObjectCreate(%Object.prototype%).
let obj = context.construct_object();
@ -101,7 +101,7 @@ pub fn create_iter_result_object(context: &mut Context, value: Value, done: bool
}
/// Get an iterator record
pub fn get_iterator(context: &mut Context, iterable: Value) -> Result<IteratorRecord> {
pub fn get_iterator(context: &mut Context, iterable: JsValue) -> Result<IteratorRecord> {
let iterator_function = iterable.get_field(WellKnownSymbols::iterator(), context)?;
if iterator_function.is_null_or_undefined() {
return Err(context.construct_type_error("Not an iterable"));
@ -136,12 +136,12 @@ fn create_iterator_prototype(context: &mut Context) -> GcObject {
#[derive(Debug)]
pub struct IteratorRecord {
iterator_object: Value,
next_function: Value,
iterator_object: JsValue,
next_function: JsValue,
}
impl IteratorRecord {
pub fn new(iterator_object: Value, next_function: Value) -> Self {
pub fn new(iterator_object: JsValue, next_function: JsValue) -> Self {
Self {
iterator_object,
next_function,
@ -168,7 +168,11 @@ impl IteratorRecord {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-iteratorclose
pub(crate) fn close(&self, completion: Result<Value>, context: &mut Context) -> Result<Value> {
pub(crate) fn close(
&self,
completion: Result<JsValue>,
context: &mut Context,
) -> Result<JsValue> {
let mut inner_result = self.iterator_object.get_field("return", context);
// 5
@ -199,12 +203,12 @@ impl IteratorRecord {
#[derive(Debug)]
pub struct IteratorResult {
value: Value,
value: JsValue,
done: bool,
}
impl IteratorResult {
fn new(value: Value, done: bool) -> Self {
fn new(value: JsValue, done: bool) -> Self {
Self { value, done }
}
@ -212,7 +216,7 @@ impl IteratorResult {
self.done
}
pub fn value(self) -> Value {
pub fn value(self) -> JsValue {
self.value
}
}

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

@ -20,7 +20,7 @@ use crate::{
property::{Attribute, PropertyDescriptor, PropertyKey},
symbol::WellKnownSymbols,
value::IntegerOrInfinity,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use serde::Serialize;
use serde_json::{self, ser::PrettyFormatter, Serializer, Value as JSONValue};
@ -39,7 +39,7 @@ impl BuiltIn for Json {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let to_string_tag = WellKnownSymbols::to_string_tag();
@ -68,19 +68,19 @@ impl Json {
///
/// [spec]: https://tc39.es/ecma262/#sec-json.parse
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
pub(crate) fn parse(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn parse(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let arg = args
.get(0)
.cloned()
.unwrap_or_else(Value::undefined)
.unwrap_or_else(JsValue::undefined)
.to_string(context)?;
match serde_json::from_str::<JSONValue>(&arg) {
Ok(json) => {
let j = Value::from_json(json, context);
let j = JsValue::from_json(json, context);
match args.get(1) {
Some(reviver) if reviver.is_function() => {
let mut holder = Value::object(Object::default());
let mut holder: JsValue = context.construct_object().into();
holder.set_field("", j, true, context)?;
Self::walk(reviver, context, &mut holder, &PropertyKey::from(""))
}
@ -98,14 +98,14 @@ impl Json {
///
/// [polyfill]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
fn walk(
reviver: &Value,
reviver: &JsValue,
context: &mut Context,
holder: &mut Value,
holder: &mut JsValue,
key: &PropertyKey,
) -> Result<Value> {
) -> Result<JsValue> {
let value = holder.get_field(key.clone(), context)?;
if let Value::Object(ref object) = value {
if let JsValue::Object(ref object) = value {
let keys: Vec<_> = object.borrow().properties().keys().collect();
for key in keys {
@ -140,18 +140,22 @@ impl Json {
///
/// [spec]: https://tc39.es/ecma262/#sec-json.stringify
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
pub(crate) fn stringify(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn stringify(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let object = match args.get(0) {
None => return Ok(Value::undefined()),
None => return Ok(JsValue::undefined()),
Some(obj) => obj,
};
const SPACE_INDENT: &str = " ";
let gap = if let Some(space) = args.get(2) {
let space = if let Some(space_obj) = space.as_object() {
if let Some(space) = space_obj.borrow().as_number() {
Value::from(space)
JsValue::new(space)
} else if let Some(space) = space_obj.borrow().as_string() {
Value::from(space)
JsValue::new(space)
} else {
space.clone()
}
@ -165,14 +169,14 @@ impl Json {
IntegerOrInfinity::Integer(i) if i < 1 => 0,
IntegerOrInfinity::Integer(i) => std::cmp::min(i, 10) as usize,
};
Value::from(&SPACE_INDENT[..space_mv])
JsValue::new(&SPACE_INDENT[..space_mv])
} else if let Some(string) = space.as_string() {
Value::from(&string[..std::cmp::min(string.len(), 10)])
JsValue::new(&string[..std::cmp::min(string.len(), 10)])
} else {
Value::from("")
JsValue::new("")
}
} else {
Value::from("")
JsValue::new("")
};
let gap = &gap.to_string(context)?;
@ -181,9 +185,9 @@ impl Json {
Some(replacer) if replacer.is_object() => replacer,
_ => {
if let Some(value) = object.to_json(context)? {
return Ok(Value::from(json_to_pretty_string(&value, gap)));
return Ok(JsValue::new(json_to_pretty_string(&value, gap)));
} else {
return Ok(Value::undefined());
return Ok(JsValue::undefined());
}
}
};
@ -195,7 +199,7 @@ impl Json {
object
.as_object()
.map(|obj| {
let object_to_return = Value::object(Object::default());
let object_to_return = JsValue::new(Object::default());
for key in obj.borrow().properties().keys() {
let val = obj.__get__(&key, obj.clone().into(), context)?;
let this_arg = object.clone();
@ -205,7 +209,7 @@ impl Json {
.value(context.call(
replacer,
&this_arg,
&[Value::from(key.clone()), val.clone()],
&[JsValue::new(key.clone()), val.clone()],
)?)
.writable(true)
.enumerable(true)
@ -213,12 +217,12 @@ impl Json {
)
}
if let Some(value) = object_to_return.to_json(context)? {
Ok(Value::from(json_to_pretty_string(&value, gap)))
Ok(JsValue::new(json_to_pretty_string(&value, gap)))
} else {
Ok(Value::undefined())
Ok(JsValue::undefined())
}
})
.ok_or_else(Value::undefined)?
.ok_or_else(JsValue::undefined)?
} else if replacer_as_object.is_array() {
let mut obj_to_return = serde_json::Map::new();
let replacer_as_object = replacer_as_object.borrow();
@ -245,14 +249,14 @@ impl Json {
}
}
}
Ok(Value::from(json_to_pretty_string(
Ok(JsValue::new(json_to_pretty_string(
&JSONValue::Object(obj_to_return),
gap,
)))
} else if let Some(value) = object.to_json(context)? {
Ok(Value::from(json_to_pretty_string(&value, gap)))
Ok(JsValue::new(json_to_pretty_string(&value, gap)))
} else {
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}
}

13
boa/src/builtins/json/tests.rs

@ -1,4 +1,4 @@
use crate::{forward, forward_val, Context, Value};
use crate::{forward, forward_val, Context, JsValue};
#[test]
fn json_sanity() {
@ -418,18 +418,21 @@ fn json_parse_sets_prototypes() {
.as_object()
.unwrap()
.prototype_instance();
let global_object_prototype: Value = context
let global_object_prototype: JsValue = context
.standard_objects()
.object_object()
.prototype()
.into();
let global_array_prototype: Value =
let global_array_prototype: JsValue =
context.standard_objects().array_object().prototype().into();
assert!(Value::same_value(
assert!(JsValue::same_value(
&object_prototype,
&global_object_prototype
));
assert!(Value::same_value(&array_prototype, &global_array_prototype));
assert!(JsValue::same_value(
&array_prototype,
&global_array_prototype
));
}
#[test]

34
boa/src/builtins/map/map_iterator.rs

@ -1,5 +1,5 @@
use crate::{
builtins::{function::make_builtin_fn, iterable::create_iter_result_object, Array, Value},
builtins::{function::make_builtin_fn, iterable::create_iter_result_object, Array, JsValue},
object::{GcObject, ObjectData},
property::PropertyDescriptor,
symbol::WellKnownSymbols,
@ -24,7 +24,7 @@ pub enum MapIterationKind {
/// [spec]: https://tc39.es/ecma262/#sec-array-iterator-objects
#[derive(Debug, Clone, Finalize, Trace)]
pub struct MapIterator {
iterated_map: Value,
iterated_map: JsValue,
map_next_index: usize,
map_iteration_kind: MapIterationKind,
lock: MapLock,
@ -34,7 +34,7 @@ impl MapIterator {
pub(crate) const NAME: &'static str = "MapIterator";
/// Constructs a new `MapIterator`, that will iterate over `map`, starting at index 0
fn new(map: Value, kind: MapIterationKind, context: &mut Context) -> Result<Self> {
fn new(map: JsValue, kind: MapIterationKind, context: &mut Context) -> Result<Self> {
let lock = Map::lock(&map, context)?;
Ok(MapIterator {
iterated_map: map,
@ -54,10 +54,10 @@ impl MapIterator {
/// [spec]: https://www.ecma-international.org/ecma-262/11.0/index.html#sec-createmapiterator
pub(crate) fn create_map_iterator(
context: &mut Context,
map: Value,
map: JsValue,
kind: MapIterationKind,
) -> Result<Value> {
let map_iterator = Value::new_object(context);
) -> Result<JsValue> {
let map_iterator = JsValue::new_object(context);
map_iterator.set_data(ObjectData::MapIterator(Self::new(map, kind, context)?));
map_iterator
.as_object()
@ -74,8 +74,8 @@ impl MapIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%mapiteratorprototype%.next
pub(crate) fn next(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
if let Value::Object(ref object) = this {
pub(crate) fn next(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
if let JsValue::Object(ref object) = this {
let mut object = object.borrow_mut();
if let Some(map_iterator) = object.as_map_iterator_mut() {
let m = &map_iterator.iterated_map;
@ -83,10 +83,14 @@ impl MapIterator {
let item_kind = &map_iterator.map_iteration_kind;
if map_iterator.iterated_map.is_undefined() {
return Ok(create_iter_result_object(context, Value::undefined(), true));
return Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
));
}
if let Value::Object(ref object) = m {
if let JsValue::Object(ref object) = m {
if let Some(entries) = object.borrow().as_map_ref() {
let num_entries = entries.full_len();
while index < num_entries {
@ -129,8 +133,12 @@ impl MapIterator {
return Err(context.construct_type_error("'this' is not a Map"));
}
map_iterator.iterated_map = Value::undefined();
Ok(create_iter_result_object(context, Value::undefined(), true))
map_iterator.iterated_map = JsValue::undefined();
Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
))
} else {
context.throw_type_error("`this` is not an MapIterator")
}
@ -145,7 +153,7 @@ impl MapIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%mapiteratorprototype%-object
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: Value) -> GcObject {
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: JsValue) -> GcObject {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// Create prototype

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

@ -17,7 +17,7 @@ use crate::{
object::{ConstructorBuilder, FunctionBuilder, ObjectData, PROTOTYPE},
property::{Attribute, PropertyDescriptor},
symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use ordered_map::OrderedMap;
@ -31,7 +31,7 @@ pub mod ordered_map;
mod tests;
#[derive(Debug, Clone)]
pub(crate) struct Map(OrderedMap<Value>);
pub(crate) struct Map(OrderedMap<JsValue>);
impl BuiltIn for Map {
const NAME: &'static str = "Map";
@ -40,7 +40,7 @@ impl BuiltIn for Map {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let to_string_tag = WellKnownSymbols::to_string_tag();
@ -104,10 +104,10 @@ impl Map {
/// Create a new map
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
if new_target.is_undefined() {
return context
.throw_type_error("calling a builtin Map constructor without new is forbidden");
@ -125,13 +125,13 @@ impl Map {
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let this = Value::from(obj);
let this = JsValue::new(obj);
// add our arguments in
let data = match args.len() {
0 => OrderedMap::new(),
_ => match &args[0] {
Value::Object(object) => {
JsValue::Object(object) => {
let object = object.borrow();
if let Some(map) = object.as_map_ref().cloned() {
map
@ -182,7 +182,7 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-map-@@species
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@species
fn get_species(this: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> Result<JsValue> {
// 1. Return the this value.
Ok(this.clone())
}
@ -197,7 +197,7 @@ impl Map {
///
/// [spec]: https://www.ecma-international.org/ecma-262/11.0/index.html#sec-map.prototype.entries
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries
pub(crate) fn entries(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn entries(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
MapIterator::create_map_iterator(context, this.clone(), MapIterationKind::KeyAndValue)
}
@ -211,12 +211,12 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.keys
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys
pub(crate) fn keys(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn keys(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
MapIterator::create_map_iterator(context, this.clone(), MapIterationKind::Key)
}
/// Helper function to set the size property.
fn set_size(this: &Value, size: usize) {
fn set_size(this: &JsValue, size: usize) {
let size = PropertyDescriptor::builder()
.value(size)
.writable(false)
@ -236,10 +236,10 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.set
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set
pub(crate) fn set(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn set(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let (key, value) = match args.len() {
0 => (Value::Undefined, Value::Undefined),
1 => (args[0].clone(), Value::Undefined),
0 => (JsValue::undefined(), JsValue::undefined()),
1 => (args[0].clone(), JsValue::undefined()),
_ => (args[0].clone(), args[1].clone()),
};
@ -268,16 +268,16 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.delete
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete
pub(crate) fn delete(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::Undefined;
let key = match args.len() {
0 => &undefined,
_ => &args[0],
};
pub(crate) fn delete(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let key = args.get(0).cloned().unwrap_or_default();
let (deleted, size) = if let Some(object) = this.as_object() {
if let Some(map) = object.borrow_mut().as_map_mut() {
let deleted = map.remove(key).is_some();
let deleted = map.remove(&key).is_some();
(deleted, map.len())
} else {
return Err(context.construct_type_error("'this' is not a Map"));
@ -299,20 +299,16 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.get
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get
pub(crate) fn get(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::Undefined;
let key = match args.len() {
0 => &undefined,
_ => &args[0],
};
pub(crate) fn get(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let key = args.get(0).cloned().unwrap_or_default();
if let Value::Object(ref object) = this {
if let JsValue::Object(ref object) = this {
let object = object.borrow();
if let Some(map) = object.as_map_ref() {
return Ok(if let Some(result) = map.get(key) {
return Ok(if let Some(result) = map.get(&key) {
result.clone()
} else {
Value::Undefined
JsValue::undefined()
});
}
}
@ -330,12 +326,12 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.clear
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear
pub(crate) fn clear(this: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
pub(crate) fn clear(this: &JsValue, _: &[JsValue], _: &mut Context) -> Result<JsValue> {
this.set_data(ObjectData::Map(OrderedMap::new()));
Self::set_size(this, 0);
Ok(Value::Undefined)
Ok(JsValue::undefined())
}
/// `Map.prototype.has( key )`
@ -348,17 +344,13 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.has
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has
pub(crate) fn has(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::Undefined;
let key = match args.len() {
0 => &undefined,
_ => &args[0],
};
pub(crate) fn has(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let key = args.get(0).cloned().unwrap_or_default();
if let Value::Object(ref object) = this {
if let JsValue::Object(ref object) = this {
let object = object.borrow();
if let Some(map) = object.as_map_ref() {
return Ok(map.contains_key(key).into());
return Ok(map.contains_key(&key).into());
}
}
@ -375,20 +367,24 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.foreach
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach
pub(crate) fn for_each(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn for_each(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
if args.is_empty() {
return Err(Value::from("Missing argument for Map.prototype.forEach"));
return Err(JsValue::new("Missing argument for Map.prototype.forEach"));
}
let callback_arg = &args[0];
let this_arg = args.get(1).cloned().unwrap_or_else(Value::undefined);
let this_arg = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
let mut index = 0;
let lock = Map::lock(this, context)?;
while index < Map::get_full_len(this, context)? {
let arguments = if let Value::Object(ref object) = this {
let arguments = if let JsValue::Object(ref object) = this {
let object = object.borrow();
if let Some(map) = object.as_map_ref() {
if let Some((key, value)) = map.get_index(index) {
@ -412,12 +408,12 @@ impl Map {
drop(lock);
Ok(Value::Undefined)
Ok(JsValue::undefined())
}
/// Helper function to get the full size of the map.
fn get_full_len(map: &Value, context: &mut Context) -> Result<usize> {
if let Value::Object(ref object) = map {
fn get_full_len(map: &JsValue, context: &mut Context) -> Result<usize> {
if let JsValue::Object(ref object) = map {
let object = object.borrow();
if let Some(map) = object.as_map_ref() {
Ok(map.full_len())
@ -430,8 +426,8 @@ impl Map {
}
/// Helper function to lock the map.
fn lock(map: &Value, context: &mut Context) -> Result<MapLock> {
if let Value::Object(ref object) = map {
fn lock(map: &JsValue, context: &mut Context) -> Result<MapLock> {
if let JsValue::Object(ref object) = map {
let mut map = object.borrow_mut();
if let Some(map) = map.as_map_mut() {
Ok(map.lock(object.clone()))
@ -453,18 +449,18 @@ impl Map {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.values
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values
pub(crate) fn values(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn values(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
MapIterator::create_map_iterator(context, this.clone(), MapIterationKind::Value)
}
/// Helper function to get a key-value pair from an array.
fn get_key_value(value: &Value, context: &mut Context) -> Result<Option<(Value, Value)>> {
if let Value::Object(object) = value {
fn get_key_value(value: &JsValue, context: &mut Context) -> Result<Option<(JsValue, JsValue)>> {
if let JsValue::Object(object) = value {
if object.is_array() {
let (key, value) =
match value.get_field("length", context)?.as_number().unwrap() as i32 {
0 => (Value::Undefined, Value::Undefined),
1 => (value.get_field("0", context)?, Value::Undefined),
0 => (JsValue::undefined(), JsValue::undefined()),
1 => (value.get_field("0", context)?, JsValue::undefined()),
_ => (
value.get_field("0", context)?,
value.get_field("1", context)?,

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

@ -1,7 +1,7 @@
use crate::{
gc::{custom_trace, Finalize, Trace},
object::GcObject,
Value,
JsValue,
};
use indexmap::{Equivalent, IndexMap};
use std::{
@ -12,7 +12,7 @@ use std::{
#[derive(PartialEq, Eq, Clone, Debug)]
enum MapKey {
Key(Value),
Key(JsValue),
Empty(usize), // Necessary to ensure empty keys are still unique.
}
@ -27,7 +27,7 @@ impl Hash for MapKey {
}
}
impl Equivalent<MapKey> for Value {
impl Equivalent<MapKey> for JsValue {
fn equivalent(&self, key: &MapKey) -> bool {
match key {
MapKey::Key(v) => v == self,
@ -116,7 +116,7 @@ impl<V> OrderedMap<V> {
/// inserted, last in order, and `None` is returned.
///
/// Computes in **O(1)** time (amortized average).
pub fn insert(&mut self, key: Value, value: V) -> Option<V> {
pub fn insert(&mut self, key: JsValue, value: V) -> Option<V> {
self.map.insert(MapKey::Key(key), Some(value)).flatten()
}
@ -130,7 +130,7 @@ impl<V> OrderedMap<V> {
/// Return `None` if `key` is not in map.
///
/// Computes in **O(n)** time (average).
pub fn remove(&mut self, key: &Value) -> Option<V> {
pub fn remove(&mut self, key: &JsValue) -> Option<V> {
if self.lock == 0 {
self.map.shift_remove(key).flatten()
} else if self.map.contains_key(key) {
@ -146,14 +146,14 @@ impl<V> OrderedMap<V> {
/// else `None`.
///
/// Computes in **O(1)** time (average).
pub fn get(&self, key: &Value) -> Option<&V> {
pub fn get(&self, key: &JsValue) -> Option<&V> {
self.map.get(key).map(Option::as_ref).flatten()
}
/// Get a key-value pair by index
/// Valid indices are 0 <= index < self.full_len()
/// Computes in O(1) time.
pub fn get_index(&self, index: usize) -> Option<(&Value, &V)> {
pub fn get_index(&self, index: usize) -> Option<(&JsValue, &V)> {
if let (MapKey::Key(key), Some(value)) = self.map.get_index(index)? {
Some((key, value))
} else {
@ -162,7 +162,7 @@ impl<V> OrderedMap<V> {
}
/// Return an iterator over the key-value pairs of the map, in their order
pub fn iter(&self) -> impl Iterator<Item = (&Value, &V)> {
pub fn iter(&self) -> impl Iterator<Item = (&JsValue, &V)> {
self.map.iter().filter_map(|o| {
if let (MapKey::Key(key), Some(value)) = o {
Some((key, value))
@ -175,7 +175,7 @@ impl<V> OrderedMap<V> {
/// Return `true` if an equivalent to `key` exists in the map.
///
/// Computes in **O(1)** time (average).
pub fn contains_key(&self, key: &Value) -> bool {
pub fn contains_key(&self, key: &JsValue) -> bool {
self.map.contains_key(key)
}

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

@ -13,7 +13,7 @@
use crate::{
builtins::BuiltIn, object::ObjectInitializer, property::Attribute, symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
#[cfg(test)]
@ -30,7 +30,7 @@ impl BuiltIn for Math {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;
@ -99,7 +99,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.abs
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/abs
pub(crate) fn abs(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn abs(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -116,7 +116,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.acos
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/acos
pub(crate) fn acos(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn acos(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -133,7 +133,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.acosh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/acosh
pub(crate) fn acosh(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn acosh(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -150,7 +150,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.asin
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/asin
pub(crate) fn asin(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn asin(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -167,7 +167,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.asinh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/asinh
pub(crate) fn asinh(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn asinh(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -184,7 +184,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.atan
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan
pub(crate) fn atan(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn atan(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -201,7 +201,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.atanh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atanh
pub(crate) fn atanh(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn atanh(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -218,7 +218,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.atan2
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan2
pub(crate) fn atan2(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn atan2(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(match (
args.get(0).map(|x| x.to_number(context)).transpose()?,
args.get(1).map(|x| x.to_number(context)).transpose()?,
@ -237,7 +237,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.cbrt
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cbrt
pub(crate) fn cbrt(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn cbrt(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -254,7 +254,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.ceil
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil
pub(crate) fn ceil(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn ceil(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -271,7 +271,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.clz32
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
pub(crate) fn clz32(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn clz32(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_u32(context))
@ -289,7 +289,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.cos
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cos
pub(crate) fn cos(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn cos(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -306,7 +306,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.cosh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cosh
pub(crate) fn cosh(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn cosh(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -323,7 +323,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.exp
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/exp
pub(crate) fn exp(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn exp(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -342,7 +342,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.expm1
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/expm1
pub(crate) fn expm1(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn expm1(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -359,7 +359,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.floor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor
pub(crate) fn floor(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn floor(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -376,7 +376,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.fround
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
pub(crate) fn fround(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn fround(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -393,7 +393,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.hypot
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/hypot
pub(crate) fn hypot(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn hypot(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let mut result = 0f64;
for arg in args {
let x = arg.to_number(context)?;
@ -410,7 +410,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.imul
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
pub(crate) fn imul(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn imul(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(match (
args.get(0).map(|x| x.to_u32(context)).transpose()?,
args.get(1).map(|x| x.to_u32(context)).transpose()?,
@ -429,7 +429,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.log
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log
pub(crate) fn log(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn log(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -446,7 +446,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.log1p
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log1p
pub(crate) fn log1p(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn log1p(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -463,7 +463,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.log10
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log10
pub(crate) fn log10(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn log10(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -480,7 +480,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.log2
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log2
pub(crate) fn log2(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn log2(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -497,7 +497,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.max
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max
pub(crate) fn max(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn max(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let mut max = f64::NEG_INFINITY;
for arg in args {
let num = arg.to_number(context)?;
@ -514,7 +514,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.min
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min
pub(crate) fn min(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn min(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let mut min = f64::INFINITY;
for arg in args {
let num = arg.to_number(context)?;
@ -531,7 +531,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.pow
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/pow
pub(crate) fn pow(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn pow(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(match (
args.get(0).map(|x| x.to_number(context)).transpose()?,
args.get(1).map(|x| x.to_number(context)).transpose()?,
@ -550,7 +550,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.random
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
pub(crate) fn random(_: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
pub(crate) fn random(_: &JsValue, _: &[JsValue], _: &mut Context) -> Result<JsValue> {
Ok(rand::random::<f64>().into())
}
@ -562,7 +562,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.round
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
pub(crate) fn round(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn round(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -579,7 +579,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.sign
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
pub(crate) fn sign(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn sign(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -605,7 +605,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.sin
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sin
pub(crate) fn sin(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn sin(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -622,7 +622,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.sinh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sinh
pub(crate) fn sinh(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn sinh(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -639,7 +639,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.sqrt
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt
pub(crate) fn sqrt(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn sqrt(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -656,7 +656,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.tan
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/tan
pub(crate) fn tan(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn tan(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -673,7 +673,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.tanh
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/tanh
pub(crate) fn tanh(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn tanh(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))
@ -690,7 +690,7 @@ impl Math {
///
/// [spec]: https://tc39.es/ecma262/#sec-math.trunc
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
pub(crate) fn trunc(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn trunc(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
Ok(args
.get(0)
.map(|x| x.to_number(context))

4
boa/src/builtins/mod.rs

@ -54,7 +54,7 @@ pub(crate) use self::{
};
use crate::{
property::{Attribute, PropertyDescriptor},
Context, Value,
Context, JsValue,
};
pub(crate) trait BuiltIn {
@ -62,7 +62,7 @@ pub(crate) trait BuiltIn {
const NAME: &'static str;
fn attribute() -> Attribute;
fn init(context: &mut Context) -> (&'static str, Value, Attribute);
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute);
}
/// Initializes builtin objects and functions

4
boa/src/builtins/nan/mod.rs

@ -13,7 +13,7 @@
#[cfg(test)]
mod tests;
use crate::{builtins::BuiltIn, property::Attribute, BoaProfiler, Context, Value};
use crate::{builtins::BuiltIn, property::Attribute, BoaProfiler, Context, JsValue};
/// JavaScript global `NaN` property.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -26,7 +26,7 @@ impl BuiltIn for NaN {
Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT
}
fn init(_: &mut Context) -> (&'static str, Value, Attribute) {
fn init(_: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, f64::NAN.into(), Self::attribute())

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

@ -19,7 +19,7 @@ use crate::{
builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
property::Attribute,
value::{AbstractRelation, IntegerOrInfinity, Value},
value::{AbstractRelation, IntegerOrInfinity, JsValue},
BoaProfiler, Context, Result,
};
use num_traits::{float::FloatCore, Num};
@ -50,7 +50,7 @@ impl BuiltIn for Number {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;
@ -155,16 +155,16 @@ impl Number {
/// `Number( value )`
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let data = match args.get(0) {
Some(value) => value.to_numeric_number(context)?,
None => 0.0,
};
if new_target.is_undefined() {
return Ok(Value::from(data));
return Ok(JsValue::new(data));
}
let prototype = new_target
.as_object()
@ -175,7 +175,7 @@ impl Number {
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let this = Value::new_object(context);
let this = JsValue::new_object(context);
this.as_object()
.expect("this should be an object")
.set_prototype_instance(prototype.into());
@ -193,11 +193,11 @@ impl Number {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-thisnumbervalue
fn this_number_value(value: &Value, context: &mut Context) -> Result<f64> {
fn this_number_value(value: &JsValue, context: &mut Context) -> Result<f64> {
match *value {
Value::Integer(integer) => return Ok(f64::from(integer)),
Value::Rational(rational) => return Ok(rational),
Value::Object(ref object) => {
JsValue::Integer(integer) => return Ok(f64::from(integer)),
JsValue::Rational(rational) => return Ok(rational),
JsValue::Object(ref object) => {
if let Some(number) = object.borrow().as_number() {
return Ok(number);
}
@ -229,13 +229,13 @@ impl Number {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toExponential
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_exponential(
this: &Value,
_: &[Value],
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let this_num = Self::this_number_value(this, context)?;
let this_str_num = Self::num_to_exponential(this_num);
Ok(Value::from(this_str_num))
Ok(JsValue::new(this_str_num))
}
/// `Number.prototype.toFixed( [digits] )`
@ -249,7 +249,11 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tofixed
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_fixed(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_fixed(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let this_num = Self::this_number_value(this, context)?;
let precision = match args.get(0) {
Some(n) => match n.to_integer(context)? as i32 {
@ -259,7 +263,7 @@ impl Number {
None => 0,
};
let this_fixed_num = format!("{:.*}", precision, this_num);
Ok(Value::from(this_fixed_num))
Ok(JsValue::new(this_fixed_num))
}
/// `Number.prototype.toLocaleString( [locales [, options]] )`
@ -277,13 +281,13 @@ impl Number {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_locale_string(
this: &Value,
_: &[Value],
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let this_num = Self::this_number_value(this, context)?;
let this_str_num = format!("{}", this_num);
Ok(Value::from(this_str_num))
Ok(JsValue::new(this_str_num))
}
/// flt_str_to_exp - used in to_precision
@ -384,16 +388,16 @@ impl Number {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_precision(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let precision = args.get(0).cloned().unwrap_or_default();
// 1 & 6
let mut this_num = Self::this_number_value(this, context)?;
// 2
if precision == Value::undefined() {
if precision == JsValue::undefined() {
return Self::to_string(this, &[], context);
}
@ -467,14 +471,14 @@ impl Number {
// iv, v
suffix.push_str(&exponent.to_string());
return Ok(Value::from(prefix + &suffix));
return Ok(JsValue::new(prefix + &suffix));
}
}
// 11
let e_inc = exponent + 1;
if e_inc == precision_i32 {
return Ok(Value::from(prefix + &suffix));
return Ok(JsValue::new(prefix + &suffix));
}
// 12
@ -488,7 +492,7 @@ impl Number {
}
// 14
Ok(Value::from(prefix + &suffix))
Ok(JsValue::new(prefix + &suffix))
}
// https://golang.org/src/math/nextafter.go
@ -630,7 +634,11 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_string(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let x be ? thisNumberValue(this value).
let x = Self::this_number_value(this, context)?;
@ -650,17 +658,17 @@ impl Number {
// 5. If radixNumber = 10, return ! ToString(x).
if radix == 10 {
return Ok(Value::from(Self::to_native_string(x)));
return Ok(JsValue::new(Self::to_native_string(x)));
}
if x == -0. {
return Ok(Value::from("0"));
return Ok(JsValue::new("0"));
} else if x.is_nan() {
return Ok(Value::from("NaN"));
return Ok(JsValue::new("NaN"));
} else if x.is_infinite() && x.is_sign_positive() {
return Ok(Value::from("Infinity"));
return Ok(JsValue::new("Infinity"));
} else if x.is_infinite() && x.is_sign_negative() {
return Ok(Value::from("-Infinity"));
return Ok(JsValue::new("-Infinity"));
}
// This is a Optimization from the v8 source code to print values that can fit in a single character
@ -672,7 +680,7 @@ impl Number {
// }
// 6. Return the String representation of this Number value using the radix specified by radixNumber.
Ok(Value::from(Self::to_native_string_radix(x, radix)))
Ok(JsValue::new(Self::to_native_string_radix(x, radix)))
}
/// `Number.prototype.toString()`
@ -685,8 +693,12 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/valueOf
pub(crate) fn value_of(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
Ok(Value::from(Self::this_number_value(this, context)?))
pub(crate) fn value_of(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
Ok(JsValue::new(Self::this_number_value(this, context)?))
}
/// Builtin javascript 'parseInt(str, radix)' function.
@ -703,7 +715,11 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-parseint-string-radix
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
pub(crate) fn parse_int(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn parse_int(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
if let (Some(val), radix) = (args.get(0), args.get(1)) {
// 1. Let inputString be ? ToString(string).
let input_string = val.to_string(context)?;
@ -738,7 +754,7 @@ impl Number {
if var_r != 0 {
// a. If R < 2 or R > 36, return NaN.
if !(2..=36).contains(&var_r) {
return Ok(Value::nan());
return Ok(JsValue::nan());
}
// b. If R ≠ 16, set stripPrefix to false.
@ -777,7 +793,7 @@ impl Number {
// 13. If Z is empty, return NaN.
if var_z.is_empty() {
return Ok(Value::nan());
return Ok(JsValue::nan());
}
// 14. Let mathInt be the integer value that is represented by Z in radix-R notation, using the
@ -796,17 +812,17 @@ impl Number {
// b. Return +0𝔽.
if math_int == 0_f64 {
if sign == -1 {
return Ok(Value::rational(-0_f64));
return Ok(JsValue::new(-0_f64));
} else {
return Ok(Value::rational(0_f64));
return Ok(JsValue::new(0_f64));
}
}
// 16. Return 𝔽(sign × mathInt).
Ok(Value::rational(f64::from(sign) * math_int))
Ok(JsValue::new(f64::from(sign) * math_int))
} else {
// Not enough arguments to parseInt.
Ok(Value::nan())
Ok(JsValue::nan())
}
}
@ -825,7 +841,11 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-parsefloat-string
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat
pub(crate) fn parse_float(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn parse_float(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
if let Some(val) = args.get(0) {
let input_string = val.to_string(context)?;
let s = input_string.trim_start_matches(is_trimmable_whitespace);
@ -833,29 +853,29 @@ impl Number {
// TODO: write our own lexer to match syntax StrDecimalLiteral
if s.starts_with("Infinity") || s.starts_with("+Infinity") {
Ok(Value::from(f64::INFINITY))
Ok(JsValue::new(f64::INFINITY))
} else if s.starts_with("-Infinity") {
Ok(Value::from(f64::NEG_INFINITY))
Ok(JsValue::new(f64::NEG_INFINITY))
} else if s_prefix_lower.starts_with("inf")
|| s_prefix_lower.starts_with("+inf")
|| s_prefix_lower.starts_with("-inf")
{
// Prevent fast_float from parsing "inf", "+inf" as Infinity and "-inf" as -Infinity
Ok(Value::nan())
Ok(JsValue::nan())
} else {
Ok(fast_float::parse_partial::<f64, _>(s)
.map(|(f, len)| {
if len > 0 {
Value::rational(f)
JsValue::new(f)
} else {
Value::nan()
JsValue::nan()
}
})
.unwrap_or_else(|_| Value::nan()))
.unwrap_or_else(|_| JsValue::nan()))
}
} else {
// Not enough arguments to parseFloat.
Ok(Value::nan())
Ok(JsValue::nan())
}
}
@ -874,10 +894,10 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-isfinite-number
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite
pub(crate) fn global_is_finite(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
if let Some(value) = args.get(0) {
let number = value.to_number(context)?;
Ok(number.is_finite().into())
@ -900,7 +920,11 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-isnan-number
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN
pub(crate) fn global_is_nan(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn global_is_nan(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
if let Some(value) = args.get(0) {
let number = value.to_number(context)?;
Ok(number.is_nan().into())
@ -923,11 +947,15 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-number.isfinite
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite
pub(crate) fn number_is_finite(_: &Value, args: &[Value], _ctx: &mut Context) -> Result<Value> {
Ok(Value::from(if let Some(val) = args.get(0) {
pub(crate) fn number_is_finite(
_: &JsValue,
args: &[JsValue],
_ctx: &mut Context,
) -> Result<JsValue> {
Ok(JsValue::new(if let Some(val) = args.get(0) {
match val {
Value::Integer(_) => true,
Value::Rational(number) => number.is_finite(),
JsValue::Integer(_) => true,
JsValue::Rational(number) => number.is_finite(),
_ => false,
}
} else {
@ -946,10 +974,10 @@ impl Number {
/// [spec]: https://tc39.es/ecma262/#sec-number.isinteger
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
pub(crate) fn number_is_integer(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
_ctx: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
Ok(args.get(0).map_or(false, Self::is_integer).into())
}
@ -967,11 +995,15 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-isnan-number
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
pub(crate) fn number_is_nan(_: &Value, args: &[Value], _ctx: &mut Context) -> Result<Value> {
Ok(Value::from(if let Some(val) = args.get(0) {
pub(crate) fn number_is_nan(
_: &JsValue,
args: &[JsValue],
_ctx: &mut Context,
) -> Result<JsValue> {
Ok(JsValue::new(if let Some(val) = args.get(0) {
match val {
Value::Integer(_) => false,
Value::Rational(number) => number.is_nan(),
JsValue::Integer(_) => false,
JsValue::Rational(number) => number.is_nan(),
_ => false,
}
} else {
@ -993,10 +1025,14 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-isnan-number
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
pub(crate) fn is_safe_integer(_: &Value, args: &[Value], _ctx: &mut Context) -> Result<Value> {
Ok(Value::from(match args.get(0) {
Some(Value::Integer(_)) => true,
Some(Value::Rational(number)) if Self::is_float_integer(*number) => {
pub(crate) fn is_safe_integer(
_: &JsValue,
args: &[JsValue],
_ctx: &mut Context,
) -> Result<JsValue> {
Ok(JsValue::new(match args.get(0) {
Some(JsValue::Integer(_)) => true,
Some(JsValue::Rational(number)) if Self::is_float_integer(*number) => {
number.abs() <= Number::MAX_SAFE_INTEGER
}
_ => false,
@ -1010,10 +1046,10 @@ impl Number {
///
/// [spec]: https://tc39.es/ecma262/#sec-isinteger
#[inline]
pub(crate) fn is_integer(val: &Value) -> bool {
pub(crate) fn is_integer(val: &JsValue) -> bool {
match val {
Value::Integer(_) => true,
Value::Rational(number) => Number::is_float_integer(*number),
JsValue::Integer(_) => true,
JsValue::Rational(number) => Number::is_float_integer(*number),
_ => false,
}
}

26
boa/src/builtins/object/for_in_iterator.rs

@ -5,7 +5,7 @@ use crate::{
property::PropertyDescriptor,
property::PropertyKey,
symbol::WellKnownSymbols,
BoaProfiler, Context, JsString, Result, Value,
BoaProfiler, Context, JsString, JsValue, Result,
};
use rustc_hash::FxHashSet;
use std::collections::VecDeque;
@ -19,7 +19,7 @@ use std::collections::VecDeque;
/// [spec]: https://tc39.es/ecma262/#sec-for-in-iterator-objects
#[derive(Debug, Clone, Finalize, Trace)]
pub struct ForInIterator {
object: Value,
object: JsValue,
visited_keys: FxHashSet<JsString>,
remaining_keys: VecDeque<JsString>,
object_was_visited: bool,
@ -28,7 +28,7 @@ pub struct ForInIterator {
impl ForInIterator {
pub(crate) const NAME: &'static str = "ForInIterator";
fn new(object: Value) -> Self {
fn new(object: JsValue) -> Self {
ForInIterator {
object,
visited_keys: FxHashSet::default(),
@ -45,8 +45,8 @@ impl ForInIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-createforiniterator
pub(crate) fn create_for_in_iterator(context: &Context, object: Value) -> Value {
let for_in_iterator = Value::new_object(context);
pub(crate) fn create_for_in_iterator(context: &Context, object: JsValue) -> JsValue {
let for_in_iterator = JsValue::new_object(context);
for_in_iterator.set_data(ObjectData::ForInIterator(Self::new(object)));
for_in_iterator
.as_object()
@ -63,8 +63,8 @@ impl ForInIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%foriniteratorprototype%.next
pub(crate) fn next(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
if let Value::Object(ref o) = this {
pub(crate) fn next(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
if let JsValue::Object(ref o) = this {
let mut for_in_iterator = o.borrow_mut();
if let Some(iterator) = for_in_iterator.as_for_in_iterator_mut() {
let mut object = iterator.object.to_object(context)?;
@ -93,7 +93,7 @@ impl ForInIterator {
if desc.expect_enumerable() {
return Ok(create_iter_result_object(
context,
Value::from(r.to_string()),
JsValue::new(r.to_string()),
false,
));
}
@ -105,10 +105,14 @@ impl ForInIterator {
object = o;
}
_ => {
return Ok(create_iter_result_object(context, Value::undefined(), true))
return Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
))
}
}
iterator.object = Value::from(object.clone());
iterator.object = JsValue::new(object.clone());
iterator.object_was_visited = false;
}
} else {
@ -125,7 +129,7 @@ impl ForInIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%foriniteratorprototype%-object
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: Value) -> GcObject {
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: JsValue) -> GcObject {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// Create prototype

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

@ -20,7 +20,7 @@ use crate::{
},
property::{Attribute, DescriptorKind, PropertyDescriptor},
symbol::WellKnownSymbols,
value::{Type, Value},
value::{JsValue, Type},
BoaProfiler, Context, Result,
};
@ -39,7 +39,7 @@ impl BuiltIn for Object {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let object = ConstructorBuilder::with_standard_object(
@ -49,7 +49,7 @@ impl BuiltIn for Object {
)
.name(Self::NAME)
.length(Self::LENGTH)
.inherit(Value::null())
.inherit(JsValue::null())
.method(Self::has_own_property, "hasOwnProperty", 0)
.method(Self::property_is_enumerable, "propertyIsEnumerable", 0)
.method(Self::to_string, "toString", 0)
@ -80,7 +80,11 @@ impl BuiltIn for Object {
impl Object {
const LENGTH: usize = 1;
fn constructor(new_target: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
fn constructor(
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
if !new_target.is_undefined() {
let prototype = new_target
.as_object()
@ -91,7 +95,7 @@ impl Object {
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let object = Value::new_object(context);
let object = JsValue::new_object(context);
object
.as_object()
@ -104,7 +108,7 @@ impl Object {
return Ok(arg.to_object(context)?.into());
}
}
Ok(Value::new_object(context))
Ok(JsValue::new_object(context))
}
/// `Object.create( proto, [propertiesObject] )`
@ -117,12 +121,12 @@ impl Object {
///
/// [spec]: https://tc39.es/ecma262/#sec-object.create
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
pub fn create(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let prototype = args.get(0).cloned().unwrap_or_else(Value::undefined);
let properties = args.get(1).cloned().unwrap_or_else(Value::undefined);
pub fn create(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let prototype = args.get(0).cloned().unwrap_or_else(JsValue::undefined);
let properties = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
let obj = match prototype {
Value::Object(_) | Value::Null => Value::object(BuiltinObject::with_prototype(
JsValue::Object(_) | JsValue::Null => JsValue::new(BuiltinObject::with_prototype(
prototype,
ObjectData::Ordinary,
)),
@ -135,7 +139,7 @@ impl Object {
};
if !properties.is_undefined() {
return Object::define_properties(&Value::Undefined, &[obj, properties], context);
return Object::define_properties(&JsValue::undefined(), &[obj, properties], context);
}
Ok(obj)
@ -152,13 +156,13 @@ impl Object {
/// [spec]: https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
pub fn get_own_property_descriptor(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let object = args
.get(0)
.unwrap_or(&Value::undefined())
.unwrap_or(&JsValue::undefined())
.to_object(context)?;
if let Some(key) = args.get(1) {
let key = key.to_property_key(context)?;
@ -168,7 +172,7 @@ impl Object {
}
}
Ok(Value::undefined())
Ok(JsValue::undefined())
}
/// `Object.getOwnPropertyDescriptors( object )`
@ -182,13 +186,13 @@ impl Object {
/// [spec]: https://tc39.es/ecma262/#sec-object.getownpropertydescriptors
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors
pub fn get_own_property_descriptors(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let object = args
.get(0)
.unwrap_or(&Value::undefined())
.unwrap_or(&JsValue::undefined())
.to_object(context)?;
let descriptors = context.construct_object();
@ -212,7 +216,7 @@ impl Object {
}
}
Ok(Value::Object(descriptors))
Ok(JsValue::Object(descriptors))
}
/// The abstract operation `FromPropertyDescriptor`.
@ -220,7 +224,7 @@ impl Object {
/// [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-frompropertydescriptor
fn from_property_descriptor(desc: PropertyDescriptor, context: &mut Context) -> Value {
fn from_property_descriptor(desc: PropertyDescriptor, context: &mut Context) -> JsValue {
let mut descriptor = ObjectInitializer::new(context);
// TODO: use CreateDataPropertyOrThrow
@ -257,15 +261,15 @@ impl Object {
}
/// Uses the SameValue algorithm to check equality of objects
pub fn is(_: &Value, args: &[Value], _: &mut Context) -> Result<Value> {
let x = args.get(0).cloned().unwrap_or_else(Value::undefined);
let y = args.get(1).cloned().unwrap_or_else(Value::undefined);
pub fn is(_: &JsValue, args: &[JsValue], _: &mut Context) -> Result<JsValue> {
let x = args.get(0).cloned().unwrap_or_else(JsValue::undefined);
let y = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
Ok(Value::same_value(&x, &y).into())
Ok(JsValue::same_value(&x, &y).into())
}
/// Get the `prototype` of an object.
pub fn get_prototype_of(_: &Value, args: &[Value], ctx: &mut Context) -> Result<Value> {
pub fn get_prototype_of(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> Result<JsValue> {
if args.is_empty() {
return ctx.throw_type_error(
"Object.getPrototypeOf: At least 1 argument required, but only 0 passed",
@ -284,7 +288,7 @@ impl Object {
/// [More information][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-object.setprototypeof
pub fn set_prototype_of(_: &Value, args: &[Value], ctx: &mut Context) -> Result<Value> {
pub fn set_prototype_of(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> Result<JsValue> {
if args.len() < 2 {
return ctx.throw_type_error(format!(
"Object.setPrototypeOf: At least 2 arguments required, but only {} passed",
@ -339,35 +343,43 @@ impl Object {
///
/// [spec]: https://tc39.es/ecma262/#sec-object.prototype.isprototypeof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isPrototypeOf
pub fn is_prototype_of(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::undefined();
pub fn is_prototype_of(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let undefined = JsValue::undefined();
let mut v = args.get(0).unwrap_or(&undefined).clone();
if !v.is_object() {
return Ok(Value::Boolean(false));
return Ok(JsValue::new(false));
}
let o = Value::from(this.to_object(context)?);
let o = JsValue::new(this.to_object(context)?);
loop {
v = Self::get_prototype_of(this, &[v], context)?;
if v.is_null() {
return Ok(Value::Boolean(false));
return Ok(JsValue::new(false));
}
if Value::same_value(&o, &v) {
return Ok(Value::Boolean(true));
if JsValue::same_value(&o, &v) {
return Ok(JsValue::new(true));
}
}
}
/// Define a property in an object
pub fn define_property(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let object = args.get(0).cloned().unwrap_or_else(Value::undefined);
pub fn define_property(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let object = args.get(0).cloned().unwrap_or_else(JsValue::undefined);
if let Some(object) = object.as_object() {
let key = args
.get(1)
.unwrap_or(&Value::Undefined)
.unwrap_or(&JsValue::Undefined)
.to_property_key(context)?;
let desc = args
.get(2)
.unwrap_or(&Value::Undefined)
.unwrap_or(&JsValue::Undefined)
.to_property_descriptor(context)?;
object.define_property_or_throw(key, desc, context)?;
@ -388,11 +400,15 @@ impl Object {
///
/// [spec]: https://tc39.es/ecma262/#sec-object.defineproperties
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties
pub fn define_properties(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub fn define_properties(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let arg = args.get(0).cloned().unwrap_or_default();
let arg_obj = arg.as_object();
if let Some(mut obj) = arg_obj {
let props = args.get(1).cloned().unwrap_or_else(Value::undefined);
let props = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
obj.define_properties(props, context)?;
Ok(arg)
} else {
@ -410,7 +426,7 @@ impl Object {
/// [spec]: https://tc39.es/ecma262/#sec-object.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
#[allow(clippy::wrong_self_convention)]
pub fn to_string(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub fn to_string(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. If the this value is undefined, return "[object Undefined]".
if this.is_undefined() {
return Ok("[object Undefined]".into());
@ -470,10 +486,14 @@ impl Object {
///
/// [spec]: https://tc39.es/ecma262/#sec-object.prototype.hasownproperty
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
pub fn has_own_property(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub fn has_own_property(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let key = args
.get(0)
.unwrap_or(&Value::undefined())
.unwrap_or(&JsValue::undefined())
.to_property_key(context)?;
let object = this.to_object(context)?;
@ -492,20 +512,20 @@ impl Object {
/// [spec]: https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable
pub fn property_is_enumerable(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let key = match args.get(0) {
None => return Ok(Value::from(false)),
None => return Ok(JsValue::new(false)),
Some(key) => key,
};
let key = key.to_property_key(context)?;
let own_property = this.to_object(context)?.__get_own_property__(&key);
Ok(own_property.map_or(Value::from(false), |own_prop| {
Value::from(own_prop.enumerable())
Ok(own_property.map_or(JsValue::new(false), |own_prop| {
JsValue::new(own_prop.enumerable())
}))
}
@ -520,7 +540,7 @@ impl Object {
///
/// [spec]: https://tc39.es/ecma262/#sec-object.assign
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
pub fn assign(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub fn assign(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
//
//
// 1. Let to be ? ToObject(target).

6
boa/src/builtins/object/tests.rs

@ -1,4 +1,4 @@
use crate::{forward, Context, Value};
use crate::{forward, Context, JsValue};
#[test]
fn object_create_with_regular_object() {
@ -218,7 +218,7 @@ fn get_own_property_descriptor_1_arg_returns_undefined() {
let obj = {a: 2};
Object.getOwnPropertyDescriptor(obj)
"#;
assert_eq!(context.eval(code).unwrap(), Value::undefined());
assert_eq!(context.eval(code).unwrap(), JsValue::undefined());
}
#[test]
@ -287,5 +287,5 @@ fn object_is_prototype_of() {
Object.prototype.isPrototypeOf(String.prototype)
"#;
assert_eq!(context.eval(init).unwrap(), Value::boolean(true));
assert_eq!(context.eval(init).unwrap(), JsValue::new(true));
}

86
boa/src/builtins/reflect/mod.rs

@ -15,7 +15,7 @@ use crate::{
object::{Object, ObjectData, ObjectInitializer},
property::{Attribute, PropertyDescriptor},
symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
#[cfg(test)]
@ -32,7 +32,7 @@ impl BuiltIn for Reflect {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let to_string_tag = WellKnownSymbols::to_string_tag();
@ -74,8 +74,8 @@ impl Reflect {
///
/// [spec]: https://tc39.es/ecma262/#sec-reflect.apply
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/apply
pub(crate) fn apply(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::undefined();
pub(crate) fn apply(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let undefined = JsValue::undefined();
let target = args
.get(0)
.and_then(|v| v.as_object())
@ -101,7 +101,11 @@ impl Reflect {
///
/// [spec]: https://tc39.es/ecma262/#sec-reflect.construct
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct
pub(crate) fn construct(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn construct(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let target = args
.get(0)
.and_then(|v| v.as_object())
@ -137,17 +141,17 @@ impl Reflect {
/// [spec]: https://tc39.es/ecma262/#sec-reflect.defineProperty
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/defineProperty
pub(crate) fn define_property(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
let undefined = Value::undefined();
) -> Result<JsValue> {
let undefined = JsValue::undefined();
let target = args
.get(0)
.and_then(|v| v.as_object())
.ok_or_else(|| context.construct_type_error("target must be an object"))?;
let key = args.get(1).unwrap_or(&undefined).to_property_key(context)?;
let prop_desc: Value = args
let prop_desc: JsValue = args
.get(2)
.and_then(|v| v.as_object())
.ok_or_else(|| context.construct_type_error("property descriptor must be an object"))?
@ -167,11 +171,11 @@ impl Reflect {
/// [spec]: https://tc39.es/ecma262/#sec-reflect.deleteproperty
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/deleteProperty
pub(crate) fn delete_property(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
let undefined = Value::undefined();
) -> Result<JsValue> {
let undefined = JsValue::undefined();
let target = args
.get(0)
.and_then(|v| v.as_object())
@ -189,8 +193,8 @@ impl Reflect {
///
/// [spec]: https://tc39.es/ecma262/#sec-reflect.get
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/get
pub(crate) fn get(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::undefined();
pub(crate) fn get(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let undefined = JsValue::undefined();
// 1. If Type(target) is not Object, throw a TypeError exception.
let target = args
.get(0)
@ -218,17 +222,17 @@ impl Reflect {
/// [spec]: https://tc39.es/ecma262/#sec-reflect.getownpropertydescriptor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getOwnPropertyDescriptor
pub(crate) fn get_own_property_descriptor(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
match args.get(0) {
Some(v) if v.is_object() => (),
_ => return context.throw_type_error("target must be an object"),
}
// This function is the same as Object.prototype.getOwnPropertyDescriptor, that why
// it is invoked here.
builtins::object::Object::get_own_property_descriptor(&Value::undefined(), args, context)
builtins::object::Object::get_own_property_descriptor(&JsValue::undefined(), args, context)
}
/// Gets the prototype of an object.
@ -240,10 +244,10 @@ impl Reflect {
/// [spec]: https://tc39.es/ecma262/#sec-reflect.getprototypeof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getPrototypeOf
pub(crate) fn get_prototype_of(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let target = args
.get(0)
.and_then(|v| v.as_object())
@ -259,14 +263,14 @@ impl Reflect {
///
/// [spec]: https://tc39.es/ecma262/#sec-reflect.has
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/has
pub(crate) fn has(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn has(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let target = args
.get(0)
.and_then(|v| v.as_object())
.ok_or_else(|| context.construct_type_error("target must be an object"))?;
let key = args
.get(1)
.unwrap_or(&Value::undefined())
.unwrap_or(&JsValue::undefined())
.to_property_key(context)?;
Ok(target.__has_property__(&key).into())
}
@ -279,7 +283,11 @@ impl Reflect {
///
/// [spec]: https://tc39.es/ecma262/#sec-reflect.isextensible
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/isExtensible
pub(crate) fn is_extensible(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn is_extensible(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let target = args
.get(0)
.and_then(|v| v.as_object())
@ -295,13 +303,17 @@ impl Reflect {
///
/// [spec]: https://tc39.es/ecma262/#sec-reflect.ownkeys
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/ownKeys
pub(crate) fn own_keys(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn own_keys(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let target = args
.get(0)
.and_then(|v| v.as_object())
.ok_or_else(|| context.construct_type_error("target must be an object"))?;
let array_prototype = context.standard_objects().array_object().prototype();
let result: Value =
let result: JsValue =
Object::with_prototype(array_prototype.into(), ObjectData::Array).into();
result.set_property(
"length",
@ -329,10 +341,10 @@ impl Reflect {
/// [spec]: https://tc39.es/ecma262/#sec-reflect.preventextensions
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/preventExtensions
pub(crate) fn prevent_extensions(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let mut target = args
.get(0)
.and_then(|v| v.as_object())
@ -349,8 +361,8 @@ impl Reflect {
///
/// [spec]: https://tc39.es/ecma262/#sec-reflect.set
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/set
pub(crate) fn set(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::undefined();
pub(crate) fn set(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let undefined = JsValue::undefined();
let target = args
.get(0)
.and_then(|v| v.as_object())
@ -376,11 +388,11 @@ impl Reflect {
/// [spec]: https://tc39.es/ecma262/#sec-reflect.setprototypeof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/setPrototypeOf
pub(crate) fn set_prototype_of(
_: &Value,
args: &[Value],
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
let undefined = Value::undefined();
) -> Result<JsValue> {
let undefined = JsValue::undefined();
let mut target = args
.get(0)
.and_then(|v| v.as_object())

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

@ -17,7 +17,7 @@ use crate::{
object::{ConstructorBuilder, FunctionBuilder, GcObject, Object, ObjectData, PROTOTYPE},
property::Attribute,
symbol::WellKnownSymbols,
value::{IntegerOrInfinity, Value},
value::{IntegerOrInfinity, JsValue},
BoaProfiler, Context, JsString, Result,
};
use regexp_string_iterator::RegExpStringIterator;
@ -69,7 +69,7 @@ impl BuiltIn for RegExp {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let get_species = FunctionBuilder::native(context, Self::get_species)
@ -183,15 +183,15 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp-pattern-flags
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
let pattern = args.get(0).cloned().unwrap_or_else(Value::undefined);
let flags = args.get(1).cloned().unwrap_or_else(Value::undefined);
) -> Result<JsValue> {
let pattern = args.get(0).cloned().unwrap_or_else(JsValue::undefined);
let flags = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
// 1. Let patternIsRegExp be ? IsRegExp(pattern).
let pattern_is_regexp = if let Value::Object(obj) = &pattern {
let pattern_is_regexp = if let JsValue::Object(obj) = &pattern {
if obj.is_regexp() {
Some(obj)
} else {
@ -211,7 +211,7 @@ impl RegExp {
// i. Let patternConstructor be ? Get(pattern, "constructor").
let pattern_constructor = pattern.get("constructor", context)?;
// ii. If SameValue(newTarget, patternConstructor) is true, return pattern.
if Value::same_value(new_target, &pattern_constructor) {
if JsValue::same_value(new_target, &pattern_constructor) {
return Ok(pattern.clone().into());
}
}
@ -229,11 +229,11 @@ impl RegExp {
// c. Else, let F be flags.
if flags.is_undefined() {
(
Value::from(regexp.original_source.clone()),
Value::from(regexp.original_flags.clone()),
JsValue::new(regexp.original_source.clone()),
JsValue::new(regexp.original_flags.clone()),
)
} else {
(Value::from(regexp.original_source.clone()), flags)
(JsValue::new(regexp.original_source.clone()), flags)
}
} else {
// a. Let P be pattern.
@ -254,7 +254,7 @@ impl RegExp {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-regexpalloc
fn alloc(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
fn alloc(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
let proto = if let Some(obj) = this.as_object() {
obj.get(PROTOTYPE, context)?
} else {
@ -274,9 +274,9 @@ impl RegExp {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-regexpinitialize
fn initialize(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let pattern = args.get(0).cloned().unwrap_or_else(Value::undefined);
let flags = args.get(1).cloned().unwrap_or_else(Value::undefined);
fn initialize(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let pattern = args.get(0).cloned().unwrap_or_else(JsValue::undefined);
let flags = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
// 1. If pattern is undefined, let P be the empty String.
// 2. Else, let P be ? ToString(pattern).
@ -373,7 +373,7 @@ impl RegExp {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-regexpcreate
pub(crate) fn create(p: Value, f: Value, context: &mut Context) -> Result<Value> {
pub(crate) fn create(p: JsValue, f: JsValue, context: &mut Context) -> Result<JsValue> {
// 1. Let obj be ? RegExpAlloc(%RegExp%).
let obj = RegExp::alloc(
&context.global_object().get(RegExp::NAME, context)?,
@ -395,16 +395,16 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp-@@species
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@species
fn get_species(this: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> Result<JsValue> {
// 1. Return the this value.
Ok(this.clone())
}
#[inline]
fn regexp_has_flag(this: &Value, flag: char, context: &mut Context) -> Result<Value> {
fn regexp_has_flag(this: &JsValue, flag: char, context: &mut Context) -> Result<JsValue> {
if let Some(object) = this.as_object() {
if let Some(regexp) = object.borrow().as_regexp() {
return Ok(Value::boolean(match flag {
return Ok(JsValue::new(match flag {
'g' => regexp.global,
'm' => regexp.multiline,
's' => regexp.dot_all,
@ -419,7 +419,7 @@ impl RegExp {
&object,
&context.standard_objects().regexp_object().prototype,
) {
return Ok(Value::undefined());
return Ok(JsValue::undefined());
}
}
@ -449,7 +449,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.global
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/global
pub(crate) fn get_global(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn get_global(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
Self::regexp_has_flag(this, 'g', context)
}
@ -464,10 +468,10 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.ignorecase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/ignoreCase
pub(crate) fn get_ignore_case(
this: &Value,
_: &[Value],
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
Self::regexp_has_flag(this, 'i', context)
}
@ -481,7 +485,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.multiline
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/multiline
pub(crate) fn get_multiline(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn get_multiline(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
Self::regexp_has_flag(this, 'm', context)
}
@ -495,7 +503,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.dotAll
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/dotAll
pub(crate) fn get_dot_all(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn get_dot_all(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
Self::regexp_has_flag(this, 's', context)
}
@ -510,7 +522,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.unicode
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode
pub(crate) fn get_unicode(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn get_unicode(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
Self::regexp_has_flag(this, 'u', context)
}
@ -525,7 +541,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.sticky
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky
pub(crate) fn get_sticky(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn get_sticky(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
Self::regexp_has_flag(this, 'y', context)
}
@ -540,7 +560,11 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags
/// [flags]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Advanced_searching_with_flags_2
pub(crate) fn get_flags(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn get_flags(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let R be the this value.
// 2. If Type(R) is not Object, throw a TypeError exception.
if let Some(object) = this.as_object() {
@ -598,7 +622,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-regexp.prototype.source
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source
pub(crate) fn get_source(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn get_source(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let R be the this value.
// 2. If Type(R) is not Object, throw a TypeError exception.
if let Some(object) = this.as_object() {
@ -609,11 +637,11 @@ impl RegExp {
None => {
// a. If SameValue(R, %RegExp.prototype%) is true, return "(?:)".
// b. Otherwise, throw a TypeError exception.
if Value::same_value(
if JsValue::same_value(
this,
&Value::from(context.standard_objects().regexp_object().prototype()),
&JsValue::new(context.standard_objects().regexp_object().prototype()),
) {
Ok(Value::from("(?:)"))
Ok(JsValue::new("(?:)"))
} else {
context.throw_type_error(
"RegExp.prototype.source method called on incompatible value",
@ -639,9 +667,9 @@ impl RegExp {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-escaperegexppattern
fn escape_pattern(src: &str, _flags: &str) -> Result<Value> {
fn escape_pattern(src: &str, _flags: &str) -> Result<JsValue> {
if src.is_empty() {
Ok(Value::from("(?:)"))
Ok(JsValue::new("(?:)"))
} else {
let mut s = String::from("");
@ -654,7 +682,7 @@ impl RegExp {
}
}
Ok(Value::from(s))
Ok(JsValue::new(s))
}
}
@ -670,7 +698,7 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.test
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
pub(crate) fn test(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn test(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let R be the this value.
// 2. If Type(R) is not Object, throw a TypeError exception.
if !this.is_object() {
@ -690,9 +718,9 @@ impl RegExp {
// 5. If match is not null, return true; else return false.
if m.is_some() {
Ok(Value::Boolean(true))
Ok(JsValue::new(true))
} else {
Ok(Value::Boolean(false))
Ok(JsValue::new(false))
}
}
@ -708,7 +736,7 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.exec
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
pub(crate) fn exec(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn exec(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let R be the this value.
// 2. Perform ? RequireInternalSlot(R, [[RegExpMatcher]]).
let obj = this.as_object().unwrap_or_default();
@ -729,7 +757,7 @@ impl RegExp {
if let Some(v) = Self::abstract_builtin_exec(obj, arg_str, context)? {
Ok(v.into())
} else {
Ok(Value::null())
Ok(JsValue::null())
}
}
@ -740,7 +768,7 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexpexec
pub(crate) fn abstract_exec(
this: &Value,
this: &JsValue,
input: JsString,
context: &mut Context,
) -> Result<Option<GcObject>> {
@ -949,7 +977,7 @@ impl RegExp {
let named_groups = match_value.named_groups();
let groups = if named_groups.clone().count() > 0 {
// a. Let groups be ! OrdinaryObjectCreate(null).
let groups = Value::new_object(context);
let groups = JsValue::new_object(context);
// Perform 27.f here
// f. If the ith capture of R was defined with a GroupName, then
@ -972,7 +1000,7 @@ impl RegExp {
groups
} else {
// a. Let groups be undefined.
Value::undefined()
JsValue::undefined()
};
// 26. Perform ! CreateDataPropertyOrThrow(A, "groups", groups).
@ -986,7 +1014,7 @@ impl RegExp {
let captured_value = match capture {
// b. If captureI is undefined, let capturedValue be undefined.
None => Value::undefined(),
None => JsValue::undefined(),
// c. Else if fullUnicode is true, then
// d. Else,
Some(range) => {
@ -1017,7 +1045,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype-@@match
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@match
pub(crate) fn r#match(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn r#match(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let rx be the this value.
// 2. If Type(rx) is not Object, throw a TypeError exception.
let rx = if let Some(rx) = this.as_object() {
@ -1042,10 +1074,10 @@ impl RegExp {
// 6. Else,
if !global {
// a. Return ? RegExpExec(rx, S).
if let Some(v) = Self::abstract_exec(&Value::from(rx), arg_str, context)? {
if let Some(v) = Self::abstract_exec(&JsValue::new(rx), arg_str, context)? {
Ok(v.into())
} else {
Ok(Value::null())
Ok(JsValue::null())
}
} else {
// a. Assert: global is true.
@ -1066,7 +1098,7 @@ impl RegExp {
loop {
// i. Let result be ? RegExpExec(rx, S).
let result =
Self::abstract_exec(&Value::from(rx.clone()), arg_str.clone(), context)?;
Self::abstract_exec(&JsValue::new(rx.clone()), arg_str.clone(), context)?;
// ii. If result is null, then
// iii. Else,
@ -1087,7 +1119,7 @@ impl RegExp {
let next_index = advance_string_index(arg_str.clone(), this_index, unicode);
// c. Perform ? Set(rx, "lastIndex", 𝔽(nextIndex), true).
rx.set("lastIndex", Value::from(next_index), true, context)?;
rx.set("lastIndex", JsValue::new(next_index), true, context)?;
}
// 4. Set n to n + 1.
@ -1096,7 +1128,7 @@ impl RegExp {
// 1. If n = 0, return null.
// 2. Return A.
if n == 0 {
return Ok(Value::null());
return Ok(JsValue::null());
} else {
return Ok(a.into());
}
@ -1116,7 +1148,11 @@ impl RegExp {
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_string(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let (body, flags) = if let Some(object) = this.as_object() {
let object = object.borrow();
let regex = object.as_regexp().ok_or_else(|| {
@ -1145,7 +1181,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp-prototype-matchall
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@matchAll
pub(crate) fn match_all(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn match_all(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let R be the this value.
// 2. If Type(R) is not Object, throw a TypeError exception.
if !this.is_object() {
@ -1205,7 +1245,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype-@@replace
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@replace
pub(crate) fn replace(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn replace(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let rx be the this value.
// 2. If Type(rx) is not Object, throw a TypeError exception.
let rx = if let Some(rx) = this.as_object() {
@ -1256,7 +1300,7 @@ impl RegExp {
// 11. Repeat, while done is false,
loop {
// a. Let result be ? RegExpExec(rx, S).
let result = Self::abstract_exec(&Value::from(rx.clone()), arg_str.clone(), context)?;
let result = Self::abstract_exec(&JsValue::new(rx.clone()), arg_str.clone(), context)?;
// b. If result is null, set done to true.
// c. Else,
@ -1281,7 +1325,7 @@ impl RegExp {
let next_index = advance_string_index(arg_str.clone(), this_index, unicode);
// c. Perform ? Set(rx, "lastIndex", 𝔽(nextIndex), true).
rx.set("lastIndex", Value::from(next_index), true, context)?;
rx.set("lastIndex", JsValue::new(next_index), true, context)?;
}
}
} else {
@ -1359,7 +1403,7 @@ impl RegExp {
let replacement: JsString;
if functional_replace {
// i. Let replacerArgs be « matched ».
let mut replacer_args = vec![Value::from(matched)];
let mut replacer_args = vec![JsValue::new(matched)];
// ii. Append in List order the elements of captures to the end of the List replacerArgs.
replacer_args.extend(captures);
@ -1375,7 +1419,8 @@ impl RegExp {
}
// v. Let replValue be ? Call(replaceValue, undefined, replacerArgs).
let repl_value = context.call(&replace_value, &Value::Undefined, &replacer_args)?;
let repl_value =
context.call(&replace_value, &JsValue::undefined(), &replacer_args)?;
// vi. Let replacement be ? ToString(replValue).
replacement = repl_value.to_string(context)?;
@ -1443,7 +1488,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype-@@search
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@search
pub(crate) fn search(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn search(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let rx be the this value.
// 2. If Type(rx) is not Object, throw a TypeError exception.
let rx = if let Some(rx) = this.as_object() {
@ -1465,19 +1514,19 @@ impl RegExp {
let previous_last_index = rx.get("lastIndex", context)?;
// 5. If SameValue(previousLastIndex, +0𝔽) is false, then
if !Value::same_value(&previous_last_index, &Value::from(0)) {
if !JsValue::same_value(&previous_last_index, &JsValue::new(0)) {
// a. Perform ? Set(rx, "lastIndex", +0𝔽, true).
rx.set("lastIndex", 0, true, context)?;
}
// 6. Let result be ? RegExpExec(rx, S).
let result = Self::abstract_exec(&Value::from(rx.clone()), arg_str, context)?;
let result = Self::abstract_exec(&JsValue::new(rx.clone()), arg_str, context)?;
// 7. Let currentLastIndex be ? Get(rx, "lastIndex").
let current_last_index = rx.get("lastIndex", context)?;
// 8. If SameValue(currentLastIndex, previousLastIndex) is false, then
if !Value::same_value(&current_last_index, &previous_last_index) {
if !JsValue::same_value(&current_last_index, &previous_last_index) {
// a. Perform ? Set(rx, "lastIndex", previousLastIndex, true).
rx.set("lastIndex", previous_last_index, true, context)?;
}
@ -1487,7 +1536,7 @@ impl RegExp {
if let Some(result) = result {
result.get("index", context)
} else {
Ok(Value::from(-1))
Ok(JsValue::new(-1))
}
}
@ -1501,7 +1550,11 @@ impl RegExp {
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp.prototype-@@split
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@split
pub(crate) fn split(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn split(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let rx be the this value.
// 2. If Type(rx) is not Object, throw a TypeError exception.
let rx = if let Some(rx) = this.as_object() {
@ -1590,7 +1643,7 @@ impl RegExp {
// 19. Repeat, while q < size,
while q < size {
// a. Perform ? Set(splitter, "lastIndex", 𝔽(q), true).
splitter.set_field("lastIndex", Value::from(q), true, context)?;
splitter.set_field("lastIndex", JsValue::new(q), true, context)?;
// b. Let z be ? RegExpExec(splitter, S).
let result = Self::abstract_exec(&splitter, arg_str.clone(), context)?;

30
boa/src/builtins/regexp/regexp_string_iterator.rs

@ -17,13 +17,13 @@ use crate::{
object::{GcObject, ObjectData},
property::PropertyDescriptor,
symbol::WellKnownSymbols,
BoaProfiler, Context, JsString, Result, Value,
BoaProfiler, Context, JsString, JsValue, Result,
};
// TODO: See todos in create_regexp_string_iterator and next.
#[derive(Debug, Clone, Finalize, Trace)]
pub struct RegExpStringIterator {
matcher: Value,
matcher: JsValue,
string: JsString,
global: bool,
unicode: bool,
@ -32,7 +32,7 @@ pub struct RegExpStringIterator {
// TODO: See todos in create_regexp_string_iterator and next.
impl RegExpStringIterator {
fn new(matcher: Value, string: JsString, global: bool, unicode: bool) -> Self {
fn new(matcher: JsValue, string: JsString, global: bool, unicode: bool) -> Self {
Self {
matcher,
string,
@ -49,12 +49,12 @@ impl RegExpStringIterator {
///
/// [spec]: https://tc39.es/ecma262/#sec-createregexpstringiterator
pub(crate) fn create_regexp_string_iterator(
matcher: &Value,
matcher: &JsValue,
string: JsString,
global: bool,
unicode: bool,
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// TODO: Implement this with closures and generators.
// For now all values of the closure are stored in RegExpStringIterator and the actual closure execution is in `.next()`.
@ -66,7 +66,7 @@ impl RegExpStringIterator {
// and fullUnicode and performs the following steps when called:
// 5. Return ! CreateIteratorFromClosure(closure, "%RegExpStringIteratorPrototype%", %RegExpStringIteratorPrototype%).
let regexp_string_iterator = Value::new_object(context);
let regexp_string_iterator = JsValue::new_object(context);
regexp_string_iterator.set_data(ObjectData::RegExpStringIterator(Self::new(
matcher.clone(),
string,
@ -86,12 +86,16 @@ impl RegExpStringIterator {
Ok(regexp_string_iterator)
}
pub fn next(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
if let Value::Object(ref object) = this {
pub fn next(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
if let JsValue::Object(ref object) = this {
let mut object = object.borrow_mut();
if let Some(iterator) = object.as_regexp_string_iterator_mut() {
if iterator.completed {
return Ok(create_iter_result_object(context, Value::undefined(), true));
return Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
));
}
// TODO: This is the code that should be created as a closure in create_regexp_string_iterator.
@ -137,7 +141,11 @@ impl RegExpStringIterator {
} else {
// ii. If match is null, return undefined.
iterator.completed = true;
Ok(create_iter_result_object(context, Value::undefined(), true))
Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
))
}
} else {
context.throw_type_error("`this` is not a RegExpStringIterator")
@ -153,7 +161,7 @@ impl RegExpStringIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%arrayiteratorprototype%-object
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: Value) -> GcObject {
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: JsValue) -> GcObject {
let _timer = BoaProfiler::global().start_event("RegExp String Iterator", "init");
// Create prototype

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

@ -15,7 +15,7 @@ use crate::{
object::{ConstructorBuilder, FunctionBuilder, ObjectData, PROTOTYPE},
property::Attribute,
symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use ordered_set::OrderedSet;
@ -27,7 +27,7 @@ pub mod ordered_set;
mod tests;
#[derive(Debug, Clone)]
pub(crate) struct Set(OrderedSet<Value>);
pub(crate) struct Set(OrderedSet<JsValue>);
impl BuiltIn for Set {
const NAME: &'static str = "Set";
@ -36,7 +36,7 @@ impl BuiltIn for Set {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let get_species = FunctionBuilder::native(context, Self::get_species)
@ -110,10 +110,10 @@ impl Set {
/// Create a new set
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// 1
if new_target.is_undefined() {
return context
@ -135,7 +135,7 @@ impl Set {
let obj = context.construct_object();
obj.set_prototype_instance(prototype.into());
let set = Value::from(obj);
let set = JsValue::new(obj);
// 3
set.set_data(ObjectData::Set(OrderedSet::default()));
@ -186,7 +186,7 @@ impl Set {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-set-@@species
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/@@species
fn get_species(this: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
fn get_species(this: &JsValue, _: &[JsValue], _: &mut Context) -> Result<JsValue> {
// 1. Return the this value.
Ok(this.clone())
}
@ -201,13 +201,13 @@ impl Set {
///
/// [spec]: https://tc39.es/ecma262/#sec-set.prototype.add
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/add
pub(crate) fn add(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn add(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let mut value = args.get(0).cloned().unwrap_or_default();
if let Some(object) = this.as_object() {
if let Some(set) = object.borrow_mut().as_set_mut() {
if value.as_number().map(|n| n == -0f64).unwrap_or(false) {
value = Value::Integer(0);
value = JsValue::Integer(0);
}
set.add(value);
} else {
@ -230,11 +230,11 @@ impl Set {
///
/// [spec]: https://tc39.es/ecma262/#sec-set.prototype.clear
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear
pub(crate) fn clear(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn clear(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
if let Some(object) = this.as_object() {
if object.borrow().is_set() {
this.set_data(ObjectData::Set(OrderedSet::new()));
Ok(Value::Undefined)
Ok(JsValue::undefined())
} else {
context.throw_type_error("'this' is not a Set")
}
@ -254,7 +254,11 @@ impl Set {
///
/// [spec]: https://tc39.es/ecma262/#sec-set.prototype.delete
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete
pub(crate) fn delete(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn delete(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let value = args.get(0).cloned().unwrap_or_default();
let res = if let Some(object) = this.as_object() {
@ -280,7 +284,7 @@ impl Set {
///
/// [spec]: https://tc39.es/ecma262/#sec-set.prototype.entries
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/entries
pub(crate) fn entries(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn entries(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
if let Some(object) = this.as_object() {
let object = object.borrow();
if !object.is_set() {
@ -310,16 +314,20 @@ impl Set {
///
/// [spec]: https://tc39.es/ecma262/#sec-set.prototype.foreach
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/foreach
pub(crate) fn for_each(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn for_each(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
if args.is_empty() {
return Err(Value::from("Missing argument for Set.prototype.forEach"));
return Err(JsValue::new("Missing argument for Set.prototype.forEach"));
}
let callback_arg = &args[0];
let this_arg = args.get(1).cloned().unwrap_or_else(Value::undefined);
let this_arg = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
// TODO: if condition should also check that we are not in strict mode
let this_arg = if this_arg.is_undefined() {
Value::Object(context.global_object())
JsValue::Object(context.global_object())
} else {
this_arg
};
@ -327,7 +335,7 @@ impl Set {
let mut index = 0;
while index < Set::get_size(this, context)? {
let arguments = if let Value::Object(ref object) = this {
let arguments = if let JsValue::Object(ref object) = this {
let object = object.borrow();
if let Some(set) = object.as_set_ref() {
set.get_index(index)
@ -346,7 +354,7 @@ impl Set {
index += 1;
}
Ok(Value::Undefined)
Ok(JsValue::Undefined)
}
/// `Map.prototype.has( key )`
@ -359,17 +367,13 @@ impl Set {
///
/// [spec]: https://tc39.es/ecma262/#sec-map.prototype.has
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has
pub(crate) fn has(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::Undefined;
let value = match args.len() {
0 => &undefined,
_ => &args[0],
};
pub(crate) fn has(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let value = args.get(0).cloned().unwrap_or_default();
if let Value::Object(ref object) = this {
if let JsValue::Object(ref object) = this {
let object = object.borrow();
if let Some(set) = object.as_set_ref() {
return Ok(set.contains(value).into());
return Ok(set.contains(&value).into());
}
}
@ -386,7 +390,7 @@ impl Set {
///
/// [spec]: https://tc39.es/ecma262/#sec-set.prototype.values
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/values
pub(crate) fn values(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn values(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
if let Some(object) = this.as_object() {
let object = object.borrow();
if !object.is_set() {
@ -406,13 +410,13 @@ impl Set {
))
}
fn size_getter(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
Set::get_size(this, context).map(Value::from)
fn size_getter(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
Set::get_size(this, context).map(JsValue::from)
}
/// Helper function to get the size of the set.
fn get_size(set: &Value, context: &mut Context) -> Result<usize> {
if let Value::Object(ref object) = set {
fn get_size(set: &JsValue, context: &mut Context) -> Result<usize> {
if let JsValue::Object(ref object) = set {
let object = object.borrow();
if let Some(set) = object.as_set_ref() {
Ok(set.size())

34
boa/src/builtins/set/set_iterator.rs

@ -2,7 +2,7 @@ use crate::{
builtins::function::make_builtin_fn,
builtins::iterable::create_iter_result_object,
builtins::Array,
builtins::Value,
builtins::JsValue,
object::{GcObject, ObjectData},
property::PropertyDescriptor,
symbol::WellKnownSymbols,
@ -24,7 +24,7 @@ pub enum SetIterationKind {
/// [spec]: https://tc39.es/ecma262/#sec-set-iterator-objects
#[derive(Debug, Clone, Finalize, Trace)]
pub struct SetIterator {
iterated_set: Value,
iterated_set: JsValue,
next_index: usize,
iteration_kind: SetIterationKind,
}
@ -33,7 +33,7 @@ impl SetIterator {
pub(crate) const NAME: &'static str = "SetIterator";
/// Constructs a new `SetIterator`, that will iterate over `set`, starting at index 0
fn new(set: Value, kind: SetIterationKind) -> Self {
fn new(set: JsValue, kind: SetIterationKind) -> Self {
SetIterator {
iterated_set: set,
next_index: 0,
@ -51,10 +51,10 @@ impl SetIterator {
/// [spec]: https://www.ecma-international.org/ecma-262/11.0/index.html#sec-createsetiterator
pub(crate) fn create_set_iterator(
context: &Context,
set: Value,
set: JsValue,
kind: SetIterationKind,
) -> Value {
let set_iterator = Value::new_object(context);
) -> JsValue {
let set_iterator = JsValue::new_object(context);
set_iterator.set_data(ObjectData::SetIterator(Self::new(set, kind)));
set_iterator
.as_object()
@ -71,8 +71,8 @@ impl SetIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%setiteratorprototype%.next
pub(crate) fn next(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
if let Value::Object(ref object) = this {
pub(crate) fn next(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
if let JsValue::Object(ref object) = this {
let mut object = object.borrow_mut();
if let Some(set_iterator) = object.as_set_iterator_mut() {
let m = &set_iterator.iterated_set;
@ -80,10 +80,14 @@ impl SetIterator {
let item_kind = &set_iterator.iteration_kind;
if set_iterator.iterated_set.is_undefined() {
return Ok(create_iter_result_object(context, Value::undefined(), true));
return Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
));
}
if let Value::Object(ref object) = m {
if let JsValue::Object(ref object) = m {
if let Some(entries) = object.borrow().as_set_ref() {
let num_entries = entries.size();
while index < num_entries {
@ -119,8 +123,12 @@ impl SetIterator {
return Err(context.construct_type_error("'this' is not a Set"));
}
set_iterator.iterated_set = Value::undefined();
Ok(create_iter_result_object(context, Value::undefined(), true))
set_iterator.iterated_set = JsValue::undefined();
Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
))
} else {
context.throw_type_error("`this` is not an SetIterator")
}
@ -135,7 +143,7 @@ impl SetIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%setiteratorprototype%-object
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: Value) -> GcObject {
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: JsValue) -> GcObject {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
// Create prototype

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

@ -20,7 +20,7 @@ use crate::{
object::{ConstructorBuilder, ObjectData},
property::{Attribute, PropertyDescriptor},
symbol::WellKnownSymbols,
BoaProfiler, Context, JsString, Result, Value,
BoaProfiler, Context, JsString, JsValue, Result,
};
use std::{
char::{decode_utf16, from_u32},
@ -90,7 +90,7 @@ impl BuiltIn for String {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let symbol_iterator = WellKnownSymbols::iterator();
@ -155,10 +155,10 @@ impl String {
///
/// <https://tc39.es/ecma262/#sec-string-constructor-string-value>
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
let string = match args.get(0) {
@ -184,7 +184,7 @@ impl String {
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let this = Value::new_object(context);
let this = JsValue::new_object(context);
this.as_object()
.expect("this should be an object")
@ -204,10 +204,10 @@ impl String {
Ok(this)
}
fn this_string_value(this: &Value, context: &mut Context) -> Result<JsString> {
fn this_string_value(this: &JsValue, context: &mut Context) -> Result<JsString> {
match this {
Value::String(ref string) => return Ok(string.clone()),
Value::Object(ref object) => {
JsValue::String(ref string) => return Ok(string.clone()),
JsValue::Object(ref object) => {
let object = object.borrow();
if let Some(string) = object.as_string() {
return Ok(string);
@ -222,9 +222,13 @@ impl String {
/// Get the string value to a primitive string
#[allow(clippy::wrong_self_convention)]
#[inline]
pub(crate) fn to_string(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_string(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// Get String from String Object and send it back as a new value
Ok(Value::from(Self::this_string_value(this, context)?))
Ok(JsValue::new(Self::this_string_value(this, context)?))
}
/// `String.prototype.charAt( index )`
@ -243,14 +247,18 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt
pub(crate) fn char_at(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn char_at(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(context)?;
let pos = args
.get(0)
.cloned()
.unwrap_or_else(Value::undefined)
.unwrap_or_else(JsValue::undefined)
.to_integer(context)? as i32;
// Fast path returning empty string when pos is obviously out of range
@ -263,7 +271,7 @@ impl String {
// Note that this is an O(N) operation (because UTF-8 is complex) while getting the number of
// bytes is an O(1) operation.
if let Some(utf16_val) = primitive_val.encode_utf16().nth(pos as usize) {
Ok(Value::from(from_u32(utf16_val as u32).unwrap()))
Ok(JsValue::new(from_u32(utf16_val as u32).unwrap()))
} else {
Ok("".into())
}
@ -280,7 +288,7 @@ impl String {
///
/// [spec]: https://tc39.es/proposal-relative-indexing-method/#sec-string.prototype.at
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/at
pub(crate) fn at(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn at(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let this = this.require_object_coercible(context)?;
let s = this.to_string(context)?;
let len = s.encode_utf16().count();
@ -296,11 +304,11 @@ impl String {
};
if let Some(utf16_val) = s.encode_utf16().nth(k) {
Ok(Value::from(
Ok(JsValue::new(
from_u32(u32::from(utf16_val)).expect("invalid utf-16 character"),
))
} else {
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}
@ -319,28 +327,28 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.codepointat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt
pub(crate) fn code_point_at(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(context)?;
let pos = args
.get(0)
.cloned()
.unwrap_or_else(Value::undefined)
.unwrap_or_else(JsValue::undefined)
.to_integer(context)? as i32;
// Fast path returning undefined when pos is obviously out of range
if pos < 0 || pos >= primitive_val.len() as i32 {
return Ok(Value::undefined());
return Ok(JsValue::undefined());
}
if let Some((code_point, _, _)) = code_point_at(primitive_val, pos) {
Ok(Value::from(code_point))
Ok(JsValue::new(code_point))
} else {
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}
@ -359,31 +367,31 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.charcodeat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
pub(crate) fn char_code_at(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(context)?;
let pos = args
.get(0)
.cloned()
.unwrap_or_else(Value::undefined)
.unwrap_or_else(JsValue::undefined)
.to_integer(context)? as i32;
// Fast path returning NaN when pos is obviously out of range
if pos < 0 || pos >= primitive_val.len() as i32 {
return Ok(Value::nan());
return Ok(JsValue::nan());
}
// Calling .len() on a string would give the wrong result, as they are bytes not the number of unicode code points
// Note that this is an O(N) operation (because UTF-8 is complex) while getting the number of bytes is an O(1) operation.
// If there is no element at that index, the result is NaN
if let Some(utf16_val) = primitive_val.encode_utf16().nth(pos as usize) {
Ok(Value::from(f64::from(utf16_val)))
Ok(JsValue::new(f64::from(utf16_val)))
} else {
Ok(Value::nan())
Ok(JsValue::nan())
}
}
@ -401,7 +409,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.concat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/concat
pub(crate) fn concat(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn concat(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let object = this.require_object_coercible(context)?;
let mut string = object.to_string(context)?.to_string();
@ -409,7 +421,7 @@ impl String {
string.push_str(&arg.to_string(context)?);
}
Ok(Value::from(string))
Ok(JsValue::new(string))
}
/// `String.prototype.repeat( count )`
@ -423,7 +435,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.repeat
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
pub(crate) fn repeat(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn repeat(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let object = this.require_object_coercible(context)?;
let string = object.to_string(context)?;
@ -457,7 +473,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.slice
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
pub(crate) fn slice(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn slice(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(context)?;
@ -469,12 +489,12 @@ impl String {
let start = args
.get(0)
.cloned()
.unwrap_or_else(Value::undefined)
.unwrap_or_else(JsValue::undefined)
.to_integer(context)? as i32;
let end = args
.get(1)
.cloned()
.unwrap_or_else(|| Value::integer(length))
.unwrap_or_else(|| JsValue::new(length))
.to_integer(context)? as i32;
let from = if start < 0 {
@ -495,7 +515,7 @@ impl String {
.skip(from as usize)
.take(span as usize)
.collect();
Ok(Value::from(new_str))
Ok(JsValue::new(new_str))
}
/// `String.prototype.startWith( searchString[, position] )`
@ -509,15 +529,15 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.startswith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
pub(crate) fn starts_with(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(context)?;
let arg = args.get(0).cloned().unwrap_or_else(Value::undefined);
let arg = args.get(0).cloned().unwrap_or_else(JsValue::undefined);
if Self::is_regexp_object(&arg) {
context.throw_type_error(
@ -543,11 +563,13 @@ impl String {
let end = start.wrapping_add(search_length);
if end > length {
Ok(Value::from(false))
Ok(JsValue::new(false))
} else {
// Only use the part of the string from "start"
let this_string: StdString = primitive_val.chars().skip(start as usize).collect();
Ok(Value::from(this_string.starts_with(search_string.as_str())))
Ok(JsValue::new(
this_string.starts_with(search_string.as_str()),
))
}
}
@ -561,12 +583,16 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.endswith
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
pub(crate) fn ends_with(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn ends_with(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(context)?;
let arg = args.get(0).cloned().unwrap_or_else(Value::undefined);
let arg = args.get(0).cloned().unwrap_or_else(JsValue::undefined);
if Self::is_regexp_object(&arg) {
context.throw_type_error(
@ -593,11 +619,11 @@ impl String {
let start = end.wrapping_sub(search_length);
if start < 0 {
Ok(Value::from(false))
Ok(JsValue::new(false))
} else {
// Only use the part of the string up to "end"
let this_string: StdString = primitive_val.chars().take(end as usize).collect();
Ok(Value::from(this_string.ends_with(search_string.as_str())))
Ok(JsValue::new(this_string.ends_with(search_string.as_str())))
}
}
@ -611,12 +637,16 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.includes
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
pub(crate) fn includes(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn includes(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(context)?;
let arg = args.get(0).cloned().unwrap_or_else(Value::undefined);
let arg = args.get(0).cloned().unwrap_or_else(JsValue::undefined);
if Self::is_regexp_object(&arg) {
context.throw_type_error(
@ -642,12 +672,12 @@ impl String {
// Take the string from "this" and use only the part of it after "start"
let this_string: StdString = primitive_val.chars().skip(start as usize).collect();
Ok(Value::from(this_string.contains(search_string.as_str())))
Ok(JsValue::new(this_string.contains(search_string.as_str())))
}
fn is_regexp_object(value: &Value) -> bool {
fn is_regexp_object(value: &JsValue) -> bool {
match value {
Value::Object(ref obj) => obj.borrow().is_regexp(),
JsValue::Object(ref obj) => obj.borrow().is_regexp(),
_ => false,
}
}
@ -667,7 +697,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.replace
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
pub(crate) fn replace(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn replace(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? RequireObjectCoercible(this value).
this.require_object_coercible(context)?;
@ -727,7 +761,7 @@ impl String {
context
.call(
&replace_value,
&Value::Undefined,
&JsValue::undefined(),
&[
search_str.into(),
position.unwrap().into(),
@ -746,7 +780,7 @@ impl String {
this_str.to_string(),
position.unwrap(),
captures,
Value::undefined(),
JsValue::undefined(),
replace_value.to_string(context)?,
context,
)?
@ -777,14 +811,18 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.indexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
pub(crate) fn index_of(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn index_of(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let this = this.require_object_coercible(context)?;
let string = this.to_string(context)?;
let search_string = args
.get(0)
.cloned()
.unwrap_or_else(Value::undefined)
.unwrap_or_else(JsValue::undefined)
.to_string(context)?;
let length = string.chars().count();
@ -804,7 +842,7 @@ impl String {
}
}
Ok(Value::from(-1))
Ok(JsValue::new(-1))
}
/// `String.prototype.lastIndexOf( searchValue[, fromIndex] )`
@ -821,17 +859,17 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.lastindexof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf
pub(crate) fn last_index_of(
this: &Value,
args: &[Value],
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let this = this.require_object_coercible(context)?;
let string = this.to_string(context)?;
let search_string = args
.get(0)
.cloned()
.unwrap_or_else(Value::undefined)
.unwrap_or_else(JsValue::undefined)
.to_string(context)?;
let length = string.chars().count();
@ -851,7 +889,7 @@ impl String {
}
}
Ok(Value::from(-1))
Ok(JsValue::new(-1))
}
/// `String.prototype.match( regexp )`
@ -865,7 +903,11 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.match
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
/// [regex]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
pub(crate) fn r#match(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn r#match(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? RequireObjectCoercible(this value).
let o = this.require_object_coercible(context)?;
@ -886,12 +928,12 @@ impl String {
let s = o.to_string(context)?;
// 4. Let rx be ? RegExpCreate(regexp, undefined).
let rx = RegExp::create(regexp, Value::undefined(), context)?;
let rx = RegExp::create(regexp, JsValue::undefined(), context)?;
// 5. Return ? Invoke(rx, @@match, « S »).
let obj = rx.as_object().expect("RegExpCreate must return Object");
if let Some(matcher) = obj.get_method(context, WellKnownSymbols::match_())? {
matcher.call(&rx, &[Value::from(s)], context)
matcher.call(&rx, &[JsValue::new(s)], context)
} else {
context.throw_type_error("RegExp[Symbol.match] is undefined")
}
@ -906,17 +948,17 @@ impl String {
max_length: i32,
fill_string: Option<JsString>,
at_start: bool,
) -> Value {
) -> JsValue {
let primitive_length = primitive.len() as i32;
if max_length <= primitive_length {
return Value::from(primitive);
return JsValue::new(primitive);
}
let filler = fill_string.as_deref().unwrap_or(" ");
if filler.is_empty() {
return Value::from(primitive);
return JsValue::new(primitive);
}
let fill_len = max_length.wrapping_sub(primitive_length);
@ -929,9 +971,9 @@ impl String {
let concat_fill_str: StdString = fill_str.chars().take(fill_len as usize).collect();
if at_start {
Value::from(format!("{}{}", concat_fill_str, &primitive))
JsValue::new(format!("{}{}", concat_fill_str, &primitive))
} else {
Value::from(format!("{}{}", primitive, &concat_fill_str))
JsValue::new(format!("{}{}", primitive, &concat_fill_str))
}
}
@ -947,10 +989,14 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
pub(crate) fn pad_end(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn pad_end(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let primitive = this.to_string(context)?;
if args.is_empty() {
return Err(Value::from("padEnd requires maxLength argument"));
return Err(JsValue::new("padEnd requires maxLength argument"));
}
let max_length = args
.get(0)
@ -974,10 +1020,14 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.padstart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
pub(crate) fn pad_start(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn pad_start(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let primitive = this.to_string(context)?;
if args.is_empty() {
return Err(Value::from("padStart requires maxLength argument"));
return Err(JsValue::new("padStart requires maxLength argument"));
}
let max_length = args
.get(0)
@ -1001,10 +1051,10 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trim
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
pub(crate) fn trim(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn trim(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
let this = this.require_object_coercible(context)?;
let string = this.to_string(context)?;
Ok(Value::from(string.trim_matches(is_trimmable_whitespace)))
Ok(JsValue::new(string.trim_matches(is_trimmable_whitespace)))
}
/// `String.prototype.trimStart()`
@ -1019,9 +1069,13 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimstart
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimStart
pub(crate) fn trim_start(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn trim_start(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let string = this.to_string(context)?;
Ok(Value::from(
Ok(JsValue::new(
string.trim_start_matches(is_trimmable_whitespace),
))
}
@ -1038,10 +1092,14 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.trimend
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd
pub(crate) fn trim_end(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn trim_end(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let this = this.require_object_coercible(context)?;
let string = this.to_string(context)?;
Ok(Value::from(
Ok(JsValue::new(
string.trim_end_matches(is_trimmable_whitespace),
))
}
@ -1057,13 +1115,17 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.tolowercase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_lowercase(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_lowercase(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let this_str = this.to_string(context)?;
// The Rust String is mapped to uppercase using the builtin .to_lowercase().
// There might be corner cases where it does not behave exactly like Javascript expects
Ok(Value::from(this_str.to_lowercase()))
Ok(JsValue::new(this_str.to_lowercase()))
}
/// `String.prototype.toUpperCase()`
@ -1079,13 +1141,17 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.toUppercase
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_uppercase(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_uppercase(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let this_str = this.to_string(context)?;
// The Rust String is mapped to uppercase using the builtin .to_uppercase().
// There might be corner cases where it does not behave exactly like Javascript expects
Ok(Value::from(this_str.to_uppercase()))
Ok(JsValue::new(this_str.to_uppercase()))
}
/// `String.prototype.substring( indexStart[, indexEnd] )`
@ -1098,7 +1164,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring
pub(crate) fn substring(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn substring(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(context)?;
@ -1135,7 +1205,7 @@ impl String {
.take(to.wrapping_sub(from)),
)
.collect();
Ok(Value::from(extracted_string.expect("Invalid string")))
Ok(JsValue::new(extracted_string.expect("Invalid string")))
}
/// `String.prototype.substr( start[, length] )`
@ -1149,7 +1219,11 @@ impl String {
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.substr
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr
/// <https://tc39.es/ecma262/#sec-string.prototype.substr>
pub(crate) fn substr(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn substr(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// First we get it the actual string a private field stored on the object only the context has access to.
// Then we convert it into a Rust String by wrapping it in from_value
let primitive_val = this.to_string(context)?;
@ -1183,7 +1257,7 @@ impl String {
// If length is negative we return an empty string
// otherwise we extract the part of the string from start and is length code units long
if result_length <= 0 {
Ok(Value::from(""))
Ok(JsValue::new(""))
} else {
let extracted_string: StdString = primitive_val
.chars()
@ -1191,7 +1265,7 @@ impl String {
.take(result_length as usize)
.collect();
Ok(Value::from(extracted_string))
Ok(JsValue::new(extracted_string))
}
}
@ -1206,7 +1280,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.split
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
pub(crate) fn split(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn split(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? RequireObjectCoercible(this value).
let this = this.require_object_coercible(context)?;
@ -1356,7 +1434,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.value_of
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/valueOf
pub(crate) fn value_of(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn value_of(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// Use the to_string method because it is specified to do the same thing in this case
Self::to_string(this, args, context)
}
@ -1373,7 +1455,11 @@ impl String {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll
/// [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
pub(crate) fn match_all(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn match_all(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? RequireObjectCoercible(this value).
let o = this.require_object_coercible(context)?;
@ -1411,12 +1497,12 @@ impl String {
let s = o.to_string(context)?;
// 4. Let rx be ? RegExpCreate(regexp, "g").
let rx = RegExp::create(regexp, Value::from("g"), context)?;
let rx = RegExp::create(regexp, JsValue::new("g"), context)?;
// 5. Return ? Invoke(rx, @@matchAll, « S »).
let obj = rx.as_object().expect("RegExpCreate must return Object");
if let Some(matcher) = obj.get_method(context, WellKnownSymbols::match_all())? {
matcher.call(&rx, &[Value::from(s)], context)
matcher.call(&rx, &[JsValue::new(s)], context)
} else {
context.throw_type_error("RegExp[Symbol.matchAll] is undefined")
}
@ -1432,7 +1518,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.normalize
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
pub(crate) fn normalize(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn normalize(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let this = this.require_object_coercible(context)?;
let s = this.to_string(context)?;
let form = args.get(0).cloned().unwrap_or_default();
@ -1447,10 +1537,10 @@ impl String {
};
match f {
"NFC" => Ok(Value::from(s.nfc().collect::<StdString>())),
"NFD" => Ok(Value::from(s.nfd().collect::<StdString>())),
"NFKC" => Ok(Value::from(s.nfkc().collect::<StdString>())),
"NFKD" => Ok(Value::from(s.nfkd().collect::<StdString>())),
"NFC" => Ok(JsValue::new(s.nfc().collect::<StdString>())),
"NFD" => Ok(JsValue::new(s.nfd().collect::<StdString>())),
"NFKC" => Ok(JsValue::new(s.nfkc().collect::<StdString>())),
"NFKD" => Ok(JsValue::new(s.nfkd().collect::<StdString>())),
_ => context
.throw_range_error("The normalization form should be one of NFC, NFD, NFKC, NFKD."),
}
@ -1466,7 +1556,11 @@ impl String {
///
/// [spec]: https://tc39.es/ecma262/#sec-string.prototype.search
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search
pub(crate) fn search(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn search(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
// 1. Let O be ? RequireObjectCoercible(this value).
let o = this.require_object_coercible(context)?;
@ -1487,18 +1581,22 @@ impl String {
let string = o.to_string(context)?;
// 4. Let rx be ? RegExpCreate(regexp, undefined).
let rx = RegExp::create(regexp, Value::undefined(), context)?;
let rx = RegExp::create(regexp, JsValue::undefined(), context)?;
// 5. Return ? Invoke(rx, @@search, « string »).
let obj = rx.as_object().expect("RegExpCreate must return Object");
if let Some(matcher) = obj.get_method(context, WellKnownSymbols::search())? {
matcher.call(&rx, &[Value::from(string)], context)
matcher.call(&rx, &[JsValue::new(string)], context)
} else {
context.throw_type_error("RegExp[Symbol.search] is undefined")
}
}
pub(crate) fn iterator(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn iterator(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
StringIterator::create_string_iterator(context, this.clone())
}
}
@ -1513,8 +1611,8 @@ pub(crate) fn get_substitution(
matched: StdString,
str: StdString,
position: usize,
captures: Vec<Value>,
named_captures: Value,
captures: Vec<JsValue>,
named_captures: JsValue,
replacement: JsString,
context: &mut Context,
) -> Result<JsString> {

30
boa/src/builtins/string/string_iterator.rs

@ -6,25 +6,25 @@ use crate::{
object::{GcObject, ObjectData},
property::PropertyDescriptor,
symbol::WellKnownSymbols,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
#[derive(Debug, Clone, Finalize, Trace)]
pub struct StringIterator {
string: Value,
string: JsValue,
next_index: i32,
}
impl StringIterator {
fn new(string: Value) -> Self {
fn new(string: JsValue) -> Self {
Self {
string,
next_index: 0,
}
}
pub fn create_string_iterator(context: &mut Context, string: Value) -> Result<Value> {
let string_iterator = Value::new_object(context);
pub fn create_string_iterator(context: &mut Context, string: JsValue) -> Result<JsValue> {
let string_iterator = JsValue::new_object(context);
string_iterator.set_data(ObjectData::StringIterator(Self::new(string)));
string_iterator
.as_object()
@ -33,19 +33,27 @@ impl StringIterator {
Ok(string_iterator)
}
pub fn next(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
if let Value::Object(ref object) = this {
pub fn next(this: &JsValue, _: &[JsValue], context: &mut Context) -> Result<JsValue> {
if let JsValue::Object(ref object) = this {
let mut object = object.borrow_mut();
if let Some(string_iterator) = object.as_string_iterator_mut() {
if string_iterator.string.is_undefined() {
return Ok(create_iter_result_object(context, Value::undefined(), true));
return Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
));
}
let native_string = string_iterator.string.to_string(context)?;
let len = native_string.encode_utf16().count() as i32;
let position = string_iterator.next_index;
if position >= len {
string_iterator.string = Value::undefined();
return Ok(create_iter_result_object(context, Value::undefined(), true));
string_iterator.string = JsValue::undefined();
return Ok(create_iter_result_object(
context,
JsValue::undefined(),
true,
));
}
let (_, code_unit_count, _) =
code_point_at(native_string, position).expect("Invalid code point position");
@ -70,7 +78,7 @@ impl StringIterator {
/// - [ECMA reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-%arrayiteratorprototype%-object
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: Value) -> GcObject {
pub(crate) fn create_prototype(context: &mut Context, iterator_prototype: JsValue) -> GcObject {
let _timer = BoaProfiler::global().start_event("String Iterator", "init");
// Create prototype

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

@ -23,7 +23,7 @@ use crate::{
object::{ConstructorBuilder, FunctionBuilder},
property::Attribute,
symbol::{JsSymbol, WellKnownSymbols},
value::Value,
value::JsValue,
BoaProfiler, Context, JsString, Result,
};
@ -78,7 +78,7 @@ impl BuiltIn for Symbol {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
let symbol_async_iterator = WellKnownSymbols::async_iterator();
@ -160,10 +160,10 @@ impl Symbol {
/// [spec]: https://tc39.es/ecma262/#sec-symbol-description
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/Symbol
pub(crate) fn constructor(
new_target: &Value,
args: &[Value],
new_target: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
if new_target.is_undefined() {
return context.throw_type_error("Symbol is not a constructor");
}
@ -175,10 +175,10 @@ impl Symbol {
Ok(JsSymbol::new(description).into())
}
fn this_symbol_value(value: &Value, context: &mut Context) -> Result<JsSymbol> {
fn this_symbol_value(value: &JsValue, context: &mut Context) -> Result<JsSymbol> {
match value {
Value::Symbol(ref symbol) => return Ok(symbol.clone()),
Value::Object(ref object) => {
JsValue::Symbol(ref symbol) => return Ok(symbol.clone()),
JsValue::Object(ref object) => {
let object = object.borrow();
if let Some(symbol) = object.as_symbol() {
return Ok(symbol);
@ -201,7 +201,11 @@ impl Symbol {
/// [spec]: https://tc39.es/ecma262/#sec-symbol.prototype.tostring
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toString
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, _: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn to_string(
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let symbol = Self::this_symbol_value(this, context)?;
Ok(symbol.to_string().into())
}
@ -217,15 +221,15 @@ impl Symbol {
/// [spec]: https://tc39.es/ecma262/#sec-symbol.prototype.description
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/description
pub(crate) fn get_description(
this: &Value,
_: &[Value],
this: &JsValue,
_: &[JsValue],
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
let symbol = Self::this_symbol_value(this, context)?;
if let Some(ref description) = symbol.description() {
Ok(description.clone().into())
} else {
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}
@ -237,7 +241,7 @@ impl Symbol {
///
/// [spec]: https://tc39.es/ecma262/#sec-symbol.prototype.for
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for
pub(crate) fn for_(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn for_(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
// 1. Let stringKey be ? ToString(key).
let string_key = args
.get(0)
@ -267,7 +271,7 @@ impl Symbol {
///
/// [spec]: https://tc39.es/ecma262/#sec-symbol.prototype.keyfor
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/keyFor
pub(crate) fn key_for(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub(crate) fn key_for(_: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
let sym = args.get(0).cloned().unwrap_or_default();
// 1. If Type(sym) is not Symbol, throw a TypeError exception.
if let Some(sym) = sym.as_symbol() {
@ -280,7 +284,7 @@ impl Symbol {
registry.get_symbol(sym)
});
Ok(symbol.map(Value::from).unwrap_or_default())
Ok(symbol.map(JsValue::from).unwrap_or_default())
} else {
context.throw_type_error("Symbol.keyFor: sym is not a symbol")
}

6
boa/src/builtins/undefined/mod.rs

@ -9,7 +9,7 @@
//! [spec]: https://tc39.es/ecma262/#sec-undefined
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined
use crate::{builtins::BuiltIn, property::Attribute, BoaProfiler, Context, Value};
use crate::{builtins::BuiltIn, property::Attribute, BoaProfiler, Context, JsValue};
#[cfg(test)]
mod tests;
@ -25,9 +25,9 @@ impl BuiltIn for Undefined {
Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT
}
fn init(_: &mut Context) -> (&'static str, Value, Attribute) {
fn init(_: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
(Self::NAME, Value::undefined(), Self::attribute())
(Self::NAME, JsValue::undefined(), Self::attribute())
}
}

6
boa/src/bytecompiler.rs

@ -5,7 +5,7 @@ use crate::{
Const, Node,
},
vm::{CodeBlock, Opcode},
JsBigInt, JsString, Value,
JsBigInt, JsString, JsValue,
};
use std::collections::HashMap;
@ -72,8 +72,8 @@ impl ByteCompiler {
}
let value = match liternal.clone() {
Literal::String(value) => Value::from(value),
Literal::BigInt(value) => Value::from(value),
Literal::String(value) => JsValue::new(value),
Literal::BigInt(value) => JsValue::new(value),
};
let index = self.code_block.literals.len() as u32;

18
boa/src/class.rs

@ -6,7 +6,7 @@
//!# property::Attribute,
//!# class::{Class, ClassBuilder},
//!# gc::{Finalize, Trace},
//!# Context, Result, Value,
//!# Context, Result, JsValue,
//!# };
//!#
//! // This does not have to be an enum it can also be a struct.
@ -25,7 +25,7 @@
//! const LENGTH: usize = 1;
//!
//! // This is what is called when we do `new Animal()`
//! fn constructor(_this: &Value, args: &[Value], context: &mut Context) -> Result<Self> {
//! fn constructor(_this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<Self> {
//! // This is equivalent to `String(arg)`.
//! let kind = args.get(0).cloned().unwrap_or_default().to_string(context)?;
//!
@ -50,7 +50,7 @@
//! }
//! }
//! }
//! Ok(Value::undefined())
//! Ok(JsValue::undefined())
//! });
//!
//! Ok(())
@ -64,7 +64,7 @@ use crate::{
builtins::function::NativeFunction,
object::{ConstructorBuilder, GcObject, NativeObject, ObjectData},
property::{Attribute, PropertyDescriptor, PropertyKey},
Context, Result, Value,
Context, JsValue, Result,
};
/// Native class.
@ -77,7 +77,7 @@ pub trait Class: NativeObject + Sized {
const ATTRIBUTES: Attribute = Attribute::all();
/// The constructor of the class.
fn constructor(this: &Value, args: &[Value], context: &mut Context) -> Result<Self>;
fn constructor(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<Self>;
/// Initializes the internals and the methods of the class.
fn init(class: &mut ClassBuilder<'_>) -> Result<()>;
@ -88,13 +88,13 @@ pub trait Class: NativeObject + Sized {
/// This is automatically implemented, when a type implements `Class`.
pub trait ClassConstructor: Class {
/// The raw constructor that mathces the `NativeFunction` signature.
fn raw_constructor(this: &Value, args: &[Value], context: &mut Context) -> Result<Value>
fn raw_constructor(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue>
where
Self: Sized;
}
impl<T: Class> ClassConstructor for T {
fn raw_constructor(this: &Value, args: &[Value], context: &mut Context) -> Result<Value>
fn raw_constructor(this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue>
where
Self: Sized,
{
@ -163,7 +163,7 @@ impl<'context> ClassBuilder<'context> {
pub fn property<K, V>(&mut self, key: K, value: V, attribute: Attribute) -> &mut Self
where
K: Into<PropertyKey>,
V: Into<Value>,
V: Into<JsValue>,
{
self.builder.property(key, value, attribute);
self
@ -176,7 +176,7 @@ impl<'context> ClassBuilder<'context> {
pub fn static_property<K, V>(&mut self, key: K, value: V, attribute: Attribute) -> &mut Self
where
K: Into<PropertyKey>,
V: Into<Value>,
V: Into<JsValue>,
{
self.builder.static_property(key, value, attribute);
self

53
boa/src/context.rs

@ -21,7 +21,7 @@ use crate::{
},
Parser,
},
BoaProfiler, Executable, JsString, Result, Value,
BoaProfiler, Executable, JsString, JsValue, Result,
};
#[cfg(feature = "console")]
@ -334,15 +334,20 @@ impl Context {
/// Construct an empty object.
#[inline]
pub fn construct_object(&self) -> GcObject {
let object_prototype: Value = self.standard_objects().object_object().prototype().into();
let object_prototype: JsValue = self.standard_objects().object_object().prototype().into();
GcObject::new(Object::create(object_prototype))
}
/// <https://tc39.es/ecma262/#sec-call>
#[inline]
pub(crate) fn call(&mut self, f: &Value, this: &Value, args: &[Value]) -> Result<Value> {
pub(crate) fn call(
&mut self,
f: &JsValue,
this: &JsValue,
args: &[JsValue],
) -> Result<JsValue> {
match *f {
Value::Object(ref object) => object.call(this, args, self),
JsValue::Object(ref object) => object.call(this, args, self),
_ => self.throw_type_error("not a function"),
}
}
@ -355,7 +360,7 @@ impl Context {
/// Constructs a `RangeError` with the specified message.
#[inline]
pub fn construct_range_error<M>(&mut self, message: M) -> Value
pub fn construct_range_error<M>(&mut self, message: M) -> JsValue
where
M: Into<Box<str>>,
{
@ -370,7 +375,7 @@ impl Context {
/// Throws a `RangeError` with the specified message.
#[inline]
pub fn throw_range_error<M>(&mut self, message: M) -> Result<Value>
pub fn throw_range_error<M>(&mut self, message: M) -> Result<JsValue>
where
M: Into<Box<str>>,
{
@ -379,7 +384,7 @@ impl Context {
/// Constructs a `TypeError` with the specified message.
#[inline]
pub fn construct_type_error<M>(&mut self, message: M) -> Value
pub fn construct_type_error<M>(&mut self, message: M) -> JsValue
where
M: Into<Box<str>>,
{
@ -394,7 +399,7 @@ impl Context {
/// Throws a `TypeError` with the specified message.
#[inline]
pub fn throw_type_error<M>(&mut self, message: M) -> Result<Value>
pub fn throw_type_error<M>(&mut self, message: M) -> Result<JsValue>
where
M: Into<Box<str>>,
{
@ -403,7 +408,7 @@ impl Context {
/// Constructs a `ReferenceError` with the specified message.
#[inline]
pub fn construct_reference_error<M>(&mut self, message: M) -> Value
pub fn construct_reference_error<M>(&mut self, message: M) -> JsValue
where
M: Into<Box<str>>,
{
@ -417,7 +422,7 @@ impl Context {
/// Throws a `ReferenceError` with the specified message.
#[inline]
pub fn throw_reference_error<M>(&mut self, message: M) -> Result<Value>
pub fn throw_reference_error<M>(&mut self, message: M) -> Result<JsValue>
where
M: Into<Box<str>>,
{
@ -426,7 +431,7 @@ impl Context {
/// Constructs a `SyntaxError` with the specified message.
#[inline]
pub fn construct_syntax_error<M>(&mut self, message: M) -> Value
pub fn construct_syntax_error<M>(&mut self, message: M) -> JsValue
where
M: Into<Box<str>>,
{
@ -440,7 +445,7 @@ impl Context {
/// Throws a `SyntaxError` with the specified message.
#[inline]
pub fn throw_syntax_error<M>(&mut self, message: M) -> Result<Value>
pub fn throw_syntax_error<M>(&mut self, message: M) -> Result<JsValue>
where
M: Into<Box<str>>,
{
@ -448,7 +453,7 @@ impl Context {
}
/// Constructs a `EvalError` with the specified message.
pub fn construct_eval_error<M>(&mut self, message: M) -> Value
pub fn construct_eval_error<M>(&mut self, message: M) -> JsValue
where
M: Into<Box<str>>,
{
@ -461,7 +466,7 @@ impl Context {
}
/// Constructs a `URIError` with the specified message.
pub fn construct_uri_error<M>(&mut self, message: M) -> Value
pub fn construct_uri_error<M>(&mut self, message: M) -> JsValue
where
M: Into<Box<str>>,
{
@ -474,7 +479,7 @@ impl Context {
}
/// Throws a `EvalError` with the specified message.
pub fn throw_eval_error<M>(&mut self, message: M) -> Result<Value>
pub fn throw_eval_error<M>(&mut self, message: M) -> Result<JsValue>
where
M: Into<Box<str>>,
{
@ -482,7 +487,7 @@ impl Context {
}
/// Throws a `URIError` with the specified message.
pub fn throw_uri_error<M>(&mut self, message: M) -> Result<Value>
pub fn throw_uri_error<M>(&mut self, message: M) -> Result<JsValue>
where
M: Into<Box<str>>,
{
@ -496,14 +501,14 @@ impl Context {
params: P,
body: B,
flags: FunctionFlags,
) -> Result<Value>
) -> Result<JsValue>
where
N: Into<JsString>,
P: Into<Box<[FormalParameter]>>,
B: Into<StatementList>,
{
let name = name.into();
let function_prototype: Value =
let function_prototype: JsValue =
self.standard_objects().function_object().prototype().into();
// Every new function has a prototype property pre-made
@ -606,7 +611,7 @@ impl Context {
#[inline]
pub fn register_global_closure<F>(&mut self, name: &str, length: usize, body: F) -> Result<()>
where
F: Fn(&Value, &[Value], &mut Context) -> Result<Value> + 'static,
F: Fn(&JsValue, &[JsValue], &mut Context) -> Result<JsValue> + 'static,
{
let function = FunctionBuilder::closure(self, body)
.name(name)
@ -627,7 +632,7 @@ impl Context {
/// <https://tc39.es/ecma262/#sec-hasproperty>
#[inline]
pub(crate) fn has_property(&self, obj: &Value, key: &PropertyKey) -> bool {
pub(crate) fn has_property(&self, obj: &JsValue, key: &PropertyKey) -> bool {
if let Some(obj) = obj.as_object() {
obj.__has_property__(key)
} else {
@ -636,7 +641,7 @@ impl Context {
}
#[inline]
pub(crate) fn set_value(&mut self, node: &Node, value: Value) -> Result<Value> {
pub(crate) fn set_value(&mut self, node: &Node, value: JsValue) -> Result<JsValue> {
match node {
Node::Identifier(ref name) => {
self.set_mutable_binding(name.as_ref(), value.clone(), true)?;
@ -725,7 +730,7 @@ impl Context {
pub fn register_global_property<K, V>(&mut self, key: K, value: V, attribute: Attribute)
where
K: Into<PropertyKey>,
V: Into<Value>,
V: Into<JsValue>,
{
self.global_object().insert(
key,
@ -752,7 +757,7 @@ impl Context {
#[cfg(not(feature = "vm"))]
#[allow(clippy::unit_arg, clippy::drop_copy)]
#[inline]
pub fn eval<T: AsRef<[u8]>>(&mut self, src: T) -> Result<Value> {
pub fn eval<T: AsRef<[u8]>>(&mut self, src: T) -> Result<JsValue> {
let main_timer = BoaProfiler::global().start_event("Main", "Main");
let src_bytes: &[u8] = src.as_ref();
@ -786,7 +791,7 @@ impl Context {
/// ```
#[cfg(feature = "vm")]
#[allow(clippy::unit_arg, clippy::drop_copy)]
pub fn eval<T: AsRef<[u8]>>(&mut self, src: T) -> Result<Value> {
pub fn eval<T: AsRef<[u8]>>(&mut self, src: T) -> Result<JsValue> {
let main_timer = BoaProfiler::global().start_event("Main", "Main");
let src_bytes: &[u8] = src.as_ref();

19
boa/src/environment/declarative_environment_record.rs

@ -12,7 +12,7 @@ use crate::{
},
gc::{Finalize, Trace},
object::GcObject,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use gc::{Gc, GcCell};
use rustc_hash::FxHashMap;
@ -24,7 +24,7 @@ use rustc_hash::FxHashMap;
/// From this point onwards, a binding is referring to one of these structures.
#[derive(Trace, Finalize, Debug, Clone)]
pub struct DeclarativeEnvironmentRecordBinding {
pub value: Option<Value>,
pub value: Option<JsValue>,
pub can_delete: bool,
pub mutable: bool,
pub strict: bool,
@ -104,7 +104,7 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
Ok(())
}
fn initialize_binding(&self, name: &str, value: Value, _context: &mut Context) -> Result<()> {
fn initialize_binding(&self, name: &str, value: JsValue, _context: &mut Context) -> Result<()> {
if let Some(ref mut record) = self.env_rec.borrow_mut().get_mut(name) {
if record.value.is_none() {
record.value = Some(value);
@ -118,7 +118,7 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
fn set_mutable_binding(
&self,
name: &str,
value: Value,
value: JsValue,
mut strict: bool,
context: &mut Context,
) -> Result<()> {
@ -159,7 +159,12 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
Ok(())
}
fn get_binding_value(&self, name: &str, _strict: bool, context: &mut Context) -> Result<Value> {
fn get_binding_value(
&self,
name: &str,
_strict: bool,
context: &mut Context,
) -> Result<JsValue> {
if let Some(binding) = self.env_rec.borrow().get(name) {
if let Some(ref val) = binding.value {
Ok(val.clone())
@ -189,8 +194,8 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
false
}
fn get_this_binding(&self, _context: &mut Context) -> Result<Value> {
Ok(Value::undefined())
fn get_this_binding(&self, _context: &mut Context) -> Result<JsValue> {
Ok(JsValue::undefined())
}
fn has_super_binding(&self) -> bool {

21
boa/src/environment/environment_record_trait.rs

@ -13,7 +13,7 @@ use crate::{environment::lexical_environment::VariableScope, object::GcObject};
use crate::{
environment::lexical_environment::{Environment, EnvironmentType},
gc::{Finalize, Trace},
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt::Debug;
@ -55,7 +55,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
/// Set the value of an already existing but uninitialized binding in an Environment Record.
/// The String value N is the text of the bound name.
/// V is the value for the binding and is a value of any ECMAScript language type.
fn initialize_binding(&self, name: &str, value: Value, context: &mut Context) -> Result<()>;
fn initialize_binding(&self, name: &str, value: JsValue, context: &mut Context) -> Result<()>;
/// Set the value of an already existing mutable binding in an Environment Record.
/// The String value `name` is the text of the bound name.
@ -64,7 +64,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
fn set_mutable_binding(
&self,
name: &str,
value: Value,
value: JsValue,
strict: bool,
context: &mut Context,
) -> Result<()>;
@ -73,7 +73,8 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
/// The String value N is the text of the bound name.
/// S is used to identify references originating in strict mode code or that
/// otherwise require strict mode reference semantics.
fn get_binding_value(&self, name: &str, strict: bool, context: &mut Context) -> Result<Value>;
fn get_binding_value(&self, name: &str, strict: bool, context: &mut Context)
-> Result<JsValue>;
/// Delete a binding from an Environment Record.
/// The String value name is the text of the bound name.
@ -86,7 +87,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
fn has_this_binding(&self) -> bool;
/// Return the `this` binding from the environment
fn get_this_binding(&self, context: &mut Context) -> Result<Value>;
fn get_this_binding(&self, context: &mut Context) -> Result<JsValue>;
/// Determine if an Environment Record establishes a super method binding.
/// Return true if it does and false if it does not.
@ -109,13 +110,13 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
fn get_environment_type(&self) -> EnvironmentType;
/// Return the `this` binding from the environment or try to get it from outer environments
fn recursive_get_this_binding(&self, context: &mut Context) -> Result<Value> {
fn recursive_get_this_binding(&self, context: &mut Context) -> Result<JsValue> {
if self.has_this_binding() {
self.get_this_binding(context)
} else {
match self.get_outer_environment_ref() {
Some(outer) => outer.recursive_get_this_binding(context),
None => Ok(Value::Undefined),
None => Ok(JsValue::undefined()),
}
}
}
@ -158,7 +159,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
fn recursive_set_mutable_binding(
&self,
name: &str,
value: Value,
value: JsValue,
strict: bool,
context: &mut Context,
) -> Result<()> {
@ -175,7 +176,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
fn recursive_initialize_binding(
&self,
name: &str,
value: Value,
value: JsValue,
context: &mut Context,
) -> Result<()> {
if self.has_binding(name) {
@ -197,7 +198,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
}
/// Retrieve binding from current or any outer environment
fn recursive_get_binding_value(&self, name: &str, context: &mut Context) -> Result<Value> {
fn recursive_get_binding_value(&self, name: &str, context: &mut Context) -> Result<JsValue> {
if self.has_binding(name) {
self.get_binding_value(name, false, context)
} else {

35
boa/src/environment/function_environment_record.rs

@ -18,7 +18,7 @@ use crate::{
},
gc::{empty_trace, Finalize, Trace},
object::GcObject,
Context, Result, Value,
Context, JsValue, Result,
};
/// Different binding status for `this`.
@ -42,7 +42,7 @@ unsafe impl Trace for BindingStatus {
pub struct FunctionEnvironmentRecord {
pub declarative_record: DeclarativeEnvironmentRecord,
/// This is the this value used for this invocation of the function.
pub this_value: Value,
pub this_value: JsValue,
/// If the value is "lexical", this is an ArrowFunction and does not have a local this value.
pub this_binding_status: BindingStatus,
/// The function object whose invocation caused this Environment Record to be created.
@ -50,28 +50,28 @@ pub struct FunctionEnvironmentRecord {
/// If the associated function has super property accesses and is not an ArrowFunction,
/// `[[HomeObject]]` is the object that the function is bound to as a method.
/// The default value for `[[HomeObject]]` is undefined.
pub home_object: Value,
pub home_object: JsValue,
/// If this Environment Record was created by the `[[Construct]]` internal method,
/// `[[NewTarget]]` is the value of the `[[Construct]]` newTarget parameter.
/// Otherwise, its value is undefined.
pub new_target: Value,
pub new_target: JsValue,
}
impl FunctionEnvironmentRecord {
pub fn new(
f: GcObject,
this: Option<Value>,
this: Option<JsValue>,
outer: Option<Environment>,
binding_status: BindingStatus,
new_target: Value,
new_target: JsValue,
) -> FunctionEnvironmentRecord {
let mut func_env = FunctionEnvironmentRecord {
declarative_record: DeclarativeEnvironmentRecord::new(outer), // the outer environment will come from Environment set as a private property of F - https://tc39.es/ecma262/#sec-ecmascript-function-objects
function: f,
this_binding_status: binding_status,
home_object: Value::undefined(),
home_object: JsValue::undefined(),
new_target,
this_value: Value::undefined(),
this_value: JsValue::undefined(),
};
// If a `this` value has been passed, bind it to the environment
if let Some(v) = this {
@ -80,7 +80,7 @@ impl FunctionEnvironmentRecord {
func_env
}
pub fn bind_this_value(&mut self, value: Value) -> Result<Value> {
pub fn bind_this_value(&mut self, value: JsValue) -> Result<JsValue> {
match self.this_binding_status {
// You can not bind an arrow function, their `this` value comes from the lexical scope above
BindingStatus::Lexical => {
@ -99,10 +99,10 @@ impl FunctionEnvironmentRecord {
}
}
pub fn get_super_base(&self) -> Value {
pub fn get_super_base(&self) -> JsValue {
let home = &self.home_object;
if home.is_undefined() {
Value::Undefined
JsValue::undefined()
} else {
assert!(home.is_object());
home.as_object()
@ -138,7 +138,7 @@ impl EnvironmentRecordTrait for FunctionEnvironmentRecord {
.create_immutable_binding(name, strict, context)
}
fn initialize_binding(&self, name: &str, value: Value, context: &mut Context) -> Result<()> {
fn initialize_binding(&self, name: &str, value: JsValue, context: &mut Context) -> Result<()> {
self.declarative_record
.initialize_binding(name, value, context)
}
@ -146,7 +146,7 @@ impl EnvironmentRecordTrait for FunctionEnvironmentRecord {
fn set_mutable_binding(
&self,
name: &str,
value: Value,
value: JsValue,
strict: bool,
context: &mut Context,
) -> Result<()> {
@ -154,7 +154,12 @@ impl EnvironmentRecordTrait for FunctionEnvironmentRecord {
.set_mutable_binding(name, value, strict, context)
}
fn get_binding_value(&self, name: &str, strict: bool, context: &mut Context) -> Result<Value> {
fn get_binding_value(
&self,
name: &str,
strict: bool,
context: &mut Context,
) -> Result<JsValue> {
self.declarative_record
.get_binding_value(name, strict, context)
}
@ -167,7 +172,7 @@ impl EnvironmentRecordTrait for FunctionEnvironmentRecord {
!matches!(self.this_binding_status, BindingStatus::Lexical)
}
fn get_this_binding(&self, context: &mut Context) -> Result<Value> {
fn get_this_binding(&self, context: &mut Context) -> Result<JsValue> {
match self.this_binding_status {
BindingStatus::Lexical => {
panic!("There is no this for a lexical function record");

25
boa/src/environment/global_environment_record.rs

@ -17,7 +17,7 @@ use crate::{
gc::{Finalize, Trace},
object::GcObject,
property::PropertyDescriptor,
Context, Result, Value,
Context, JsValue, Result,
};
use gc::{Gc, GcCell};
use rustc_hash::FxHashSet;
@ -111,7 +111,7 @@ impl GlobalEnvironmentRecord {
let extensible = global_object.is_extensible();
if !has_property && extensible {
obj_rec.create_mutable_binding(name.clone(), deletion, false, context)?;
obj_rec.initialize_binding(&name, Value::undefined(), context)?;
obj_rec.initialize_binding(&name, JsValue::undefined(), context)?;
}
let mut var_declared_names = self.var_names.borrow_mut();
@ -121,7 +121,7 @@ impl GlobalEnvironmentRecord {
Ok(())
}
pub fn create_global_function_binding(&mut self, name: &str, value: Value, deletion: bool) {
pub fn create_global_function_binding(&mut self, name: &str, value: JsValue, deletion: bool) {
let global_object = &mut self.object_record.bindings;
let existing_prop = global_object.get_property(name);
// TODO: change to desc.is_undefined()
@ -184,7 +184,7 @@ impl EnvironmentRecordTrait for GlobalEnvironmentRecord {
.create_immutable_binding(name, strict, context)
}
fn initialize_binding(&self, name: &str, value: Value, context: &mut Context) -> Result<()> {
fn initialize_binding(&self, name: &str, value: JsValue, context: &mut Context) -> Result<()> {
if self.declarative_record.has_binding(name) {
return self
.declarative_record
@ -201,7 +201,7 @@ impl EnvironmentRecordTrait for GlobalEnvironmentRecord {
fn set_mutable_binding(
&self,
name: &str,
value: Value,
value: JsValue,
strict: bool,
context: &mut Context,
) -> Result<()> {
@ -214,7 +214,12 @@ impl EnvironmentRecordTrait for GlobalEnvironmentRecord {
.set_mutable_binding(name, value, strict, context)
}
fn get_binding_value(&self, name: &str, strict: bool, context: &mut Context) -> Result<Value> {
fn get_binding_value(
&self,
name: &str,
strict: bool,
context: &mut Context,
) -> Result<JsValue> {
if self.declarative_record.has_binding(name) {
return self
.declarative_record
@ -228,7 +233,7 @@ impl EnvironmentRecordTrait for GlobalEnvironmentRecord {
return self.declarative_record.delete_binding(name);
}
let global: &Value = &self.object_record.bindings;
let global: &JsValue = &self.object_record.bindings;
if global.has_field(name) {
let status = self.object_record.delete_binding(name);
if status {
@ -246,7 +251,7 @@ impl EnvironmentRecordTrait for GlobalEnvironmentRecord {
true
}
fn get_this_binding(&self, _context: &mut Context) -> Result<Value> {
fn get_this_binding(&self, _context: &mut Context) -> Result<JsValue> {
Ok(self.global_this_binding.clone().into())
}
@ -298,7 +303,7 @@ impl EnvironmentRecordTrait for GlobalEnvironmentRecord {
fn recursive_set_mutable_binding(
&self,
name: &str,
value: Value,
value: JsValue,
strict: bool,
context: &mut Context,
) -> Result<()> {
@ -308,7 +313,7 @@ impl EnvironmentRecordTrait for GlobalEnvironmentRecord {
fn recursive_initialize_binding(
&self,
name: &str,
value: Value,
value: JsValue,
context: &mut Context,
) -> Result<()> {
self.initialize_binding(name, value, context)

10
boa/src/environment/lexical_environment.rs

@ -8,7 +8,7 @@
use super::global_environment_record::GlobalEnvironmentRecord;
use crate::{
environment::environment_record_trait::EnvironmentRecordTrait, object::GcObject, BoaProfiler,
Context, Result, Value,
Context, JsValue, Result,
};
use gc::Gc;
use std::{collections::VecDeque, error, fmt};
@ -88,7 +88,7 @@ impl Context {
self.realm.environment.environment_stack.pop_back()
}
pub(crate) fn get_this_binding(&mut self) -> Result<Value> {
pub(crate) fn get_this_binding(&mut self) -> Result<JsValue> {
self.get_current_environment()
.recursive_get_this_binding(self)
}
@ -116,14 +116,14 @@ impl Context {
pub(crate) fn set_mutable_binding(
&mut self,
name: &str,
value: Value,
value: JsValue,
strict: bool,
) -> Result<()> {
self.get_current_environment()
.recursive_set_mutable_binding(name, value, strict, self)
}
pub(crate) fn initialize_binding(&mut self, name: &str, value: Value) -> Result<()> {
pub(crate) fn initialize_binding(&mut self, name: &str, value: JsValue) -> Result<()> {
self.get_current_environment()
.recursive_initialize_binding(name, value, self)
}
@ -143,7 +143,7 @@ impl Context {
self.get_current_environment().recursive_has_binding(name)
}
pub(crate) fn get_binding_value(&mut self, name: &str) -> Result<Value> {
pub(crate) fn get_binding_value(&mut self, name: &str) -> Result<JsValue> {
self.get_current_environment()
.recursive_get_binding_value(name, self)
}

27
boa/src/environment/object_environment_record.rs

@ -16,19 +16,19 @@ use crate::{
gc::{Finalize, Trace},
object::GcObject,
property::PropertyDescriptor,
Context, Result, Value,
Context, JsValue, Result,
};
#[derive(Debug, Trace, Finalize, Clone)]
pub struct ObjectEnvironmentRecord {
// TODO: bindings should be an object.
pub bindings: Value,
pub bindings: JsValue,
pub with_environment: bool,
pub outer_env: Option<Environment>,
}
impl ObjectEnvironmentRecord {
pub fn new(object: Value, environment: Option<Environment>) -> ObjectEnvironmentRecord {
pub fn new(object: JsValue, environment: Option<Environment>) -> ObjectEnvironmentRecord {
ObjectEnvironmentRecord {
bindings: object,
outer_env: environment,
@ -65,7 +65,7 @@ impl EnvironmentRecordTrait for ObjectEnvironmentRecord {
// only for it to be replace with the real value later. We could just add the name to a Vector instead
let bindings = &self.bindings;
let prop = PropertyDescriptor::builder()
.value(Value::undefined())
.value(JsValue::undefined())
.writable(true)
.enumerable(true)
.configurable(deletion);
@ -83,7 +83,7 @@ impl EnvironmentRecordTrait for ObjectEnvironmentRecord {
Ok(())
}
fn initialize_binding(&self, name: &str, value: Value, context: &mut Context) -> Result<()> {
fn initialize_binding(&self, name: &str, value: JsValue, context: &mut Context) -> Result<()> {
// We should never need to check if a binding has been created,
// As all calls to create_mutable_binding are followed by initialized binding
// The below is just a check.
@ -94,7 +94,7 @@ impl EnvironmentRecordTrait for ObjectEnvironmentRecord {
fn set_mutable_binding(
&self,
name: &str,
value: Value,
value: JsValue,
strict: bool,
_context: &mut Context,
) -> Result<()> {
@ -110,7 +110,12 @@ impl EnvironmentRecordTrait for ObjectEnvironmentRecord {
Ok(())
}
fn get_binding_value(&self, name: &str, strict: bool, context: &mut Context) -> Result<Value> {
fn get_binding_value(
&self,
name: &str,
strict: bool,
context: &mut Context,
) -> Result<JsValue> {
if self.bindings.has_field(name) {
Ok(self
.bindings
@ -118,11 +123,11 @@ impl EnvironmentRecordTrait for ObjectEnvironmentRecord {
.as_ref()
.and_then(|prop| prop.value())
.cloned()
.unwrap_or(Value::Undefined))
.unwrap_or_default())
} else if strict {
context.throw_reference_error(format!("{} has no binding", name))
} else {
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}
@ -135,8 +140,8 @@ impl EnvironmentRecordTrait for ObjectEnvironmentRecord {
false
}
fn get_this_binding(&self, _context: &mut Context) -> Result<Value> {
Ok(Value::undefined())
fn get_this_binding(&self, _context: &mut Context) -> Result<JsValue> {
Ok(JsValue::undefined())
}
fn has_super_binding(&self) -> bool {

4
boa/src/exec/mod.rs

@ -3,11 +3,11 @@
#[cfg(test)]
mod tests;
use crate::{Context, Result, Value};
use crate::{Context, JsValue, Result};
pub trait Executable {
/// Runs this executable in the given context.
fn run(&self, context: &mut Context) -> Result<Value>;
fn run(&self, context: &mut Context) -> Result<JsValue>;
}
#[derive(Debug, Eq, PartialEq)]

66
boa/src/exec/tests.rs

@ -1,4 +1,4 @@
use crate::{builtins::Number, exec, forward, forward_val, Context, Value};
use crate::{builtins::Number, exec, forward, forward_val, Context, JsValue};
#[test]
fn function_declaration_returns_undefined() {
@ -899,19 +899,19 @@ fn function_decl_hoisting() {
fn to_bigint() {
let mut context = Context::new();
assert!(Value::null().to_bigint(&mut context).is_err());
assert!(Value::undefined().to_bigint(&mut context).is_err());
assert!(Value::integer(55).to_bigint(&mut context).is_ok());
assert!(Value::rational(10.0).to_bigint(&mut context).is_ok());
assert!(Value::string("100").to_bigint(&mut context).is_ok());
assert!(JsValue::null().to_bigint(&mut context).is_err());
assert!(JsValue::undefined().to_bigint(&mut context).is_err());
assert!(JsValue::new(55).to_bigint(&mut context).is_ok());
assert!(JsValue::new(10.0).to_bigint(&mut context).is_ok());
assert!(JsValue::new("100").to_bigint(&mut context).is_ok());
}
#[test]
fn to_index() {
let mut context = Context::new();
assert_eq!(Value::undefined().to_index(&mut context).unwrap(), 0);
assert!(Value::integer(-1).to_index(&mut context).is_err());
assert_eq!(JsValue::undefined().to_index(&mut context).unwrap(), 0);
assert!(JsValue::new(-1).to_index(&mut context).is_err());
}
#[test]
@ -919,34 +919,34 @@ fn to_integer() {
let mut context = Context::new();
assert!(Number::equal(
Value::number(f64::NAN).to_integer(&mut context).unwrap(),
JsValue::nan().to_integer(&mut context).unwrap(),
0.0
));
assert!(Number::equal(
Value::number(f64::NEG_INFINITY)
JsValue::new(f64::NEG_INFINITY)
.to_integer(&mut context)
.unwrap(),
f64::NEG_INFINITY
));
assert!(Number::equal(
Value::number(f64::INFINITY)
JsValue::new(f64::INFINITY)
.to_integer(&mut context)
.unwrap(),
f64::INFINITY
));
assert!(Number::equal(
Value::number(0.0).to_integer(&mut context).unwrap(),
JsValue::new(0.0).to_integer(&mut context).unwrap(),
0.0
));
let number = Value::number(-0.0).to_integer(&mut context).unwrap();
let number = JsValue::new(-0.0).to_integer(&mut context).unwrap();
assert!(!number.is_sign_negative());
assert!(Number::equal(number, 0.0));
assert!(Number::equal(
Value::number(20.9).to_integer(&mut context).unwrap(),
JsValue::new(20.9).to_integer(&mut context).unwrap(),
20.0
));
assert!(Number::equal(
Value::number(-20.9).to_integer(&mut context).unwrap(),
JsValue::new(-20.9).to_integer(&mut context).unwrap(),
-20.0
));
}
@ -955,31 +955,29 @@ fn to_integer() {
fn to_length() {
let mut context = Context::new();
assert_eq!(Value::number(f64::NAN).to_length(&mut context).unwrap(), 0);
assert_eq!(JsValue::new(f64::NAN).to_length(&mut context).unwrap(), 0);
assert_eq!(
Value::number(f64::NEG_INFINITY)
JsValue::new(f64::NEG_INFINITY)
.to_length(&mut context)
.unwrap(),
0
);
assert_eq!(
Value::number(f64::INFINITY)
.to_length(&mut context)
.unwrap(),
JsValue::new(f64::INFINITY).to_length(&mut context).unwrap(),
Number::MAX_SAFE_INTEGER as usize
);
assert_eq!(Value::number(0.0).to_length(&mut context).unwrap(), 0);
assert_eq!(Value::number(-0.0).to_length(&mut context).unwrap(), 0);
assert_eq!(Value::number(20.9).to_length(&mut context).unwrap(), 20);
assert_eq!(Value::number(-20.9).to_length(&mut context).unwrap(), 0);
assert_eq!(JsValue::new(0.0).to_length(&mut context).unwrap(), 0);
assert_eq!(JsValue::new(-0.0).to_length(&mut context).unwrap(), 0);
assert_eq!(JsValue::new(20.9).to_length(&mut context).unwrap(), 20);
assert_eq!(JsValue::new(-20.9).to_length(&mut context).unwrap(), 0);
assert_eq!(
Value::number(100000000000.0)
JsValue::new(100000000000.0)
.to_length(&mut context)
.unwrap() as u64,
100000000000
);
assert_eq!(
Value::number(4010101101.0).to_length(&mut context).unwrap(),
JsValue::new(4010101101.0).to_length(&mut context).unwrap(),
4010101101
);
}
@ -990,7 +988,7 @@ fn to_int32() {
macro_rules! check_to_int32 {
($from:expr => $to:expr) => {
assert_eq!(Value::from($from).to_i32(&mut context).unwrap(), $to);
assert_eq!(JsValue::new($from).to_i32(&mut context).unwrap(), $to);
};
}
@ -1101,15 +1099,15 @@ fn to_int32() {
fn to_string() {
let mut context = Context::new();
assert_eq!(Value::null().to_string(&mut context).unwrap(), "null");
assert_eq!(JsValue::null().to_string(&mut context).unwrap(), "null");
assert_eq!(
Value::undefined().to_string(&mut context).unwrap(),
JsValue::undefined().to_string(&mut context).unwrap(),
"undefined"
);
assert_eq!(Value::integer(55).to_string(&mut context).unwrap(), "55");
assert_eq!(Value::rational(55.0).to_string(&mut context).unwrap(), "55");
assert_eq!(JsValue::new(55).to_string(&mut context).unwrap(), "55");
assert_eq!(JsValue::new(55.0).to_string(&mut context).unwrap(), "55");
assert_eq!(
Value::string("hello").to_string(&mut context).unwrap(),
JsValue::new("hello").to_string(&mut context).unwrap(),
"hello"
);
}
@ -1132,11 +1130,11 @@ fn calling_function_with_unspecified_arguments() {
fn to_object() {
let mut context = Context::new();
assert!(Value::undefined()
assert!(JsValue::undefined()
.to_object(&mut context)
.unwrap_err()
.is_object());
assert!(Value::null()
assert!(JsValue::null()
.to_object(&mut context)
.unwrap_err()
.is_object());

6
boa/src/lib.rs

@ -69,7 +69,7 @@ pub(crate) use crate::{exec::Executable, profiler::BoaProfiler};
// Export things to root level
#[doc(inline)]
pub use crate::{
bigint::JsBigInt, context::Context, string::JsString, symbol::JsSymbol, value::Value,
bigint::JsBigInt, context::Context, string::JsString, symbol::JsSymbol, value::JsValue,
};
use crate::syntax::{
@ -79,7 +79,7 @@ use crate::syntax::{
/// 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>;
pub type Result<T> = StdResult<T, JsValue>;
/// Parses the given source code.
///
@ -122,7 +122,7 @@ pub(crate) fn forward<T: AsRef<[u8]>>(context: &mut Context, src: T) -> String {
/// If the interpreter fails parsing an error value is returned instead (error object)
#[allow(clippy::unit_arg, clippy::drop_copy)]
#[cfg(test)]
pub(crate) fn forward_val<T: AsRef<[u8]>>(context: &mut Context, src: T) -> Result<Value> {
pub(crate) fn forward_val<T: AsRef<[u8]>>(context: &mut Context, src: T) -> Result<JsValue> {
let main_timer = BoaProfiler::global().start_event("Main", "Main");
let src_bytes: &[u8] = src.as_ref();

50
boa/src/object/gcobject.rs

@ -16,7 +16,7 @@ use crate::{
symbol::WellKnownSymbols,
syntax::ast::node::RcStatementList,
value::PreferredType,
Context, Executable, Result, Value,
Context, Executable, JsValue, Result,
};
use gc::{Finalize, Gc, GcCell, GcCellRef, GcCellRefMut, Trace};
use serde_json::{map::Map, Value as JSONValue};
@ -125,11 +125,11 @@ impl GcObject {
#[track_caller]
fn call_construct(
&self,
this_target: &Value,
args: &[Value],
this_target: &JsValue,
args: &[JsValue],
context: &mut Context,
construct: bool,
) -> Result<Value> {
) -> Result<JsValue> {
let this_function_object = self.clone();
let mut has_parameter_expressions = false;
@ -178,7 +178,7 @@ impl GcObject {
.prototype()
.into()
};
Value::from(Object::create(proto))
JsValue::new(Object::create(proto))
} else {
this_target.clone()
};
@ -199,7 +199,7 @@ impl GcObject {
} else {
BindingStatus::Uninitialized
},
Value::undefined(),
JsValue::undefined(),
);
let mut arguments_in_parameter_names = false;
@ -249,7 +249,7 @@ impl GcObject {
}
let value = match args.get(i).cloned() {
None | Some(Value::Undefined) => param
None | Some(JsValue::Undefined) => param
.init()
.map(|init| init.run(context).ok())
.flatten()
@ -280,7 +280,7 @@ impl GcObject {
} else {
BindingStatus::Uninitialized
},
Value::undefined(),
JsValue::undefined(),
);
context.push_environment(second_env);
}
@ -298,7 +298,7 @@ impl GcObject {
function(this_target, args, context)
}
FunctionBody::BuiltInConstructor(function) => {
function(&Value::undefined(), args, context)
function(&JsValue::undefined(), args, context)
}
FunctionBody::BuiltInFunction(function) => function(this_target, args, context),
FunctionBody::Closure(function) => (function)(this_target, args, context),
@ -329,7 +329,7 @@ impl GcObject {
// <https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist>
#[track_caller]
#[inline]
pub fn call(&self, this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
pub fn call(&self, this: &JsValue, args: &[JsValue], context: &mut Context) -> Result<JsValue> {
self.call_construct(this, args, context, false)
}
@ -343,10 +343,10 @@ impl GcObject {
#[inline]
pub fn construct(
&self,
args: &[Value],
new_target: &Value,
args: &[JsValue],
new_target: &JsValue,
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
self.call_construct(new_target, args, context, true)
}
@ -372,7 +372,7 @@ impl GcObject {
&self,
context: &mut Context,
hint: PreferredType,
) -> Result<Value> {
) -> Result<JsValue> {
// 1. Assert: Type(O) is Object.
// Already is GcObject by type.
// 2. Assert: Type(hint) is String and its value is either "string" or "number".
@ -386,8 +386,8 @@ impl GcObject {
if recursion_limiter.live {
// we're in a recursive object, bail
return Ok(match hint {
PreferredType::Number => Value::from(0),
PreferredType::String => Value::from(""),
PreferredType::Number => JsValue::new(0),
PreferredType::String => JsValue::new(""),
PreferredType::Default => unreachable!("checked type hint in step 2"),
});
}
@ -403,10 +403,10 @@ impl GcObject {
};
// 5. For each name in methodNames in List order, do
let this = Value::from(self.clone());
let this = JsValue::new(self.clone());
for name in &method_names {
// a. Let method be ? Get(O, name).
let method: Value = this.get_field(*name, context)?;
let method: JsValue = this.get_field(*name, context)?;
// b. If IsCallable(method) is true, then
if method.is_function() {
// i. Let result be ? Call(method, O).
@ -436,7 +436,7 @@ impl GcObject {
.collect();
keys.sort_unstable();
let mut arr: Vec<JSONValue> = Vec::with_capacity(keys.len());
let this = Value::from(self.clone());
let this = JsValue::new(self.clone());
for key in keys {
let value = this.get_field(key, context)?;
if let Some(value) = value.to_json(context)? {
@ -448,7 +448,7 @@ impl GcObject {
Ok(Some(JSONValue::Array(arr)))
} else {
let mut new_obj = Map::new();
let this = Value::from(self.clone());
let this = JsValue::new(self.clone());
let keys: Vec<PropertyKey> = self.borrow().properties.keys().collect();
for k in keys {
let key = k.clone();
@ -522,7 +522,7 @@ impl GcObject {
/// Panics if the object is currently mutably borrowed.
#[inline]
#[track_caller]
pub fn prototype_instance(&self) -> Value {
pub fn prototype_instance(&self) -> JsValue {
self.borrow().prototype_instance().clone()
}
@ -534,7 +534,7 @@ impl GcObject {
/// or if th prototype is not an object or undefined.
#[inline]
#[track_caller]
pub fn set_prototype_instance(&self, prototype: Value) -> bool {
pub fn set_prototype_instance(&self, prototype: JsValue) -> bool {
self.borrow_mut().set_prototype_instance(prototype)
}
@ -720,7 +720,7 @@ impl GcObject {
pub(crate) fn ordinary_has_instance(
&self,
context: &mut Context,
value: &Value,
value: &JsValue,
) -> Result<bool> {
// 1. If IsCallable(C) is false, return false.
if !self.is_callable() {
@ -771,9 +771,9 @@ impl GcObject {
/// [spec]: https://tc39.es/ecma262/#sec-speciesconstructor
pub(crate) fn species_constructor(
&self,
default_constructor: Value,
default_constructor: JsValue,
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
// 1. Assert: Type(O) is Object.
// 2. Let C be ? Get(O, "constructor").

46
boa/src/object/internal_methods.rs

@ -8,7 +8,7 @@
use crate::{
object::{GcObject, Object, ObjectData},
property::{DescriptorKind, PropertyDescriptor, PropertyKey},
value::{Type, Value},
value::{JsValue, Type},
BoaProfiler, Context, Result,
};
@ -106,7 +106,7 @@ impl GcObject {
///
/// [spec]: https://tc39.es/ecma262/#sec-get-o-p
#[inline]
pub fn get<K>(&self, key: K, context: &mut Context) -> Result<Value>
pub fn get<K>(&self, key: K, context: &mut Context) -> Result<JsValue>
where
K: Into<PropertyKey>,
{
@ -126,7 +126,7 @@ impl GcObject {
pub fn set<K, V>(&self, key: K, value: V, throw: bool, context: &mut Context) -> Result<bool>
where
K: Into<PropertyKey>,
V: Into<Value>,
V: Into<JsValue>,
{
let key = key.into();
// 1. Assert: Type(O) is Object.
@ -188,7 +188,7 @@ impl GcObject {
) -> Result<bool>
where
K: Into<PropertyKey>,
V: Into<Value>,
V: Into<JsValue>,
{
// 1. Assert: Type(O) is Object.
// 2. Assert: IsPropertyKey(P) is true.
@ -216,7 +216,7 @@ impl GcObject {
) -> Result<bool>
where
K: Into<PropertyKey>,
V: Into<Value>,
V: Into<JsValue>,
{
let key = key.into();
// 1. Assert: Type(O) is Object.
@ -237,7 +237,7 @@ impl GcObject {
let prop = self.__get_own_property__(key);
if prop.is_none() {
let parent = self.__get_prototype_of__();
return if let Value::Object(ref object) = parent {
return if let JsValue::Object(ref object) = parent {
object.__has_property__(key)
} else {
false
@ -286,16 +286,16 @@ impl GcObject {
pub fn __get__(
&self,
key: &PropertyKey,
receiver: Value,
receiver: JsValue,
context: &mut Context,
) -> Result<Value> {
) -> Result<JsValue> {
match self.__get_own_property__(key) {
None => {
// parent will either be null or an Object
if let Some(parent) = self.__get_prototype_of__().as_object() {
Ok(parent.__get__(key, receiver, context)?)
} else {
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}
Some(ref desc) => match desc.kind() {
@ -305,7 +305,7 @@ impl GcObject {
DescriptorKind::Accessor { get: Some(get), .. } if !get.is_undefined() => {
context.call(get, &receiver, &[])
}
_ => Ok(Value::undefined()),
_ => Ok(JsValue::undefined()),
},
}
}
@ -314,8 +314,8 @@ impl GcObject {
pub fn __set__(
&self,
key: PropertyKey,
value: Value,
receiver: Value,
value: JsValue,
receiver: JsValue,
context: &mut Context,
) -> Result<bool> {
let _timer = BoaProfiler::global().start_event("Object::set", "object");
@ -327,7 +327,7 @@ impl GcObject {
return parent.__set__(key, value, receiver, context);
} else {
PropertyDescriptor::builder()
.value(Value::undefined())
.value(JsValue::undefined())
.writable(true)
.enumerable(true)
.configurable(true)
@ -448,17 +448,17 @@ impl GcObject {
if matches!(desc.writable(), Some(true)) {
return false;
}
if matches!(desc.value(), Some(value) if !Value::same_value(value, current.expect_value()))
if matches!(desc.value(), Some(value) if !JsValue::same_value(value, current.expect_value()))
{
return false;
}
return true;
}
} else if !current.expect_configurable() {
if matches!(desc.set(), Some(set) if !Value::same_value(set, current.expect_set())) {
if matches!(desc.set(), Some(set) if !JsValue::same_value(set, current.expect_set())) {
return false;
}
if matches!(desc.get(), Some(get) if !Value::same_value(get, current.expect_get())) {
if matches!(desc.get(), Some(get) if !JsValue::same_value(get, current.expect_get())) {
return false;
}
return true;
@ -623,7 +623,7 @@ impl GcObject {
let result_str = string
.encode_utf16()
.nth(pos)
.map(|utf16_val| Value::from(String::from_utf16_lossy(&[utf16_val])))?;
.map(|utf16_val| JsValue::from(String::from_utf16_lossy(&[utf16_val])))?;
let desc = PropertyDescriptor::builder()
.value(result_str)
@ -690,7 +690,7 @@ impl GcObject {
///
/// [spec]: https://tc39.es/ecma262/#sec-object.defineproperties
#[inline]
pub fn define_properties(&mut self, props: Value, context: &mut Context) -> Result<()> {
pub fn define_properties(&mut self, props: JsValue, context: &mut Context) -> Result<()> {
let props = &props.to_object(context)?;
let keys = props.own_property_keys();
let mut descriptors: Vec<(PropertyKey, PropertyDescriptor)> = Vec::new();
@ -724,10 +724,10 @@ impl GcObject {
/// [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-setprototypeof-v
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf
#[inline]
pub fn __set_prototype_of__(&mut self, val: Value) -> bool {
pub fn __set_prototype_of__(&mut self, val: JsValue) -> bool {
debug_assert!(val.is_object() || val.is_null());
let current = self.__get_prototype_of__();
if Value::same_value(&current, &val) {
if JsValue::same_value(&current, &val) {
return true;
}
if !self.__is_extensible__() {
@ -738,7 +738,7 @@ impl GcObject {
while !done {
if p.is_null() {
done = true
} else if Value::same_value(&Value::from(self.clone()), &p) {
} else if JsValue::same_value(&JsValue::new(self.clone()), &p) {
return false;
} else {
let prototype = p
@ -762,7 +762,7 @@ impl GcObject {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf
#[inline]
#[track_caller]
pub fn __get_prototype_of__(&self) -> Value {
pub fn __get_prototype_of__(&self) -> JsValue {
self.borrow().prototype.clone()
}
@ -837,7 +837,7 @@ impl GcObject {
&self,
element_types: &[Type],
context: &mut Context,
) -> Result<Vec<Value>> {
) -> Result<Vec<JsValue>> {
// 1. If elementTypes is not present, set elementTypes to « Undefined, Null, Boolean, String, Symbol, Number, BigInt, Object ».
let types = if element_types.is_empty() {
&[

56
boa/src/object/mod.rs

@ -15,7 +15,7 @@ use crate::{
context::StandardConstructor,
gc::{Finalize, Trace},
property::{Attribute, PropertyDescriptor, PropertyKey},
BoaProfiler, Context, JsBigInt, JsString, JsSymbol, Value,
BoaProfiler, Context, JsBigInt, JsString, JsSymbol, JsValue,
};
use std::{
any::Any,
@ -68,7 +68,7 @@ pub struct Object {
pub data: ObjectData,
properties: PropertyMap,
/// Instance prototype `__proto__`.
prototype: Value,
prototype: JsValue,
/// Whether it can have new properties added to it.
extensible: bool,
}
@ -78,7 +78,7 @@ pub struct Object {
pub enum ObjectData {
Array,
ArrayIterator(ArrayIterator),
Map(OrderedMap<Value>),
Map(OrderedMap<JsValue>),
MapIterator(MapIterator),
RegExp(Box<RegExp>),
RegExpStringIterator(RegExpStringIterator),
@ -86,7 +86,7 @@ pub enum ObjectData {
Boolean(bool),
ForInIterator(ForInIterator),
Function(Function),
Set(OrderedSet<Value>),
Set(OrderedSet<JsValue>),
SetIterator(SetIterator),
String(JsString),
StringIterator(StringIterator),
@ -138,7 +138,7 @@ impl Default for Object {
Self {
data: ObjectData::Ordinary,
properties: PropertyMap::default(),
prototype: Value::null(),
prototype: JsValue::null(),
extensible: true,
}
}
@ -152,7 +152,7 @@ impl Object {
/// Return a new ObjectData struct, with `kind` set to Ordinary
#[inline]
pub fn function(function: Function, prototype: Value) -> Self {
pub fn function(function: Function, prototype: JsValue) -> Self {
let _timer = BoaProfiler::global().start_event("Object::Function", "object");
Self {
@ -171,7 +171,7 @@ impl Object {
/// [spec]: https://tc39.es/ecma262/#sec-objectcreate
// TODO: proto should be a &Value here
#[inline]
pub fn create(proto: Value) -> Self {
pub fn create(proto: JsValue) -> Self {
let mut obj = Self::new();
obj.prototype = proto;
obj
@ -183,7 +183,7 @@ impl Object {
Self {
data: ObjectData::Boolean(value),
properties: PropertyMap::default(),
prototype: Value::null(),
prototype: JsValue::null(),
extensible: true,
}
}
@ -194,7 +194,7 @@ impl Object {
Self {
data: ObjectData::Number(value),
properties: PropertyMap::default(),
prototype: Value::null(),
prototype: JsValue::null(),
extensible: true,
}
}
@ -208,7 +208,7 @@ impl Object {
Self {
data: ObjectData::String(value.into()),
properties: PropertyMap::default(),
prototype: Value::null(),
prototype: JsValue::null(),
extensible: true,
}
}
@ -219,7 +219,7 @@ impl Object {
Self {
data: ObjectData::BigInt(value),
properties: PropertyMap::default(),
prototype: Value::null(),
prototype: JsValue::null(),
extensible: true,
}
}
@ -233,7 +233,7 @@ impl Object {
Self {
data: ObjectData::NativeObject(Box::new(value)),
properties: PropertyMap::default(),
prototype: Value::null(),
prototype: JsValue::null(),
extensible: true,
}
}
@ -335,7 +335,7 @@ impl Object {
}
#[inline]
pub fn as_map_ref(&self) -> Option<&OrderedMap<Value>> {
pub fn as_map_ref(&self) -> Option<&OrderedMap<JsValue>> {
match self.data {
ObjectData::Map(ref map) => Some(map),
_ => None,
@ -343,7 +343,7 @@ impl Object {
}
#[inline]
pub fn as_map_mut(&mut self) -> Option<&mut OrderedMap<Value>> {
pub fn as_map_mut(&mut self) -> Option<&mut OrderedMap<JsValue>> {
match &mut self.data {
ObjectData::Map(map) => Some(map),
_ => None,
@ -364,7 +364,7 @@ impl Object {
}
#[inline]
pub fn as_set_ref(&self) -> Option<&OrderedSet<Value>> {
pub fn as_set_ref(&self) -> Option<&OrderedSet<JsValue>> {
match self.data {
ObjectData::Set(ref set) => Some(set),
_ => None,
@ -372,7 +372,7 @@ impl Object {
}
#[inline]
pub fn as_set_mut(&mut self) -> Option<&mut OrderedSet<Value>> {
pub fn as_set_mut(&mut self) -> Option<&mut OrderedSet<JsValue>> {
match &mut self.data {
ObjectData::Set(set) => Some(set),
_ => None,
@ -506,7 +506,7 @@ impl Object {
}
#[inline]
pub fn prototype_instance(&self) -> &Value {
pub fn prototype_instance(&self) -> &JsValue {
&self.prototype
}
@ -517,7 +517,7 @@ impl Object {
/// [spec]: https://tc39.es/ecma262/#sec-invariants-of-the-essential-internal-methods
#[inline]
#[track_caller]
pub fn set_prototype_instance(&mut self, prototype: Value) -> bool {
pub fn set_prototype_instance(&mut self, prototype: JsValue) -> bool {
assert!(prototype.is_null() || prototype.is_object());
if self.extensible {
self.prototype = prototype;
@ -525,13 +525,13 @@ impl Object {
} else {
// If target is non-extensible, [[SetPrototypeOf]] must return false
// unless V is the SameValue as the target's observed [[GetPrototypeOf]] value.
Value::same_value(&prototype, &self.prototype)
JsValue::same_value(&prototype, &self.prototype)
}
}
/// Similar to `Value::new_object`, but you can pass a prototype to create from, plus a kind
#[inline]
pub fn with_prototype(proto: Value, data: ObjectData) -> Object {
pub fn with_prototype(proto: JsValue, data: ObjectData) -> Object {
let mut object = Object::new();
object.data = data;
object.set_prototype_instance(proto);
@ -693,7 +693,7 @@ impl<'context> FunctionBuilder<'context> {
#[inline]
pub fn closure<F>(context: &'context mut Context, function: F) -> Self
where
F: Fn(&Value, &[Value], &mut Context) -> Result<Value, Value> + 'static,
F: Fn(&JsValue, &[JsValue], &mut Context) -> Result<JsValue, JsValue> + 'static,
{
Self {
context,
@ -789,7 +789,7 @@ impl<'context> FunctionBuilder<'context> {
/// # Examples
///
/// ```
/// # use boa::{Context, Value, object::ObjectInitializer, property::Attribute};
/// # use boa::{Context, JsValue, object::ObjectInitializer, property::Attribute};
/// let mut context = Context::new();
/// let object = ObjectInitializer::new(&mut context)
/// .property(
@ -802,7 +802,7 @@ impl<'context> FunctionBuilder<'context> {
/// 1,
/// Attribute::all()
/// )
/// .function(|_, _, _| Ok(Value::undefined()), "func", 0)
/// .function(|_, _, _| Ok(JsValue::undefined()), "func", 0)
/// .build();
/// ```
///
@ -857,7 +857,7 @@ impl<'context> ObjectInitializer<'context> {
pub fn property<K, V>(&mut self, key: K, value: V, attribute: Attribute) -> &mut Self
where
K: Into<PropertyKey>,
V: Into<Value>,
V: Into<JsValue>,
{
let property = PropertyDescriptor::builder()
.value(value)
@ -885,7 +885,7 @@ pub struct ConstructorBuilder<'context> {
length: usize,
callable: bool,
constructable: bool,
inherit: Option<Value>,
inherit: Option<JsValue>,
}
impl Debug for ConstructorBuilder<'_> {
@ -996,7 +996,7 @@ impl<'context> ConstructorBuilder<'context> {
pub fn property<K, V>(&mut self, key: K, value: V, attribute: Attribute) -> &mut Self
where
K: Into<PropertyKey>,
V: Into<Value>,
V: Into<JsValue>,
{
let property = PropertyDescriptor::builder()
.value(value)
@ -1012,7 +1012,7 @@ impl<'context> ConstructorBuilder<'context> {
pub fn static_property<K, V>(&mut self, key: K, value: V, attribute: Attribute) -> &mut Self
where
K: Into<PropertyKey>,
V: Into<Value>,
V: Into<JsValue>,
{
let property = PropertyDescriptor::builder()
.value(value)
@ -1132,7 +1132,7 @@ impl<'context> ConstructorBuilder<'context> {
///
/// Default is `Object.prototype`
#[inline]
pub fn inherit(&mut self, prototype: Value) -> &mut Self {
pub fn inherit(&mut self, prototype: JsValue) -> &mut Self {
assert!(prototype.is_object() || prototype.is_null());
self.inherit = Some(prototype);
self

56
boa/src/property/mod.rs

@ -16,7 +16,7 @@
use crate::{
gc::{Finalize, Trace},
JsString, JsSymbol, Value,
JsString, JsSymbol, JsValue,
};
use std::{convert::TryFrom, fmt};
@ -55,12 +55,12 @@ pub struct PropertyDescriptor {
#[derive(Debug, Clone, Trace, Finalize)]
pub enum DescriptorKind {
Data {
value: Option<Value>,
value: Option<JsValue>,
writable: Option<bool>,
},
Accessor {
get: Option<Value>,
set: Option<Value>,
get: Option<JsValue>,
set: Option<JsValue>,
},
Generic,
}
@ -129,7 +129,7 @@ impl PropertyDescriptor {
}
#[inline]
pub fn value(&self) -> Option<&Value> {
pub fn value(&self) -> Option<&JsValue> {
match &self.kind {
DescriptorKind::Data { value, .. } => value.as_ref(),
_ => None,
@ -137,7 +137,7 @@ impl PropertyDescriptor {
}
#[inline]
pub fn get(&self) -> Option<&Value> {
pub fn get(&self) -> Option<&JsValue> {
match &self.kind {
DescriptorKind::Accessor { get, .. } => get.as_ref(),
_ => None,
@ -145,7 +145,7 @@ impl PropertyDescriptor {
}
#[inline]
pub fn set(&self) -> Option<&Value> {
pub fn set(&self) -> Option<&JsValue> {
match &self.kind {
DescriptorKind::Accessor { set, .. } => set.as_ref(),
_ => None,
@ -180,7 +180,7 @@ impl PropertyDescriptor {
}
#[inline]
pub fn expect_value(&self) -> &Value {
pub fn expect_value(&self) -> &JsValue {
if let Some(value) = self.value() {
value
} else {
@ -189,7 +189,7 @@ impl PropertyDescriptor {
}
#[inline]
pub fn expect_get(&self) -> &Value {
pub fn expect_get(&self) -> &JsValue {
if let Some(get) = self.get() {
get
} else {
@ -198,7 +198,7 @@ impl PropertyDescriptor {
}
#[inline]
pub fn expect_set(&self) -> &Value {
pub fn expect_set(&self) -> &JsValue {
if let Some(set) = self.set() {
set
} else {
@ -298,7 +298,7 @@ impl PropertyDescriptorBuilder {
Self::default()
}
pub fn value<V: Into<Value>>(mut self, value: V) -> Self {
pub fn value<V: Into<JsValue>>(mut self, value: V) -> Self {
match self.inner.kind {
DescriptorKind::Data {
value: ref mut v, ..
@ -331,7 +331,7 @@ impl PropertyDescriptorBuilder {
self
}
pub fn get<V: Into<Value>>(mut self, get: V) -> Self {
pub fn get<V: Into<JsValue>>(mut self, get: V) -> Self {
match self.inner.kind {
DescriptorKind::Accessor { get: ref mut g, .. } => *g = Some(get.into()),
// TODO: maybe panic when trying to convert data to accessor?
@ -345,7 +345,7 @@ impl PropertyDescriptorBuilder {
self
}
pub fn set<V: Into<Value>>(mut self, set: V) -> Self {
pub fn set<V: Into<JsValue>>(mut self, set: V) -> Self {
match self.inner.kind {
DescriptorKind::Accessor { set: ref mut s, .. } => *s = Some(set.into()),
// TODO: maybe panic when trying to convert data to accessor?
@ -373,7 +373,7 @@ impl PropertyDescriptorBuilder {
self
}
pub fn maybe_value<V: Into<Value>>(mut self, value: Option<V>) -> Self {
pub fn maybe_value<V: Into<JsValue>>(mut self, value: Option<V>) -> Self {
if let Some(value) = value {
self = self.value(value);
}
@ -387,14 +387,14 @@ impl PropertyDescriptorBuilder {
self
}
pub fn maybe_get<V: Into<Value>>(mut self, get: Option<V>) -> Self {
pub fn maybe_get<V: Into<JsValue>>(mut self, get: Option<V>) -> Self {
if let Some(get) = get {
self = self.get(get);
}
self
}
pub fn maybe_set<V: Into<Value>>(mut self, set: Option<V>) -> Self {
pub fn maybe_set<V: Into<JsValue>>(mut self, set: Option<V>) -> Self {
if let Some(set) = set {
self = self.set(set);
}
@ -414,7 +414,7 @@ impl PropertyDescriptorBuilder {
match self.inner.kind {
DescriptorKind::Generic => {
self.inner.kind = DescriptorKind::Data {
value: Some(Value::undefined()),
value: Some(JsValue::undefined()),
writable: Some(false),
}
}
@ -423,7 +423,7 @@ impl PropertyDescriptorBuilder {
ref mut writable,
} => {
if value.is_none() {
*value = Some(Value::undefined())
*value = Some(JsValue::undefined())
}
if writable.is_none() {
*writable = Some(false)
@ -434,10 +434,10 @@ impl PropertyDescriptorBuilder {
ref mut get,
} => {
if set.is_none() {
*set = Some(Value::undefined())
*set = Some(JsValue::undefined())
}
if get.is_none() {
*get = Some(Value::undefined())
*get = Some(JsValue::undefined())
}
}
}
@ -541,34 +541,34 @@ impl fmt::Display for PropertyKey {
}
}
impl From<&PropertyKey> for Value {
impl From<&PropertyKey> for JsValue {
#[inline]
fn from(property_key: &PropertyKey) -> Value {
fn from(property_key: &PropertyKey) -> JsValue {
match property_key {
PropertyKey::String(ref string) => string.clone().into(),
PropertyKey::Symbol(ref symbol) => symbol.clone().into(),
PropertyKey::Index(index) => {
if let Ok(integer) = i32::try_from(*index) {
Value::integer(integer)
JsValue::new(integer)
} else {
Value::number(*index)
JsValue::new(*index)
}
}
}
}
}
impl From<PropertyKey> for Value {
impl From<PropertyKey> for JsValue {
#[inline]
fn from(property_key: PropertyKey) -> Value {
fn from(property_key: PropertyKey) -> JsValue {
match property_key {
PropertyKey::String(ref string) => string.clone().into(),
PropertyKey::Symbol(ref symbol) => symbol.clone().into(),
PropertyKey::Index(index) => {
if let Ok(integer) = i32::try_from(index) {
Value::integer(integer)
JsValue::new(integer)
} else {
Value::number(index)
JsValue::new(index)
}
}
}

4
boa/src/syntax/ast/node/array/mod.rs

@ -5,7 +5,7 @@ use crate::{
builtins::{iterable, Array},
exec::Executable,
gc::{Finalize, Trace},
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -39,7 +39,7 @@ pub struct ArrayDecl {
}
impl Executable for ArrayDecl {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("ArrayDecl", "exec");
let array = Array::new_array(context);
let mut elements = Vec::new();

6
boa/src/syntax/ast/node/await_expr/mod.rs

@ -1,7 +1,7 @@
//! Await expression node.
use super::Node;
use crate::{exec::Executable, BoaProfiler, Context, Result, Value};
use crate::{exec::Executable, BoaProfiler, Context, JsValue, Result};
use gc::{Finalize, Trace};
use std::fmt;
@ -27,10 +27,10 @@ pub struct AwaitExpr {
}
impl Executable for AwaitExpr {
fn run(&self, _: &mut Context) -> Result<Value> {
fn run(&self, _: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("AwaitExpression", "exec");
// TODO: Implement AwaitExpr
Ok(Value::Undefined)
Ok(JsValue::undefined())
}
}

6
boa/src/syntax/ast/node/block/mod.rs

@ -6,7 +6,7 @@ use crate::{
exec::Executable,
exec::InterpreterState,
gc::{Finalize, Trace},
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -54,7 +54,7 @@ impl Block {
}
impl Executable for Block {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("Block", "exec");
{
let env = context.get_current_environment();
@ -63,7 +63,7 @@ impl Executable for Block {
// https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation
// The return value is uninitialized, which means it defaults to Value::Undefined
let mut obj = Value::default();
let mut obj = JsValue::default();
for statement in self.items() {
obj = statement.run(context).map_err(|e| {
// No matter how control leaves the Block the LexicalEnvironment is always

6
boa/src/syntax/ast/node/break_node/mod.rs

@ -3,7 +3,7 @@ use crate::{
exec::Executable,
exec::InterpreterState,
gc::{Finalize, Trace},
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -52,12 +52,12 @@ impl Break {
}
impl Executable for Break {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
context
.executor()
.set_current_state(InterpreterState::Break(self.label().map(Box::from)));
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}

9
boa/src/syntax/ast/node/call/mod.rs

@ -4,8 +4,7 @@ use crate::{
exec::InterpreterState,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, Node},
value::Value,
BoaProfiler, Context, Result,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -61,13 +60,13 @@ impl Call {
}
impl Executable for Call {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("Call", "exec");
let (this, func) = match self.expr() {
Node::GetConstField(ref get_const_field) => {
let mut obj = get_const_field.obj().run(context)?;
if !obj.is_object() {
obj = Value::Object(obj.to_object(context)?);
obj = JsValue::Object(obj.to_object(context)?);
}
(
obj.clone(),
@ -77,7 +76,7 @@ impl Executable for Call {
Node::GetField(ref get_field) => {
let mut obj = get_field.obj().run(context)?;
if !obj.is_object() {
obj = Value::Object(obj.to_object(context)?);
obj = JsValue::Object(obj.to_object(context)?);
}
let field = get_field.field().run(context)?;
(

4
boa/src/syntax/ast/node/conditional/conditional_op/mod.rs

@ -2,7 +2,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::Node,
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -60,7 +60,7 @@ impl ConditionalOp {
}
impl Executable for ConditionalOp {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
Ok(if self.cond().run(context)?.to_boolean() {
self.if_true().run(context)?
} else {

6
boa/src/syntax/ast/node/conditional/if_node/mod.rs

@ -2,7 +2,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::Node,
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -79,13 +79,13 @@ impl If {
}
impl Executable for If {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
Ok(if self.cond().run(context)?.to_boolean() {
self.body().run(context)?
} else if let Some(else_e) = self.else_node() {
else_e.run(context)?
} else {
Value::undefined()
JsValue::undefined()
})
}
}

4
boa/src/syntax/ast/node/declaration/arrow_function_decl/mod.rs

@ -3,7 +3,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList},
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -72,7 +72,7 @@ impl ArrowFunctionDecl {
}
impl Executable for ArrowFunctionDecl {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
context.create_function(
"",
self.params().to_vec(),

6
boa/src/syntax/ast/node/declaration/async_function_decl/mod.rs

@ -3,7 +3,7 @@
use crate::{
exec::Executable,
syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList},
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use gc::{Finalize, Trace};
use std::fmt;
@ -79,10 +79,10 @@ impl AsyncFunctionDecl {
}
impl Executable for AsyncFunctionDecl {
fn run(&self, _: &mut Context) -> Result<Value> {
fn run(&self, _: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("AsyncFunctionDecl", "exec");
// TODO: Implement AsyncFunctionDecl
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}

6
boa/src/syntax/ast/node/declaration/async_function_expr/mod.rs

@ -3,7 +3,7 @@
use crate::{
exec::Executable,
syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList},
Context, Result, Value,
Context, JsValue, Result,
};
use gc::{Finalize, Trace};
use std::fmt;
@ -81,9 +81,9 @@ impl AsyncFunctionExpr {
}
impl Executable for AsyncFunctionExpr {
fn run(&self, _: &mut Context) -> Result<Value> {
fn run(&self, _: &mut Context) -> Result<JsValue> {
// TODO: Implement AsyncFunctionExpr
Ok(Value::Undefined)
Ok(JsValue::undefined())
}
}

6
boa/src/syntax/ast/node/declaration/function_decl/mod.rs

@ -4,7 +4,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList},
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -86,7 +86,7 @@ impl FunctionDecl {
}
impl Executable for FunctionDecl {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("FunctionDecl", "exec");
let val = context.create_function(
self.name(),
@ -106,7 +106,7 @@ impl Executable for FunctionDecl {
context.initialize_binding(self.name(), val)?;
}
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}

4
boa/src/syntax/ast/node/declaration/function_expr/mod.rs

@ -3,7 +3,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList},
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -98,7 +98,7 @@ impl FunctionExpr {
}
impl Executable for FunctionExpr {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let val = context.create_function(
self.name().unwrap_or(""),
self.parameters().to_vec(),

8
boa/src/syntax/ast/node/declaration/mod.rs

@ -4,7 +4,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{join_nodes, Identifier, Node},
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -90,7 +90,7 @@ pub enum DeclarationList {
}
impl Executable for DeclarationList {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
for decl in self.as_ref() {
use DeclarationList::*;
let val = match decl.init() {
@ -98,7 +98,7 @@ impl Executable for DeclarationList {
return context.throw_syntax_error("missing = in const declaration")
}
Some(init) => init.run(context)?,
None => Value::undefined(),
None => JsValue::undefined(),
};
if self.is_var() && context.has_binding(decl.name()) {
@ -129,7 +129,7 @@ impl Executable for DeclarationList {
context.initialize_binding(decl.name(), val)?;
}
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}

7
boa/src/syntax/ast/node/field/get_const_field/mod.rs

@ -2,8 +2,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::Node,
value::Value,
Context, Result,
Context, JsValue, Result,
};
use std::fmt;
@ -63,10 +62,10 @@ impl GetConstField {
}
impl Executable for GetConstField {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let mut obj = self.obj().run(context)?;
if !obj.is_object() {
obj = Value::Object(obj.to_object(context)?);
obj = JsValue::Object(obj.to_object(context)?);
}
obj.get_field(self.field(), context)

7
boa/src/syntax/ast/node/field/get_field/mod.rs

@ -2,8 +2,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::Node,
value::Value,
Context, Result,
Context, JsValue, Result,
};
use std::fmt;
@ -62,10 +61,10 @@ impl GetField {
}
impl Executable for GetField {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let mut obj = self.obj().run(context)?;
if !obj.is_object() {
obj = Value::Object(obj.to_object(context)?);
obj = JsValue::Object(obj.to_object(context)?);
}
let field = self.field().run(context)?;

4
boa/src/syntax/ast/node/identifier/mod.rs

@ -4,7 +4,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::Node,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -34,7 +34,7 @@ pub struct Identifier {
}
impl Executable for Identifier {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("Identifier", "exec");
context.get_binding_value(self.as_ref())
}

6
boa/src/syntax/ast/node/iteration/continue_node/mod.rs

@ -2,7 +2,7 @@ use crate::{
exec::{Executable, InterpreterState},
gc::{Finalize, Trace},
syntax::ast::node::Node,
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -46,12 +46,12 @@ impl Continue {
}
impl Executable for Continue {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
context
.executor()
.set_current_state(InterpreterState::Continue(self.label().map(Box::from)));
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}

4
boa/src/syntax/ast/node/iteration/do_while_loop/mod.rs

@ -2,7 +2,7 @@ use crate::{
exec::{Executable, InterpreterState},
gc::{Finalize, Trace},
syntax::ast::node::Node,
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -74,7 +74,7 @@ impl DoWhileLoop {
}
impl Executable for DoWhileLoop {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let mut result;
loop {
result = self.body().run(context)?;

8
boa/src/syntax/ast/node/iteration/for_in_loop/mod.rs

@ -7,7 +7,7 @@ use crate::{
exec::{Executable, InterpreterState},
gc::{Finalize, Trace},
syntax::ast::node::Node,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -80,16 +80,16 @@ impl From<ForInLoop> for Node {
}
impl Executable for ForInLoop {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("ForIn", "exec");
let object = self.expr().run(context)?;
let mut result = Value::undefined();
let mut result = JsValue::undefined();
if object.is_null_or_undefined() {
return Ok(result);
}
let object = object.to_object(context)?;
let for_in_iterator = ForInIterator::create_for_in_iterator(context, Value::from(object));
let for_in_iterator = ForInIterator::create_for_in_iterator(context, JsValue::new(object));
let next_function = for_in_iterator
.get_property("next")
.as_ref()

6
boa/src/syntax/ast/node/iteration/for_loop/mod.rs

@ -3,7 +3,7 @@ use crate::{
exec::{Executable, InterpreterState},
gc::{Finalize, Trace},
syntax::ast::node::Node,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -98,7 +98,7 @@ impl ForLoop {
}
impl Executable for ForLoop {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
// Create the block environment.
let _timer = BoaProfiler::global().start_event("ForLoop", "exec");
{
@ -143,7 +143,7 @@ impl Executable for ForLoop {
// pop the block env
let _ = context.pop_environment();
Ok(Value::undefined())
Ok(JsValue::undefined())
}
}

6
boa/src/syntax/ast/node/iteration/for_of_loop/mod.rs

@ -7,7 +7,7 @@ use crate::{
exec::{Executable, InterpreterState},
gc::{Finalize, Trace},
syntax::ast::node::Node,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -80,11 +80,11 @@ impl From<ForOfLoop> for Node {
}
impl Executable for ForOfLoop {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("ForOf", "exec");
let iterable = self.iterable().run(context)?;
let iterator = get_iterator(context, iterable)?;
let mut result = Value::undefined();
let mut result = JsValue::undefined();
loop {
{

6
boa/src/syntax/ast/node/iteration/while_loop/mod.rs

@ -2,7 +2,7 @@ use crate::{
exec::{Executable, InterpreterState},
gc::{Finalize, Trace},
syntax::ast::node::Node,
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -72,8 +72,8 @@ impl WhileLoop {
}
impl Executable for WhileLoop {
fn run(&self, context: &mut Context) -> Result<Value> {
let mut result = Value::undefined();
fn run(&self, context: &mut Context) -> Result<JsValue> {
let mut result = JsValue::undefined();
while self.cond().run(context)?.to_boolean() {
result = self.body().run(context)?;
match context.executor().get_current_state() {

20
boa/src/syntax/ast/node/mod.rs

@ -50,7 +50,7 @@ use super::Const;
use crate::{
exec::Executable,
gc::{empty_trace, Finalize, Trace},
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::{
cmp::Ordering,
@ -307,23 +307,23 @@ impl Node {
}
impl Executable for Node {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("Executable", "exec");
match *self {
Node::AsyncFunctionDecl(ref decl) => decl.run(context),
Node::AsyncFunctionExpr(ref function_expr) => function_expr.run(context),
Node::AwaitExpr(ref expr) => expr.run(context),
Node::Call(ref call) => call.run(context),
Node::Const(Const::Null) => Ok(Value::null()),
Node::Const(Const::Num(num)) => Ok(Value::rational(num)),
Node::Const(Const::Int(num)) => Ok(Value::integer(num)),
Node::Const(Const::BigInt(ref num)) => Ok(Value::from(num.clone())),
Node::Const(Const::Undefined) => Ok(Value::Undefined),
Node::Const(Const::Null) => Ok(JsValue::null()),
Node::Const(Const::Num(num)) => Ok(JsValue::new(num)),
Node::Const(Const::Int(num)) => Ok(JsValue::new(num)),
Node::Const(Const::BigInt(ref num)) => Ok(JsValue::new(num.clone())),
Node::Const(Const::Undefined) => Ok(JsValue::undefined()),
// we can't move String from Const into value, because const is a garbage collected value
// Which means Drop() get's called on Const, but str will be gone at that point.
// Do Const values need to be garbage collected? We no longer need them once we've generated Values
Node::Const(Const::String(ref value)) => Ok(Value::string(value.to_string())),
Node::Const(Const::Bool(value)) => Ok(Value::boolean(value)),
Node::Const(Const::String(ref value)) => Ok(JsValue::new(value.to_string())),
Node::Const(Const::Bool(value)) => Ok(JsValue::new(value)),
Node::Block(ref block) => block.run(context),
Node::Identifier(ref identifier) => identifier.run(context),
Node::GetConstField(ref get_const_field_node) => get_const_field_node.run(context),
@ -362,7 +362,7 @@ impl Executable for Node {
Node::Try(ref try_node) => try_node.run(context),
Node::Break(ref break_node) => break_node.run(context),
Node::Continue(ref continue_node) => continue_node.run(context),
Node::Empty => Ok(Value::Undefined),
Node::Empty => Ok(JsValue::undefined()),
}
}
}

8
boa/src/syntax/ast/node/new/mod.rs

@ -3,7 +3,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{Call, Node},
value::Value,
value::JsValue,
BoaProfiler, Context, Result,
};
use std::fmt;
@ -48,7 +48,7 @@ impl New {
}
impl Executable for New {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("New", "exec");
let func_object = self.expr().run(context)?;
@ -72,7 +72,9 @@ impl Executable for New {
}
match func_object {
Value::Object(ref object) => object.construct(&v_args, &object.clone().into(), context),
JsValue::Object(ref object) => {
object.construct(&v_args, &object.clone().into(), context)
}
_ => context
.throw_type_error(format!("{} is not a constructor", self.expr().to_string(),)),
}

6
boa/src/syntax/ast/node/object/mod.rs

@ -5,7 +5,7 @@ use crate::{
gc::{Finalize, Trace},
property::PropertyDescriptor,
syntax::ast::node::{join_nodes, MethodDefinitionKind, Node, PropertyDefinition},
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -87,9 +87,9 @@ impl Object {
}
impl Executable for Object {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("object", "exec");
let obj = Value::new_object(context);
let obj = JsValue::new_object(context);
// TODO: Implement the rest of the property types.
for property in self.properties().iter() {

4
boa/src/syntax/ast/node/operator/assign/mod.rs

@ -3,7 +3,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::Node,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -53,7 +53,7 @@ impl Assign {
}
impl Executable for Assign {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("Assign", "exec");
let val = self.rhs().run(context)?;
match self.lhs() {

10
boa/src/syntax/ast/node/operator/bin_op/mod.rs

@ -6,7 +6,7 @@ use crate::{
node::Node,
op::{self, AssignOp, BitOp, CompOp, LogOp, NumOp},
},
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -58,7 +58,7 @@ impl BinOp {
}
/// Runs the assignment operators.
fn run_assign(op: AssignOp, x: Value, y: &Node, context: &mut Context) -> Result<Value> {
fn run_assign(op: AssignOp, x: JsValue, y: &Node, context: &mut Context) -> Result<JsValue> {
match op {
AssignOp::Add => x.add(&y.run(context)?, context),
AssignOp::Sub => x.sub(&y.run(context)?, context),
@ -98,7 +98,7 @@ impl BinOp {
}
impl Executable for BinOp {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
match self.op() {
op::BinOp::Num(op) => {
let x = self.lhs().run(context)?;
@ -127,7 +127,7 @@ impl Executable for BinOp {
op::BinOp::Comp(op) => {
let x = self.lhs().run(context)?;
let y = self.rhs().run(context)?;
Ok(Value::from(match op {
Ok(JsValue::new(match op {
CompOp::Equal => x.equals(&y, context)?,
CompOp::NotEqual => !x.equals(&y, context)?,
CompOp::StrictEqual => x.strict_equals(&y),
@ -213,7 +213,7 @@ impl Executable for BinOp {
v_r_a.set_field(get_const_field.field(), value.clone(), false, context)?;
Ok(value)
}
_ => Ok(Value::undefined()),
_ => Ok(JsValue::undefined()),
},
op::BinOp::Comma => {
self.lhs().run(context)?;

22
boa/src/syntax/ast/node/operator/unary_op/mod.rs

@ -2,7 +2,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::{node::Node, op},
Context, JsBigInt, Result, Value,
Context, JsBigInt, JsValue, Result,
};
use std::fmt;
@ -50,10 +50,10 @@ impl UnaryOp {
}
impl Executable for UnaryOp {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
Ok(match self.op() {
op::UnaryOp::Minus => self.target().run(context)?.neg(context)?,
op::UnaryOp::Plus => Value::from(self.target().run(context)?.to_number(context)?),
op::UnaryOp::Plus => JsValue::new(self.target().run(context)?.to_number(context)?),
op::UnaryOp::IncrementPost => {
let x = self.target().run(context)?;
let ret = x.clone();
@ -81,16 +81,16 @@ impl Executable for UnaryOp {
let expr = self.target().run(context)?;
let old_v = expr.to_numeric(context)?;
match old_v {
Numeric::Number(x) => Value::from(Number::not(x)),
Numeric::BigInt(x) => Value::from(JsBigInt::not(&x)),
Numeric::Number(x) => JsValue::new(Number::not(x)),
Numeric::BigInt(x) => JsValue::new(JsBigInt::not(&x)),
}
}
op::UnaryOp::Void => {
self.target().run(context)?;
Value::undefined()
JsValue::undefined()
}
op::UnaryOp::Delete => match *self.target() {
Node::GetConstField(ref get_const_field) => Value::boolean(
Node::GetConstField(ref get_const_field) => JsValue::new(
get_const_field
.obj()
.run(context)?
@ -103,9 +103,9 @@ impl Executable for UnaryOp {
let res = obj
.to_object(context)?
.__delete__(&field.to_property_key(context)?);
return Ok(Value::boolean(res));
return Ok(JsValue::new(res));
}
Node::Identifier(_) => Value::boolean(false),
Node::Identifier(_) => JsValue::new(false),
Node::ArrayDecl(_)
| Node::Block(_)
| Node::Const(_)
@ -113,10 +113,10 @@ impl Executable for UnaryOp {
| Node::FunctionExpr(_)
| Node::New(_)
| Node::Object(_)
| Node::UnaryOp(_) => Value::boolean(true),
| Node::UnaryOp(_) => JsValue::new(true),
_ => return context.throw_syntax_error(format!("wrong delete argument {}", self)),
},
op::UnaryOp::TypeOf => Value::from(self.target().run(context)?.type_of()),
op::UnaryOp::TypeOf => JsValue::new(self.target().run(context)?.type_of()),
})
}
}

6
boa/src/syntax/ast/node/return_smt/mod.rs

@ -2,7 +2,7 @@ use crate::{
exec::{Executable, InterpreterState},
gc::{Finalize, Trace},
syntax::ast::node::Node,
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -61,10 +61,10 @@ impl Return {
}
impl Executable for Return {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let result = match self.expr() {
Some(v) => v.run(context),
None => Ok(Value::undefined()),
None => Ok(JsValue::undefined()),
};
// Set flag for return
context

4
boa/src/syntax/ast/node/spread/mod.rs

@ -2,7 +2,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::Node,
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -52,7 +52,7 @@ impl Spread {
}
impl Executable for Spread {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
// TODO: for now we can do nothing but return the value as-is
self.val().run(context)
}

6
boa/src/syntax/ast/node/statement_list/mod.rs

@ -4,7 +4,7 @@ use crate::{
exec::{Executable, InterpreterState},
gc::{empty_trace, Finalize, Trace},
syntax::ast::node::Node,
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::{collections::HashSet, fmt, ops::Deref, rc::Rc};
@ -92,12 +92,12 @@ impl StatementList {
}
impl Executable for StatementList {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("StatementList", "exec");
// https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation
// The return value is uninitialized, which means it defaults to Value::Undefined
let mut obj = Value::default();
let mut obj = JsValue::default();
context
.executor()
.set_current_state(InterpreterState::Executing);

6
boa/src/syntax/ast/node/switch/mod.rs

@ -4,7 +4,7 @@ use crate::{
exec::{Executable, InterpreterState},
gc::{Finalize, Trace},
syntax::ast::node::Node,
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -123,9 +123,9 @@ impl Switch {
}
impl Executable for Switch {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let val = self.val().run(context)?;
let mut result = Value::null();
let mut result = JsValue::null();
let mut matched = false;
context
.executor()

14
boa/src/syntax/ast/node/template/mod.rs

@ -1,7 +1,7 @@
//! Template literal node.
use super::Node;
use crate::{builtins::Array, exec::Executable, BoaProfiler, Context, Result, Value};
use crate::{builtins::Array, exec::Executable, BoaProfiler, Context, JsValue, Result};
use gc::{Finalize, Trace};
#[cfg(feature = "deser")]
@ -32,7 +32,7 @@ impl TemplateLit {
}
impl Executable for TemplateLit {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("TemplateLiteral", "exec");
let mut result = String::new();
@ -90,21 +90,21 @@ impl TaggedTemplate {
}
impl Executable for TaggedTemplate {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("TaggedTemplate", "exec");
let template_object = Array::new_array(context);
let raw_array = Array::new_array(context);
for (i, raw) in self.raws.iter().enumerate() {
raw_array.set_field(i, Value::from(raw), false, context)?;
raw_array.set_field(i, JsValue::new(raw.as_ref()), false, context)?;
}
for (i, cooked) in self.cookeds.iter().enumerate() {
if let Some(cooked) = cooked {
template_object.set_field(i, Value::from(cooked), false, context)?;
template_object.set_field(i, JsValue::new(cooked.as_ref()), false, context)?;
} else {
template_object.set_field(i, Value::undefined(), false, context)?;
template_object.set_field(i, JsValue::undefined(), false, context)?;
}
}
template_object.set_field("raw", raw_array, false, context)?;
@ -113,7 +113,7 @@ impl Executable for TaggedTemplate {
Node::GetConstField(ref get_const_field) => {
let mut obj = get_const_field.obj().run(context)?;
if !obj.is_object() {
obj = Value::Object(obj.to_object(context)?);
obj = JsValue::Object(obj.to_object(context)?);
}
(
obj.clone(),

4
boa/src/syntax/ast/node/throw/mod.rs

@ -2,7 +2,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::Node,
Context, Result, Value,
Context, JsValue, Result,
};
use std::fmt;
@ -50,7 +50,7 @@ impl Throw {
impl Executable for Throw {
#[inline]
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
Err(self.expr().run(context)?)
}
}

4
boa/src/syntax/ast/node/try_node/mod.rs

@ -6,7 +6,7 @@ use crate::{
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{Block, Identifier, Node},
BoaProfiler, Context, Result, Value,
BoaProfiler, Context, JsValue, Result,
};
use std::fmt;
@ -95,7 +95,7 @@ impl Try {
}
impl Executable for Try {
fn run(&self, context: &mut Context) -> Result<Value> {
fn run(&self, context: &mut Context) -> Result<JsValue> {
let _timer = BoaProfiler::global().start_event("Try", "exec");
let res = self.block().run(context).map_or_else(
|err| {

132
boa/src/value/conversions.rs

@ -1,60 +1,36 @@
use super::*;
use std::convert::TryFrom;
impl From<&Value> for Value {
impl From<&JsValue> for JsValue {
#[inline]
fn from(value: &Value) -> Self {
fn from(value: &JsValue) -> Self {
value.clone()
}
}
impl From<String> for Value {
impl<T> From<T> for JsValue
where
T: Into<JsString>,
{
#[inline]
fn from(value: String) -> Self {
fn from(value: T) -> Self {
let _timer = BoaProfiler::global().start_event("From<String>", "value");
Self::string(value)
}
}
impl From<Box<str>> for Value {
#[inline]
fn from(value: Box<str>) -> Self {
Self::string(String::from(value))
}
}
impl From<&str> for Value {
#[inline]
fn from(value: &str) -> Value {
Value::string(value)
}
}
impl From<&Box<str>> for Value {
#[inline]
fn from(value: &Box<str>) -> Self {
Self::string(value.as_ref())
Self::String(value.into())
}
}
impl From<char> for Value {
impl From<char> for JsValue {
#[inline]
fn from(value: char) -> Self {
Value::string(value.to_string())
JsValue::new(value.to_string())
}
}
impl From<JsString> for Value {
#[inline]
fn from(value: JsString) -> Self {
Value::String(value)
}
}
impl From<JsSymbol> for Value {
impl From<JsSymbol> for JsValue {
#[inline]
fn from(value: JsSymbol) -> Self {
Value::Symbol(value)
JsValue::Symbol(value)
}
}
@ -67,81 +43,86 @@ impl Display for TryFromCharError {
}
}
impl From<f64> for Value {
impl From<f64> for JsValue {
#[allow(clippy::float_cmp)]
#[inline]
fn from(value: f64) -> Self {
Self::rational(value)
// if value as i32 as f64 == value {
// JsValue::Integer(value as i32)
// } else {
JsValue::Rational(value)
// }
}
}
impl From<u32> for Value {
impl From<u32> for JsValue {
#[inline]
fn from(value: u32) -> Value {
fn from(value: u32) -> JsValue {
if let Ok(integer) = i32::try_from(value) {
Value::integer(integer)
JsValue::Integer(integer)
} else {
Value::rational(value)
JsValue::Rational(value.into())
}
}
}
impl From<i32> for Value {
impl From<i32> for JsValue {
#[inline]
fn from(value: i32) -> Value {
Value::integer(value)
fn from(value: i32) -> JsValue {
JsValue::Integer(value)
}
}
impl From<JsBigInt> for Value {
impl From<JsBigInt> for JsValue {
#[inline]
fn from(value: JsBigInt) -> Self {
Value::BigInt(value)
JsValue::BigInt(value)
}
}
impl From<usize> for Value {
impl From<usize> for JsValue {
#[inline]
fn from(value: usize) -> Value {
fn from(value: usize) -> JsValue {
if let Ok(value) = i32::try_from(value) {
Value::integer(value)
JsValue::Integer(value)
} else {
Value::rational(value as f64)
JsValue::Rational(value as f64)
}
}
}
impl From<u64> for Value {
impl From<u64> for JsValue {
#[inline]
fn from(value: u64) -> Value {
fn from(value: u64) -> JsValue {
if let Ok(value) = i32::try_from(value) {
Value::integer(value)
JsValue::Integer(value)
} else {
Value::rational(value as f64)
JsValue::Rational(value as f64)
}
}
}
impl From<i64> for Value {
impl From<i64> for JsValue {
#[inline]
fn from(value: i64) -> Value {
fn from(value: i64) -> JsValue {
if let Ok(value) = i32::try_from(value) {
Value::integer(value)
JsValue::Integer(value)
} else {
Value::rational(value as f64)
JsValue::Rational(value as f64)
}
}
}
impl From<bool> for Value {
impl From<bool> for JsValue {
#[inline]
fn from(value: bool) -> Self {
Value::boolean(value)
JsValue::Boolean(value)
}
}
impl<T> From<&[T]> for Value
impl<T> From<&[T]> for JsValue
where
T: Clone + Into<Value>,
T: Clone + Into<JsValue>,
{
fn from(value: &[T]) -> Self {
let mut array = Object::default();
@ -159,9 +140,9 @@ where
}
}
impl<T> From<Vec<T>> for Value
impl<T> From<Vec<T>> for JsValue
where
T: Into<Value>,
T: Into<JsValue>,
{
fn from(value: Vec<T>) -> Self {
let mut array = Object::default();
@ -175,22 +156,23 @@ where
.configurable(true),
);
}
Value::from(array)
JsValue::new(array)
}
}
impl From<Object> for Value {
impl From<Object> for JsValue {
#[inline]
fn from(object: Object) -> Self {
let _timer = BoaProfiler::global().start_event("From<Object>", "value");
Value::object(object)
JsValue::Object(GcObject::new(object))
}
}
impl From<GcObject> for Value {
impl From<GcObject> for JsValue {
#[inline]
fn from(object: GcObject) -> Self {
let _timer = BoaProfiler::global().start_event("From<GcObject>", "value");
Value::Object(object)
JsValue::Object(object)
}
}
@ -204,22 +186,22 @@ impl Display for TryFromObjectError {
}
}
impl From<()> for Value {
impl From<()> for JsValue {
#[inline]
fn from(_: ()) -> Self {
Value::null()
JsValue::null()
}
}
impl<T> From<Option<T>> for Value
impl<T> From<Option<T>> for JsValue
where
T: Into<Value>,
T: Into<JsValue>,
{
#[inline]
fn from(value: Option<T>) -> Self {
match value {
Some(value) => value.into(),
None => Value::null(),
None => JsValue::null(),
}
}
}

40
boa/src/value/display.rs

@ -3,7 +3,7 @@ use super::*;
/// This object is used for displaying a `Value`.
#[derive(Debug, Clone, Copy)]
pub struct ValueDisplay<'value> {
pub(super) value: &'value Value,
pub(super) value: &'value JsValue,
}
/// A helper macro for printing objects
@ -80,10 +80,10 @@ macro_rules! print_obj_value {
};
}
pub(crate) fn log_string_from(x: &Value, print_internals: bool, print_children: bool) -> String {
pub(crate) fn log_string_from(x: &JsValue, print_internals: bool, print_children: bool) -> String {
match x {
// We don't want to print private (compiler) or prototype properties
Value::Object(ref v) => {
JsValue::Object(ref v) => {
// Can use the private "type" field of an Object to match on
// which type of Object it represents for special printing
match v.borrow().data {
@ -122,7 +122,7 @@ pub(crate) fn log_string_from(x: &Value, print_internals: bool, print_children:
.as_ref()
// FIXME: handle accessor descriptors
.and_then(|p| p.value())
.unwrap_or(&Value::Undefined),
.unwrap_or(&JsValue::Undefined),
print_internals,
false,
)
@ -177,13 +177,13 @@ pub(crate) fn log_string_from(x: &Value, print_internals: bool, print_children:
_ => display_obj(x, print_internals),
}
}
Value::Symbol(ref symbol) => symbol.to_string(),
JsValue::Symbol(ref symbol) => symbol.to_string(),
_ => format!("{}", x.display()),
}
}
/// A helper function for specifically printing object values
pub(crate) fn display_obj(v: &Value, print_internals: bool) -> String {
pub(crate) fn display_obj(v: &JsValue, print_internals: bool) -> String {
// A simple helper for getting the address of a value
// TODO: Find a more general place for this, as it can be used in other situations as well
fn address_of<T>(t: &T) -> usize {
@ -195,20 +195,20 @@ pub(crate) fn display_obj(v: &Value, print_internals: bool) -> String {
// in-memory address in this set
let mut encounters = HashSet::new();
if let Value::Object(object) = v {
if let JsValue::Object(object) = v {
if object.borrow().is_error() {
let name = v
.get_property("name")
.as_ref()
.and_then(|d| d.value())
.unwrap_or(&Value::Undefined)
.unwrap_or(&JsValue::Undefined)
.display()
.to_string();
let message = v
.get_property("message")
.as_ref()
.and_then(|d| d.value())
.unwrap_or(&Value::Undefined)
.unwrap_or(&JsValue::Undefined)
.display()
.to_string();
return format!("{}: {}", name, message);
@ -216,12 +216,12 @@ pub(crate) fn display_obj(v: &Value, print_internals: bool) -> String {
}
fn display_obj_internal(
data: &Value,
data: &JsValue,
encounters: &mut HashSet<usize>,
indent: usize,
print_internals: bool,
) -> String {
if let Value::Object(ref v) = *data {
if let JsValue::Object(ref v) = *data {
// The in-memory address of the current object
let addr = address_of(v.as_ref());
@ -261,18 +261,18 @@ pub(crate) fn display_obj(v: &Value, print_internals: bool) -> String {
impl Display for ValueDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.value {
Value::Null => write!(f, "null"),
Value::Undefined => write!(f, "undefined"),
Value::Boolean(v) => write!(f, "{}", v),
Value::Symbol(ref symbol) => match symbol.description() {
JsValue::Null => write!(f, "null"),
JsValue::Undefined => write!(f, "undefined"),
JsValue::Boolean(v) => write!(f, "{}", v),
JsValue::Symbol(ref symbol) => match symbol.description() {
Some(description) => write!(f, "Symbol({})", description),
None => write!(f, "Symbol()"),
},
Value::String(ref v) => write!(f, "\"{}\"", v),
Value::Rational(v) => format_rational(*v, f),
Value::Object(_) => write!(f, "{}", log_string_from(self.value, true, true)),
Value::Integer(v) => write!(f, "{}", v),
Value::BigInt(ref num) => write!(f, "{}n", num),
JsValue::String(ref v) => write!(f, "\"{}\"", v),
JsValue::Rational(v) => format_rational(*v, f),
JsValue::Object(_) => write!(f, "{}", log_string_from(self.value, true, true)),
JsValue::Integer(v) => write!(f, "{}", v),
JsValue::BigInt(ref num) => write!(f, "{}n", num),
}
}
}

46
boa/src/value/equality.rs

@ -1,7 +1,7 @@
use super::*;
use crate::{builtins::Number, Context};
impl Value {
impl JsValue {
/// Strict equality comparison.
///
/// This method is executed when doing strict equality comparisons with the `===` operator.
@ -80,10 +80,10 @@ impl Value {
},
// 8. If Type(x) is Boolean, return the result of the comparison ! ToNumber(x) == y.
(Self::Boolean(x), _) => return other.equals(&Value::from(*x as i32), context),
(Self::Boolean(x), _) => return other.equals(&JsValue::new(*x as i32), context),
// 9. If Type(y) is Boolean, return the result of the comparison x == ! ToNumber(y).
(_, Self::Boolean(y)) => return self.equals(&Value::from(*y as i32), context),
(_, Self::Boolean(y)) => return self.equals(&JsValue::new(*y as i32), context),
// 10. If Type(x) is either String, Number, BigInt, or Symbol and Type(y) is Object, return the result
// of the comparison x == ? ToPrimitive(y).
@ -119,7 +119,7 @@ impl Value {
/// - [ECMAScript][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-samevalue
pub fn same_value(x: &Value, y: &Value) -> bool {
pub fn same_value(x: &JsValue, y: &JsValue) -> bool {
// 1. If Type(x) is different from Type(y), return false.
if x.get_type() != y.get_type() {
return false;
@ -128,11 +128,11 @@ impl Value {
match (x, y) {
// 2. If Type(x) is Number or BigInt, then
// a. Return ! Type(x)::SameValue(x, y).
(Value::BigInt(x), Value::BigInt(y)) => JsBigInt::same_value(x, y),
(Value::Rational(x), Value::Rational(y)) => Number::same_value(*x, *y),
(Value::Rational(x), Value::Integer(y)) => Number::same_value(*x, f64::from(*y)),
(Value::Integer(x), Value::Rational(y)) => Number::same_value(f64::from(*x), *y),
(Value::Integer(x), Value::Integer(y)) => x == y,
(JsValue::BigInt(x), JsValue::BigInt(y)) => JsBigInt::same_value(x, y),
(JsValue::Rational(x), JsValue::Rational(y)) => Number::same_value(*x, *y),
(JsValue::Rational(x), JsValue::Integer(y)) => Number::same_value(*x, f64::from(*y)),
(JsValue::Integer(x), JsValue::Rational(y)) => Number::same_value(f64::from(*x), *y),
(JsValue::Integer(x), JsValue::Integer(y)) => x == y,
// 3. Return ! SameValueNonNumeric(x, y).
(_, _) => Self::same_value_non_numeric(x, y),
@ -148,7 +148,7 @@ impl Value {
/// - [ECMAScript][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-samevaluezero
pub fn same_value_zero(x: &Value, y: &Value) -> bool {
pub fn same_value_zero(x: &JsValue, y: &JsValue) -> bool {
if x.get_type() != y.get_type() {
return false;
}
@ -156,26 +156,30 @@ impl Value {
match (x, y) {
// 2. If Type(x) is Number or BigInt, then
// a. Return ! Type(x)::SameValueZero(x, y).
(Value::BigInt(x), Value::BigInt(y)) => JsBigInt::same_value_zero(x, y),
(JsValue::BigInt(x), JsValue::BigInt(y)) => JsBigInt::same_value_zero(x, y),
(Value::Rational(x), Value::Rational(y)) => Number::same_value_zero(*x, *y),
(Value::Rational(x), Value::Integer(y)) => Number::same_value_zero(*x, f64::from(*y)),
(Value::Integer(x), Value::Rational(y)) => Number::same_value_zero(f64::from(*x), *y),
(Value::Integer(x), Value::Integer(y)) => x == y,
(JsValue::Rational(x), JsValue::Rational(y)) => Number::same_value_zero(*x, *y),
(JsValue::Rational(x), JsValue::Integer(y)) => {
Number::same_value_zero(*x, f64::from(*y))
}
(JsValue::Integer(x), JsValue::Rational(y)) => {
Number::same_value_zero(f64::from(*x), *y)
}
(JsValue::Integer(x), JsValue::Integer(y)) => x == y,
// 3. Return ! SameValueNonNumeric(x, y).
(_, _) => Self::same_value_non_numeric(x, y),
}
}
fn same_value_non_numeric(x: &Value, y: &Value) -> bool {
fn same_value_non_numeric(x: &JsValue, y: &JsValue) -> bool {
debug_assert!(x.get_type() == y.get_type());
match (x, y) {
(Value::Null, Value::Null) | (Value::Undefined, Value::Undefined) => true,
(Value::String(ref x), Value::String(ref y)) => x == y,
(Value::Boolean(x), Value::Boolean(y)) => x == y,
(Value::Object(ref x), Value::Object(ref y)) => GcObject::equals(x, y),
(Value::Symbol(ref x), Value::Symbol(ref y)) => x == y,
(JsValue::Null, JsValue::Null) | (JsValue::Undefined, JsValue::Undefined) => true,
(JsValue::String(ref x), JsValue::String(ref y)) => x == y,
(JsValue::Boolean(x), JsValue::Boolean(y)) => x == y,
(JsValue::Object(ref x), JsValue::Object(ref y)) => GcObject::equals(x, y),
(JsValue::Symbol(ref x), JsValue::Symbol(ref y)) => x == y,
_ => false,
}
}

6
boa/src/value/hash.rs

@ -3,13 +3,13 @@ use super::*;
use crate::builtins::Number;
use std::hash::{Hash, Hasher};
impl PartialEq for Value {
impl PartialEq for JsValue {
fn eq(&self, other: &Self) -> bool {
Self::same_value_zero(self, other)
}
}
impl Eq for Value {}
impl Eq for JsValue {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct UndefinedHashable;
@ -36,7 +36,7 @@ impl Hash for RationalHashable {
}
}
impl Hash for Value {
impl Hash for JsValue {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Self::Undefined => UndefinedHashable.hash(state),

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save