Skip to content

Commit

Permalink
Merge 7c326f2 into 07ff7a8
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat authored Oct 1, 2020
2 parents 07ff7a8 + 7c326f2 commit 65d95ae
Show file tree
Hide file tree
Showing 31 changed files with 1,613 additions and 1,654 deletions.
220 changes: 95 additions & 125 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
#[cfg(test)]
mod tests;

use super::function::{make_builtin_fn, make_constructor_fn};
use crate::{
object::{ObjectData, PROTOTYPE},
builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE},
property::{Attribute, Property},
value::{same_value_zero, Value},
BoaProfiler, Context, Result,
Expand All @@ -25,17 +25,103 @@ use std::cmp::{max, min};
#[derive(Debug, Clone, Copy)]
pub(crate) struct Array;

impl BuiltIn for Array {
const NAME: &'static str = "Array";

fn attribute() -> Attribute {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}

fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");

let array = ConstructorBuilder::with_standard_object(
context,
Self::constructor,
context.standard_objects().array_object().clone(),
)
.name(Self::NAME)
.length(Self::LENGTH)
.property("length", 0, Attribute::all())
.method(Self::concat, "concat", 1)
.method(Self::push, "push", 1)
.method(Self::index_of, "indexOf", 1)
.method(Self::last_index_of, "lastIndexOf", 1)
.method(Self::includes_value, "includes", 1)
.method(Self::map, "map", 1)
.method(Self::fill, "fill", 1)
.method(Self::for_each, "forEach", 1)
.method(Self::filter, "filter", 1)
.method(Self::pop, "pop", 0)
.method(Self::join, "join", 1)
.method(Self::to_string, "toString", 0)
.method(Self::reverse, "reverse", 0)
.method(Self::shift, "shift", 0)
.method(Self::unshift, "unshift", 1)
.method(Self::every, "every", 1)
.method(Self::find, "find", 1)
.method(Self::find_index, "findIndex", 1)
.method(Self::slice, "slice", 2)
.method(Self::some, "some", 2)
.method(Self::reduce, "reduce", 2)
.method(Self::reduce_right, "reduceRight", 2)
// Static Methods
.static_method(Self::is_array, "isArray", 1)
.build();

(Self::NAME, array.into(), Self::attribute())
}
}

