Skip to content

Commit 3b70830

Browse files
authored
Merge ecd65b2 into d2939ff
2 parents d2939ff + ecd65b2 commit 3b70830

File tree

30 files changed

+2097
-1752
lines changed

30 files changed

+2097
-1752
lines changed

boa/src/builtins/array/mod.rs

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mod tests;
1515
use super::function::{make_builtin_fn, make_constructor_fn};
1616
use crate::{
1717
builtins::{
18-
object::{ObjectKind, INSTANCE_PROTOTYPE, PROTOTYPE},
18+
object::{ObjectData, INSTANCE_PROTOTYPE, PROTOTYPE},
1919
property::Property,
2020
value::{same_value_zero, ResultValue, Value, ValueData},
2121
},
@@ -25,14 +25,19 @@ use crate::{
2525
use std::{
2626
borrow::Borrow,
2727
cmp::{max, min},
28-
ops::Deref,
2928
};
3029

3130
/// JavaScript `Array` built-in implementation.
3231
#[derive(Debug, Clone, Copy)]
3332
pub(crate) struct Array;
3433

3534
impl Array {
35+
/// The name of the object.
36+
pub(crate) const NAME: &'static str = "Array";
37+
38+
/// The amount of arguments this function object takes.
39+
pub(crate) const LENGTH: usize = 1;
40+
3641
/// Creates a new `Array` instance.
3742
pub(crate) fn new_array(interpreter: &Interpreter) -> ResultValue {
3843
let array = Value::new_object(Some(
@@ -42,7 +47,7 @@ impl Array {
4247
.get_global_object()
4348
.expect("Could not get global object"),
4449
));
45-
array.set_kind(ObjectKind::Array);
50+
array.set_data(ObjectData::Array);
4651
array.borrow().set_internal_slot(
4752
INSTANCE_PROTOTYPE,
4853
interpreter
@@ -117,7 +122,7 @@ impl Array {
117122
this.set_internal_slot(INSTANCE_PROTOTYPE, prototype);
118123
// This value is used by console.log and other routines to match Object type
119124
// to its Javascript Identifier (global constructor method name)
120-
this.set_kind(ObjectKind::Array);
125+
this.set_data(ObjectData::Array);
121126

122127
// add our arguments in
123128
let mut length = args.len() as i32;
@@ -167,25 +172,9 @@ impl Array {
167172
args: &[Value],
168173
_interpreter: &mut Interpreter,
169174
) -> ResultValue {
170-
let value_true = Value::boolean(true);
171-
let value_false = Value::boolean(false);
172-
173-
match args.get(0) {
174-
Some(arg) => {
175-
match arg.data() {
176-
// 1.
177-
ValueData::Object(ref obj) => {
178-
// 2.
179-
if (*obj).deref().borrow().kind == ObjectKind::Array {
180-
return Ok(value_true);
181-
}
182-
Ok(value_false)
183-
}
184-
// 3.
185-
_ => Ok(value_false),
186-
}
187-
}
188-
None => Ok(value_false),
175+
match args.get(0).and_then(|x| x.as_object()) {
176+
Some(object) => Ok(Value::from(object.is_array())),
177+
None => Ok(Value::from(false)),
189178
}
190179
}
191180

@@ -1008,7 +997,7 @@ impl Array {
1008997
let prototype = Value::new_object(None);
1009998
let length = Property::default().value(Value::from(0));
1010999

1011-
prototype.set_property_slice("length", length);
1000+
prototype.set_property("length", length);
10121001

10131002
make_builtin_fn(Self::concat, "concat", &prototype, 1);
10141003
make_builtin_fn(Self::push, "push", &prototype, 1);
@@ -1031,7 +1020,14 @@ impl Array {
10311020
make_builtin_fn(Self::slice, "slice", &prototype, 2);
10321021
make_builtin_fn(Self::some, "some", &prototype, 2);
10331022

1034-
let array = make_constructor_fn("Array", 1, Self::make_array, global, prototype, true);
1023+
let array = make_constructor_fn(
1024+
Self::NAME,
1025+
Self::LENGTH,
1026+
Self::make_array,
1027+
global,
1028+
prototype,
1029+
true,
1030+
);
10351031

10361032
// Static Methods
10371033
make_builtin_fn(Self::is_array, "isArray", &array, 1);
@@ -1041,8 +1037,9 @@ impl Array {
10411037

10421038
/// Initialise the `Array` object on the global object.
10431039
#[inline]
1044-
pub(crate) fn init(global: &Value) {
1045-
let _timer = BoaProfiler::global().start_event("array", "init");
1046-
global.set_field("Array", Self::create(global));
1040+
pub(crate) fn init(global: &Value) -> (&str, Value) {
1041+
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
1042+
1043+
(Self::NAME, Self::create(global))
10471044
}
10481045
}

boa/src/builtins/bigint/mod.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use crate::{
1616
builtins::{
1717
function::{make_builtin_fn, make_constructor_fn},
18+
object::ObjectData,
1819
value::{ResultValue, Value, ValueData},
1920
},
2021
exec::Interpreter,
@@ -43,6 +44,12 @@ mod tests;
4344
pub struct BigInt(num_bigint::BigInt);
4445

4546
impl BigInt {
47+
/// The name of the object.
48+
pub(crate) const NAME: &'static str = "BigInt";
49+
50+
/// The amount of arguments this function object takes.
51+
pub(crate) const LENGTH: usize = 1;
52+
4653
/// The abstract operation thisBigIntValue takes argument value.
4754
///
4855
/// The phrase “this BigInt value” within the specification of a method refers to the
@@ -62,18 +69,16 @@ impl BigInt {
6269
// 2. If Type(value) is Object and value has a [[BigIntData]] internal slot, then
6370
// a. Assert: Type(value.[[BigIntData]]) is BigInt.
6471
// b. Return value.[[BigIntData]].
65-
ValueData::Object(_) => {
66-
let bigint = value.get_internal_slot("BigIntData");
67-
if let ValueData::BigInt(bigint) = bigint.data() {
72+
ValueData::Object(ref object) => {
73+
if let ObjectData::BigInt(ref bigint) = object.borrow().data {
6874
return Ok(bigint.clone());
6975
}
7076
}
7177
_ => {}
7278
}
7379

7480
// 3. Throw a TypeError exception.
75-
ctx.throw_type_error("'this' is not a BigInt")?;
76-
unreachable!();
81+
Err(ctx.construct_type_error("'this' is not a BigInt"))
7782
}
7883

7984
/// `BigInt()`
@@ -86,16 +91,12 @@ impl BigInt {
8691
///
8792
/// [spec]: https://tc39.es/ecma262/#sec-bigint-objects
8893
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/BigInt
89-
pub(crate) fn make_bigint(
90-
_this: &mut Value,
91-
args: &[Value],
92-
ctx: &mut Interpreter,
93-
) -> ResultValue {
94+
pub(crate) fn make_bigint(_: &mut Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
9495
let data = match args.get(0) {
95-
Some(ref value) => Value::from(ctx.to_bigint(value)?),
96-
None => Value::from(Self::from(0)),
96+
Some(ref value) => ctx.to_bigint(value)?,
97+
None => Self::from(0),
9798
};
98-
Ok(data)
99+
Ok(Value::from(data))
99100
}
100101

101102
/// `BigInt.prototype.toString( [radix] )`
@@ -213,12 +214,18 @@ impl BigInt {
213214
/// Create a new `Number` object
214215
pub(crate) fn create(global: &Value) -> Value {
215216
let prototype = Value::new_object(Some(global));
216-
prototype.set_internal_slot("BigIntData", Value::from(Self::from(0)));
217217

218218
make_builtin_fn(Self::to_string, "toString", &prototype, 1);
219219
make_builtin_fn(Self::value_of, "valueOf", &prototype, 0);
220220

221-
let big_int = make_constructor_fn("BigInt", 1, Self::make_bigint, global, prototype, false);
221+
let big_int = make_constructor_fn(
222+
Self::NAME,
223+
Self::LENGTH,
224+
Self::make_bigint,
225+
global,
226+
prototype,
227+
false,
228+
);
222229

223230
make_builtin_fn(Self::as_int_n, "asIntN", &big_int, 2);
224231
make_builtin_fn(Self::as_uint_n, "asUintN", &big_int, 2);
@@ -228,9 +235,10 @@ impl BigInt {
228235

229236
/// Initialise the `BigInt` object on the global object.
230237
#[inline]
231-
pub(crate) fn init(global: &Value) {
232-
let _timer = BoaProfiler::global().start_event("bigint", "init");
233-
global.set_field("BigInt", Self::create(global));
238+
pub(crate) fn init(global: &Value) -> (&str, Value) {
239+
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
240+
241+
(Self::NAME, Self::create(global))
234242
}
235243
}
236244

boa/src/builtins/boolean/mod.rs

Lines changed: 43 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,45 @@ mod tests;
1515
use super::function::{make_builtin_fn, make_constructor_fn};
1616
use crate::{
1717
builtins::{
18-
object::{internal_methods_trait::ObjectInternalMethods, ObjectKind},
18+
object::ObjectData,
1919
value::{ResultValue, Value, ValueData},
2020
},
2121
exec::Interpreter,
2222
BoaProfiler,
2323
};
24-
use std::{borrow::Borrow, ops::Deref};
2524

2625
/// Boolean implementation.
2726
#[derive(Debug, Clone, Copy)]
2827
pub(crate) struct Boolean;
2928

3029
impl Boolean {
30+
/// The name of the object.
31+
pub(crate) const NAME: &'static str = "Boolean";
32+
33+
/// The amount of arguments this function object takes.
34+
pub(crate) const LENGTH: usize = 1;
35+
36+
/// An Utility function used to get the internal [[BooleanData]].
37+
///
38+
/// More information:
39+
/// - [ECMAScript reference][spec]
40+
///
41+
/// [spec]: https://tc39.es/ecma262/#sec-thisbooleanvalue
42+
fn this_boolean_value(value: &Value, ctx: &mut Interpreter) -> Result<bool, Value> {
43+
match value.data() {
44+
ValueData::Boolean(boolean) => return Ok(*boolean),
45+
ValueData::Object(ref object) => {
46+
let object = object.borrow();
47+
if let Some(boolean) = object.as_boolean() {
48+
return Ok(boolean);
49+
}
50+
}
51+
_ => {}
52+
}
53+
54+
Err(ctx.construct_type_error("'this' is not a boolean"))
55+
}
56+
3157
/// `[[Construct]]` Create a new boolean object
3258
///
3359
/// `[[Call]]` Creates a new boolean primitive
@@ -36,19 +62,11 @@ impl Boolean {
3662
args: &[Value],
3763
_: &mut Interpreter,
3864
) -> ResultValue {
39-
this.set_kind(ObjectKind::Boolean);
40-
4165
// Get the argument, if any
42-
if let Some(ref value) = args.get(0) {
43-
this.set_internal_slot("BooleanData", Self::to_boolean(value));
44-
} else {
45-
this.set_internal_slot("BooleanData", Self::to_boolean(&Value::from(false)));
46-
}
66+
let data = args.get(0).map(|x| x.to_boolean()).unwrap_or(false);
67+
this.set_data(ObjectData::Boolean(data));
4768

48-
match args.get(0) {
49-
Some(ref value) => Ok(Self::to_boolean(value)),
50-
None => Ok(Self::to_boolean(&Value::from(false))),
51-
}
69+
Ok(Value::from(data))
5270
}
5371

5472
/// The `toString()` method returns a string representing the specified `Boolean` object.
@@ -60,9 +78,9 @@ impl Boolean {
6078
/// [spec]: https://tc39.es/ecma262/#sec-boolean-object
6179
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString
6280
#[allow(clippy::wrong_self_convention)]
63-
pub(crate) fn to_string(this: &mut Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
64-
let b = Self::this_boolean_value(this);
65-
Ok(Value::from(b.to_string()))
81+
pub(crate) fn to_string(this: &mut Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
82+
let boolean = Self::this_boolean_value(this, ctx)?;
83+
Ok(Value::from(boolean.to_string()))
6684
}
6785

6886
/// The valueOf() method returns the primitive value of a `Boolean` object.
@@ -73,52 +91,23 @@ impl Boolean {
7391
///
7492
/// [spec]: https://tc39.es/ecma262/#sec-boolean.prototype.valueof
7593
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/valueOf
76-
pub(crate) fn value_of(this: &mut Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
77-
Ok(Self::this_boolean_value(this))
78-
}
79-
80-
// === Utility Functions ===
81-
/// [toBoolean](https://tc39.es/ecma262/#sec-toboolean)
82-
/// Creates a new boolean value from the input
83-
#[allow(clippy::wrong_self_convention)]
84-
pub(crate) fn to_boolean(value: &Value) -> Value {
85-
match *value.deref().borrow() {
86-
ValueData::Object(_) => Value::from(true),
87-
ValueData::String(ref s) if !s.is_empty() => Value::from(true),
88-
ValueData::Rational(n) if n != 0.0 && !n.is_nan() => Value::from(true),
89-
ValueData::Integer(n) if n != 0 => Value::from(true),
90-
ValueData::Boolean(v) => Value::from(v),
91-
_ => Value::from(false),
92-
}
93-
}
94-
95-
/// An Utility function used to get the internal BooleanData.
96-
///
97-
/// More information:
98-
/// - [ECMAScript reference][spec]
99-
///
100-
/// [spec]: https://tc39.es/ecma262/#sec-thisbooleanvalue
101-
pub(crate) fn this_boolean_value(value: &Value) -> Value {
102-
match *value.deref().borrow() {
103-
ValueData::Boolean(v) => Value::from(v),
104-
ValueData::Object(ref v) => (v).deref().borrow().get_internal_slot("BooleanData"),
105-
_ => Value::from(false),
106-
}
94+
#[inline]
95+
pub(crate) fn value_of(this: &mut Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue {
96+
Ok(Value::from(Self::this_boolean_value(this, ctx)?))
10797
}
10898

10999
/// Create a new `Boolean` object.
110100
pub(crate) fn create(global: &Value) -> Value {
111101
// Create Prototype
112102
// https://tc39.es/ecma262/#sec-properties-of-the-boolean-prototype-object
113103
let prototype = Value::new_object(Some(global));
114-
prototype.set_internal_slot("BooleanData", Self::to_boolean(&Value::from(false)));
115104

116105
make_builtin_fn(Self::to_string, "toString", &prototype, 0);
117106
make_builtin_fn(Self::value_of, "valueOf", &prototype, 0);
118107

119108
make_constructor_fn(
120-
"Boolean",
121-
1,
109+
Self::NAME,
110+
Self::LENGTH,
122111
Self::construct_boolean,
123112
global,
124113
prototype,
@@ -128,8 +117,9 @@ impl Boolean {
128117

129118
/// Initialise the `Boolean` object on the global object.
130119
#[inline]
131-
pub(crate) fn init(global: &Value) {
132-
let _timer = BoaProfiler::global().start_event("boolean", "init");
133-
global.set_field("Boolean", Self::create(global));
120+
pub(crate) fn init(global: &Value) -> (&str, Value) {
121+
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");
122+
123+
(Self::NAME, Self::create(global))
134124
}
135125
}

boa/src/builtins/console/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,8 @@ pub fn create(global: &Value) -> Value {
554554

555555
/// Initialise the `console` object on the global object.
556556
#[inline]
557-
pub fn init(global: &Value) {
557+
pub fn init(global: &Value) -> (&str, Value) {
558558
let _timer = BoaProfiler::global().start_event("console", "init");
559-
global.set_field("console", create(global));
559+
560+
("console", create(global))
560561
}

0 commit comments

Comments
 (0)