Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moved value operations from Interpreter to Value #625

Merged
merged 19 commits into from
Aug 15, 2020
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6cb8859
Moved `Interpreter::to_primitive()` to `Value::to_primitive()`
HalidOdat Aug 11, 2020
58ee11b
Moved `Interpreter::to_bigint()` to `Value::to_bigint()`
HalidOdat Aug 11, 2020
96ba3a2
Added `Value::display()` which implements Display
HalidOdat Aug 11, 2020
df1575c
Moved `Interpreter::to_string()` to `Value::to_string()`
HalidOdat Aug 11, 2020
2919a22
Moved `Interpreter::to_object()` to `Value::to_object()`
HalidOdat Aug 11, 2020
62b3dd1
Moved `Interpreter::to_property_key()` to `Value::to_property_key()`
HalidOdat Aug 11, 2020
f2aeb98
Moved `Interpreter::to_numeric()` to `Value::to_numeric()`
HalidOdat Aug 11, 2020
803894d
Moved `Interpreter::to_uint32()` to `Value::to_uint32()`
HalidOdat Aug 11, 2020
5f01329
Moved `Interpreter::to_int32()` to `Value::to_int32()`
HalidOdat Aug 11, 2020
7010e2b
Moved `Interpreter::to_index()` to `Value::to_index()`
HalidOdat Aug 11, 2020
41948de
Moved `Interpreter::to_length()` to `Value::to_length()`
HalidOdat Aug 11, 2020
1a96e08
Moved `Interpreter::to_integer()` to `Value::to_integer()`
HalidOdat Aug 12, 2020
ff82661
Moved `Interpreter::to_number()` to `Value::to_number()`
HalidOdat Aug 12, 2020
9ae1dc7
Moved `Interpreter::to_numeric_number()` to `Value::to_numeric_number()`
HalidOdat Aug 12, 2020
cc903e3
Added fast path for `Value::to_property_key`
HalidOdat Aug 12, 2020
b5aa974
Added `Numeric` enum for `.to_numeric()`
HalidOdat Aug 14, 2020
85aa5a1
Added some documentation
HalidOdat Aug 14, 2020
e929bd6
Doc fix
HalidOdat Aug 14, 2020
9c5b69d
Use map_or instead of always cast to u8
HalidOdat Aug 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 47 additions & 39 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl Array {
let array_obj_ptr = array_obj.clone();

// Wipe existing contents of the array object
let orig_length = i32::from(&array_obj.get_field("length"));
let orig_length = array_obj.get_field("length").as_number().unwrap() as i32;
for n in 0..orig_length {
array_obj_ptr.remove_property(&n.to_string());
}
Expand All @@ -90,7 +90,7 @@ impl Array {
/// Utility function which takes an existing array object and puts additional
/// values on the end, correctly rewriting the length
pub(crate) fn add_to_array_object(array_ptr: &Value, add_values: &[Value]) -> ResultValue {
let orig_length = i32::from(&array_ptr.get_field("length"));
let orig_length = array_ptr.get_field("length").as_number().unwrap() as i32;

for (n, value) in add_values.iter().enumerate() {
let new_index = orig_length.wrapping_add(n as i32);
Expand Down Expand Up @@ -124,7 +124,7 @@ impl Array {
let mut length = args.len() as i32;
match args.len() {
1 if args[0].is_integer() => {
length = i32::from(&args[0]);
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.to_string(), Value::undefined());
Expand Down Expand Up @@ -195,13 +195,13 @@ impl Array {
// one)
let mut new_values: Vec<Value> = Vec::new();

let this_length = i32::from(&this.get_field("length"));
let this_length = this.get_field("length").as_number().unwrap() as i32;
for n in 0..this_length {
new_values.push(this.get_field(n.to_string()));
}

for concat_array in args {
let concat_length = i32::from(&concat_array.get_field("length"));
let concat_length = concat_array.get_field("length").as_number().unwrap() as i32;
for n in 0..concat_length {
new_values.push(concat_array.get_field(n.to_string()));
}
Expand Down Expand Up @@ -238,7 +238,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], _: &mut Interpreter) -> ResultValue {
let curr_length = i32::from(&this.get_field("length"));
let curr_length = this.get_field("length").as_number().unwrap() as i32;
if curr_length < 1 {
return Ok(Value::undefined());
}
Expand Down Expand Up @@ -271,7 +271,7 @@ impl Array {
let callback_arg = args.get(0).expect("Could not get `callbackFn` argument.");
let this_arg = args.get(1).cloned().unwrap_or_else(Value::undefined);

let length = i32::from(&this.get_field("length"));
let length = this.get_field("length").as_number().unwrap() as i32;

for i in 0..length {
let element = this.get_field(i.to_string());
Expand Down Expand Up @@ -299,14 +299,16 @@ impl Array {
let separator = if args.is_empty() {
String::from(",")
} else {
ctx.to_string(args.get(0).expect("Could not get argument"))?
args.get(0)
.expect("Could not get argument")
.to_string(ctx)?
.to_string()
};

let mut elem_strs = Vec::new();
let length = i32::from(&this.get_field("length"));
let length = this.get_field("length").as_number().unwrap() as i32;
for n in 0..length {
let elem_str = ctx.to_string(&this.get_field(n.to_string()))?.to_string();
let elem_str = this.get_field(n.to_string()).to_string(ctx)?.to_string();
elem_strs.push(elem_str);
}

Expand Down Expand Up @@ -367,7 +369,7 @@ impl Array {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse
#[allow(clippy::else_if_without_else)]
pub(crate) fn reverse(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
let len = i32::from(&this.get_field("length"));
let len = this.get_field("length").as_number().unwrap() as i32;
let middle: i32 = len.wrapping_div(2);

for lower in 0..middle {
Expand Down Expand Up @@ -405,7 +407,7 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.shift
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
pub(crate) fn shift(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue {
let len = i32::from(&this.get_field("length"));
let len = this.get_field("length").as_number().unwrap() as i32;

if len == 0 {
this.set_field("length", 0);
Expand Down Expand Up @@ -447,7 +449,7 @@ impl Array {
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.unshift
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
pub(crate) fn unshift(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
let len = i32::from(&this.get_field("length"));
let len = this.get_field("length").as_number().unwrap() as i32;
let arg_c: i32 = args.len() as i32;

if arg_c > 0 {
Expand Down Expand Up @@ -507,7 +509,7 @@ impl Array {
Value::undefined()
};
let mut i = 0;
let max_len = i32::from(&this.get_field("length"));
let max_len = this.get_field("length").as_number().unwrap() as i32;
let mut len = max_len;
while i < len {
let element = this.get_field(i.to_string());
Expand All @@ -516,7 +518,10 @@ impl Array {
if !result.to_boolean() {
return Ok(Value::from(false));
}
len = min(max_len, i32::from(&this.get_field("length")));
len = min(
max_len,
this.get_field("length").as_number().unwrap() as i32,
);
i += 1;
}
Ok(Value::from(true))
Expand All @@ -543,7 +548,7 @@ impl Array {
let callback = args.get(0).cloned().unwrap_or_else(Value::undefined);
let this_val = args.get(1).cloned().unwrap_or_else(Value::undefined);

let length = i32::from(&this.get_field("length"));
let length = this.get_field("length").as_number().unwrap() as i32;

let new = Self::new_array(interpreter)?;

Expand Down Expand Up @@ -587,11 +592,11 @@ impl Array {
}

let search_element = args[0].clone();
let len = i32::from(&this.get_field("length"));
let len = this.get_field("length").as_number().unwrap() as i32;

let mut idx = match args.get(1) {
Some(from_idx_ptr) => {
let from_idx = i32::from(from_idx_ptr);
let from_idx = from_idx_ptr.as_number().unwrap() as i32;

if from_idx < 0 {
len + from_idx
Expand Down Expand Up @@ -640,11 +645,11 @@ impl Array {
}

let search_element = args[0].clone();
let len = i32::from(&this.get_field("length"));
let len = this.get_field("length").as_number().unwrap() as i32;

let mut idx = match args.get(1) {
Some(from_idx_ptr) => {
let from_idx = i32::from(from_idx_ptr);
let from_idx = from_idx_ptr.as_number().unwrap() as i32;

if from_idx >= 0 {
min(from_idx, len - 1)
Expand Down Expand Up @@ -688,7 +693,7 @@ impl Array {
}
let callback = &args[0];
let this_arg = args.get(1).cloned().unwrap_or_else(Value::undefined);
let len = i32::from(&this.get_field("length"));
let len = this.get_field("length").as_number().unwrap() as i32;
for i in 0..len {
let element = this.get_field(i.to_string());
let arguments = [element.clone(), Value::from(i), this.clone()];
Expand Down Expand Up @@ -727,7 +732,7 @@ impl Array {

let this_arg = args.get(1).cloned().unwrap_or_else(Value::undefined);

let length = i32::from(&this.get_field("length"));
let length = this.get_field("length").as_number().unwrap() as i32;

for i in 0..length {
let element = this.get_field(i.to_string());
Expand All @@ -754,16 +759,16 @@ 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], _: &mut Interpreter) -> ResultValue {
let len: i32 = i32::from(&this.get_field("length"));
pub(crate) fn fill(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
let len: i32 = this.get_field("length").as_number().unwrap() as i32;
let default_value = Value::undefined();
let value = args.get(0).unwrap_or(&default_value);
let relative_start = args.get(1).unwrap_or(&default_value).to_number() as i32;
let relative_start = args.get(1).unwrap_or(&default_value).to_number(ctx)? as i32;
let relative_end_val = args.get(2).unwrap_or(&default_value);
let relative_end = if relative_end_val.is_undefined() {
len
} else {
relative_end_val.to_number() as i32
relative_end_val.to_number(ctx)? as i32
};
let start = if relative_start < 0 {
max(len + relative_start, 0)
Expand Down Expand Up @@ -796,7 +801,7 @@ impl Array {
pub(crate) fn includes_value(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue {
let search_element = args.get(0).cloned().unwrap_or_else(Value::undefined);

let length = i32::from(&this.get_field("length"));
let length = this.get_field("length").as_number().unwrap() as i32;

for idx in 0..length {
let check_element = this.get_field(idx.to_string()).clone();
Expand Down Expand Up @@ -829,14 +834,14 @@ impl Array {
interpreter: &mut Interpreter,
) -> ResultValue {
let new_array = Self::new_array(interpreter)?;
let len = i32::from(&this.get_field("length"));
let len = this.get_field("length").as_number().unwrap() as i32;

let start = match args.get(0) {
Some(v) => i32::from(v),
Some(v) => v.as_number().unwrap() as i32,
None => 0,
};
let end = match args.get(1) {
Some(v) => i32::from(v),
Some(v) => v.as_number().unwrap() as i32,
None => len,
};

Expand Down Expand Up @@ -886,7 +891,7 @@ impl Array {
let callback = args.get(0).cloned().unwrap_or_else(Value::undefined);
let this_val = args.get(1).cloned().unwrap_or_else(Value::undefined);

let length = i32::from(&this.get_field("length"));
let length = this.get_field("length").as_number().unwrap() as i32;

let new = Self::new_array(interpreter)?;

Expand Down Expand Up @@ -939,7 +944,7 @@ impl Array {
Value::undefined()
};
let mut i = 0;
let max_len = i32::from(&this.get_field("length"));
let max_len = this.get_field("length").as_number().unwrap() as i32;
let mut len = max_len;
while i < len {
let element = this.get_field(i.to_string());
Expand All @@ -949,7 +954,10 @@ impl Array {
return Ok(Value::from(true));
}
// the length of the array must be updated because the callback can mutate it.
len = min(max_len, i32::from(&this.get_field("length")));
len = min(
max_len,
this.get_field("length").as_number().unwrap() as i32,
);
i += 1;
}
Ok(Value::from(false))
Expand All @@ -971,13 +979,13 @@ impl Array {
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
let this = interpreter.to_object(this)?;
let this = this.to_object(interpreter)?;
let callback = match args.get(0) {
Some(value) if value.is_function() => value,
_ => return interpreter.throw_type_error("Reduce was called without a callback"),
};
let initial_value = args.get(1).cloned().unwrap_or_else(Value::undefined);
let mut length = interpreter.to_length(&this.get_field("length"))?;
let mut length = this.get_field("length").to_length(interpreter)?;
if length == 0 && initial_value.is_undefined() {
return interpreter
.throw_type_error("Reduce was called on an empty array and with no initial value");
Expand Down Expand Up @@ -1015,7 +1023,7 @@ impl Array {
/* We keep track of possibly shortened length in order to prevent unnecessary iteration.
It may also be necessary to do this since shortening the array length does not
delete array elements. See: https://github.com/boa-dev/boa/issues/557 */
length = min(length, interpreter.to_length(&this.get_field("length"))?);
length = min(length, this.get_field("length").to_length(interpreter)?);
}
k += 1;
}
Expand All @@ -1038,13 +1046,13 @@ impl Array {
args: &[Value],
interpreter: &mut Interpreter,
) -> ResultValue {
let this = interpreter.to_object(this)?;
let this = this.to_object(interpreter)?;
let callback = match args.get(0) {
Some(value) if value.is_function() => value,
_ => return interpreter.throw_type_error("reduceRight was called without a callback"),
};
let initial_value = args.get(1).cloned().unwrap_or_else(Value::undefined);
let mut length = interpreter.to_length(&this.get_field("length"))?;
let mut length = this.get_field("length").to_length(interpreter)?;
if length == 0 {
if initial_value.is_undefined() {
return interpreter.throw_type_error(
Expand Down Expand Up @@ -1092,7 +1100,7 @@ impl Array {
/* We keep track of possibly shortened length in order to prevent unnecessary iteration.
It may also be necessary to do this since shortening the array length does not
delete array elements. See: https://github.com/boa-dev/boa/issues/557 */
length = min(length, interpreter.to_length(&this.get_field("length"))?);
length = min(length, this.get_field("length").to_length(interpreter)?);

// move k to the last defined element if necessary or return if the length was set to 0
if k >= length {
Expand Down
8 changes: 4 additions & 4 deletions boa/src/builtins/bigint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl BigInt {
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/BigInt
pub(crate) fn make_bigint(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
let data = match args.get(0) {
Some(ref value) => ctx.to_bigint(value)?,
Some(ref value) => value.to_bigint(ctx)?,
None => RcBigInt::from(Self::from(0)),
};
Ok(Value::from(data))
Expand All @@ -112,7 +112,7 @@ impl BigInt {
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_string(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue {
let radix = if !args.is_empty() {
args[0].to_integer()
args[0].to_integer(ctx)? as i32
} else {
10
};
Expand Down Expand Up @@ -184,10 +184,10 @@ impl BigInt {
let bits_arg = args.get(0).unwrap_or(&undefined_value);
let bigint_arg = args.get(1).unwrap_or(&undefined_value);

let bits = ctx.to_index(bits_arg)?;
let bits = bits_arg.to_index(ctx)?;
let bits = u32::try_from(bits).unwrap_or(u32::MAX);

let bigint = ctx.to_bigint(bigint_arg)?;
let bigint = bigint_arg.to_bigint(ctx)?;

Ok((
bigint
Expand Down
Loading