impl Array {
/// The name of the object.
pub(crate) const NAME: &'static str = "Array";
const LENGTH: usize = 1;

fn constructor(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
// Set Prototype
let prototype = context.standard_objects().array_object().prototype();

this.as_object_mut()
.expect("this should be an array object")
.set_prototype_instance(prototype.into());
// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::Array);

// add our arguments in
let mut length = args.len() as i32;
match args.len() {
1 if args[0].is_integer() => {
length = args[0].as_number().unwrap() as i32;
// TODO: It should not create an array of undefineds, but an empty array ("holy" array in V8) with length `n`.
for n in 0..length {
this.set_field(n, Value::undefined());
}
}
1 if args[0].is_double() => {
return context.throw_range_error("invalid array length");
}
_ => {
for (n, value) in args.iter().enumerate() {
this.set_field(n, value.clone());
}
}
}

/// The amount of arguments this function object takes.
pub(crate) const LENGTH: usize = 1;
// finally create length property
let length = Property::data_descriptor(
length.into(),
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
);

this.set_property("length".to_string(), length);

Ok(this.clone())
}

/// Creates a new `Array` instance.
pub(crate) fn new_array(interpreter: &Context) -> Result<Value> {
pub(crate) fn new_array(context: &Context) -> Result<Value> {
let array = Value::new_object(Some(
&interpreter
&context
.realm()
.environment
.get_global_object()
Expand All @@ -45,14 +131,7 @@ impl Array {
array
.as_object_mut()
.expect("array object")
.set_prototype_instance(
interpreter
.realm()
.environment
.get_binding_value("Array")
.expect("Array was not initialized")
.get_field(PROTOTYPE),
);
.set_prototype_instance(context.standard_objects().array_object().prototype().into());
array.set_field("length", Value::from(0));
Ok(array)
}
Expand Down Expand Up @@ -101,52 +180,6 @@ impl Array {
Ok(array_ptr.clone())
}

/// Create a new array
pub(crate) fn make_array(this: &Value, args: &[Value], ctx: &mut Context) -> Result<Value> {
// Make a new Object which will internally represent the Array (mapping
// between indices and values): this creates an Object with no prototype

// Set Prototype
let prototype = ctx.global_object().get_field("Array").get_field(PROTOTYPE);

this.as_object_mut()
.expect("this should be an array object")
.set_prototype_instance(prototype);
// This value is used by console.log and other routines to match Object type
// to its Javascript Identifier (global constructor method name)
this.set_data(ObjectData::Array);

// add our arguments in
let mut length = args.len() as i32;
match args.len() {
1 if args[0].is_integer() => {
length = args[0].as_number().unwrap() as i32;
// TODO: It should not create an array of undefineds, but an empty array ("holy" array in V8) with length `n`.
for n in 0..length {
this.set_field(n, Value::undefined());
}
}
1 if args[0].is_double() => {
return ctx.throw_range_error("invalid array length");
}
_ => {
for (n, value) in args.iter().enumerate() {
this.set_field(n, value.clone());
}
}
}

// finally create length property
let length = Property::data_descriptor(
length.into(),
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
);

this.set_property("length".to_string(), length);

Ok(this.clone())
}

/// `Array.isArray( arg )`
///
/// The isArray function takes one argument arg, and returns the Boolean value true
Expand Down Expand Up @@ -1090,67 +1123,4 @@ impl Array {
}
Ok(accumulator)
}

/// Initialise the `Array` object on the global object.
#[inline]
pub(crate) fn init(interpreter: &mut Context) -> (&'static str, Value) {
let global = interpreter.global_object();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");

// Create prototype
let prototype = Value::new_object(Some(global));
let length = Property::default().value(Value::from(0));

prototype.set_property("length", length);

make_builtin_fn(Self::concat, "concat", &prototype, 1, interpreter);
make_builtin_fn(Self::push, "push", &prototype, 1, interpreter);
make_builtin_fn(Self::index_of, "indexOf", &prototype, 1, interpreter);
make_builtin_fn(
Self::last_index_of,
"lastIndexOf",
&prototype,
1,
interpreter,
);
make_builtin_fn(Self::includes_value, "includes", &prototype, 1, interpreter);
make_builtin_fn(Self::map, "map", &prototype, 1, interpreter);
make_builtin_fn(Self::fill, "fill", &prototype, 1, interpreter);
make_builtin_fn(Self::for_each, "forEach", &prototype, 1, interpreter);
make_builtin_fn(Self::filter, "filter", &prototype, 1, interpreter);
make_builtin_fn(Self::pop, "pop", &prototype, 0, interpreter);
make_builtin_fn(Self::join, "join", &prototype, 1, interpreter);
make_builtin_fn(Self::to_string, "toString", &prototype, 0, interpreter);
make_builtin_fn(Self::reverse, "reverse", &prototype, 0, interpreter);
make_builtin_fn(Self::shift, "shift", &prototype, 0, interpreter);
make_builtin_fn(Self::unshift, "unshift", &prototype, 1, interpreter);
make_builtin_fn(Self::every, "every", &prototype, 1, interpreter);
make_builtin_fn(Self::find, "find", &prototype, 1, interpreter);
make_builtin_fn(Self::find_index, "findIndex", &prototype, 1, interpreter);
make_builtin_fn(Self::slice, "slice", &prototype, 2, interpreter);
make_builtin_fn(Self::some, "some", &prototype, 2, interpreter);
make_builtin_fn(Self::reduce, "reduce", &prototype, 2, interpreter);
make_builtin_fn(
Self::reduce_right,
"reduceRight",
&prototype,
2,
interpreter,
);

let array = make_constructor_fn(
Self::NAME,
Self::LENGTH,
Self::make_array,
global,
prototype,
true,
true,
);

// Static Methods
make_builtin_fn(Self::is_array, "isArray", &array, 1, interpreter);

(Self::NAME, array)
}
}
100 changes: 50 additions & 50 deletions boa/src/builtins/bigint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
use crate::{
builtins::function::{make_builtin_fn, make_constructor_fn},
object::ObjectData,
builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData},
property::Attribute,
value::{RcBigInt, Value},
BoaProfiler, Context, Result,
};
Expand All @@ -40,13 +41,57 @@ mod tests;
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct BigInt(num_bigint::BigInt);

impl BigInt {
/// The name of the object.
pub(crate) const NAME: &'static str = "BigInt";
impl BuiltIn for BigInt {
const NAME: &'static str = "BigInt";

fn attribute() -> Attribute {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE
}

fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");

let bigint_object = ConstructorBuilder::with_standard_object(
context,
Self::constructor,
context.standard_objects().bigint_object().clone(),
)
.name(Self::NAME)
.length(Self::LENGTH)
.method(Self::to_string, "toString", 1)
.method(Self::value_of, "valueOf", 0)
.static_method(Self::as_int_n, "asIntN", 2)
.static_method(Self::as_uint_n, "asUintN", 2)
.callable(true)
.constructable(false)
.build();

(Self::NAME, bigint_object.into(), Self::attribute())
}
}

impl BigInt {
/// The amount of arguments this function object takes.
pub(crate) const LENGTH: usize = 1;

/// `BigInt()`
///
/// The `BigInt()` constructor is used to create BigInt objects.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [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> {
let data = match args.get(0) {
Some(ref value) => value.to_bigint(context)?,
None => RcBigInt::from(Self::from(0)),
};
Ok(Value::from(data))
}

/// The abstract operation thisBigIntValue takes argument value.
///
/// The phrase “this BigInt value” within the specification of a method refers to the
Expand Down Expand Up @@ -78,24 +123,6 @@ impl BigInt {
Err(ctx.construct_type_error("'this' is not a BigInt"))
}

/// `BigInt()`
///
/// The `BigInt()` constructor is used to create BigInt objects.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-bigint-objects
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/BigInt
pub(crate) fn make_bigint(_: &Value, args: &[Value], ctx: &mut Context) -> Result<Value> {
let data = match args.get(0) {
Some(ref value) => value.to_bigint(ctx)?,
None => RcBigInt::from(Self::from(0)),
};
Ok(Value::from(data))
}

/// `BigInt.prototype.toString( [radix] )`
///
/// The `toString()` method returns a string representing the specified BigInt object.
Expand Down Expand Up @@ -194,33 +221,6 @@ impl BigInt {
bits,
))
}

/// Initialise the `BigInt` object on the global object.
#[inline]
pub fn init(interpreter: &mut Context) -> (&'static str, Value) {
let global = interpreter.global_object();
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");

let prototype = Value::new_object(Some(global));

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

let bigint_object = make_constructor_fn(
Self::NAME,
Self::LENGTH,
Self::make_bigint,
global,
prototype,
false,
true,
);

make_builtin_fn(Self::as_int_n, "asIntN", &bigint_object, 2, interpreter);
make_builtin_fn(Self::as_uint_n, "asUintN", &bigint_object, 2, interpreter);

(Self::NAME, bigint_object)
}
}

impl Finalize for BigInt {}
Expand Down
Loading

0 comments on commit 65d95ae

Please sign in to comment.