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

Implement new get_or_undefined method for [JsValue] #1492

Merged
merged 5 commits into from
Sep 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
48 changes: 25 additions & 23 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use crate::{
};
use std::cmp::{max, min, Ordering};

use super::JsArgs;

/// JavaScript `Array` built-in implementation.
#[derive(Debug, Clone, Copy)]
pub(crate) struct Array;
Expand Down Expand Up @@ -687,8 +689,8 @@ 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(JsValue::undefined);
callback.call(&this_arg, &[k_value, k.into(), o.clone().into()], context)?;
let this_arg = args.get_or_undefined(1);
callback.call(this_arg, &[k_value, k.into(), o.clone().into()], context)?;
}
// d. Set k to k + 1.
}
Expand Down Expand Up @@ -1022,7 +1024,7 @@ impl Array {
return context.throw_type_error("Array.prototype.every: callback is not callable");
};

let this_arg = args.get(1).cloned().unwrap_or_default();
let this_arg = args.get_or_undefined(1);

// 4. Let k be 0.
// 5. Repeat, while k < len,
Expand All @@ -1036,7 +1038,7 @@ impl Array {
let k_value = o.get(k, context)?;
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
let test_result = callback
.call(&this_arg, &[k_value, k.into(), o.clone().into()], context)?
.call(this_arg, &[k_value, k.into(), o.clone().into()], context)?
.to_boolean();
// iii. If testResult is false, return false.
if !test_result {
Expand Down Expand Up @@ -1070,15 +1072,15 @@ impl Array {
// 2. Let len be ? LengthOfArrayLike(O).
let len = o.length_of_array_like(context)?;
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
let callback = args.get(0).cloned().unwrap_or_default();
let callback = args.get_or_undefined(0);
if !callback.is_function() {
return context.throw_type_error("Array.prototype.map: Callbackfn is not callable");
}

// 4. Let A be ? ArraySpeciesCreate(O, len).
let a = Self::array_species_create(&o, len, context)?;

let this_arg = args.get(1).cloned().unwrap_or_default();
let this_arg = args.get_or_undefined(1);

// 5. Let k be 0.
// 6. Repeat, while k < len,
Expand All @@ -1092,7 +1094,7 @@ impl Array {
let k_value = o.get(k, context)?;
// ii. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
let mapped_value =
context.call(&callback, &this_arg, &[k_value, k.into(), this.into()])?;
context.call(callback, this_arg, &[k_value, k.into(), this.into()])?;
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
a.create_data_property_or_throw(k, mapped_value, context)?;
}
Expand Down Expand Up @@ -1156,7 +1158,7 @@ impl Array {
}
};

let search_element = args.get(0).cloned().unwrap_or_default();
let search_element = args.get_or_undefined(0);

// 10. Repeat, while k < len,
while k < len {
Expand Down Expand Up @@ -1232,7 +1234,7 @@ impl Array {
IntegerOrInfinity::Integer(n) => len + n,
};

let search_element = args.get(0).cloned().unwrap_or_default();
let search_element = args.get_or_undefined(0);

// 8. Repeat, while k ≥ 0,
while k >= 0 {
Expand All @@ -1244,7 +1246,7 @@ impl Array {
let element_k = o.get(k, context)?;
// ii. Let same be IsStrictlyEqual(searchElement, elementK).
// iii. If same is true, return 𝔽(k).
if JsValue::strict_equals(&search_element, &element_k) {
if JsValue::strict_equals(search_element, &element_k) {
return Ok(JsValue::new(k));
}
}
Expand Down Expand Up @@ -1286,7 +1288,7 @@ impl Array {
}
};

let this_arg = args.get(1).cloned().unwrap_or_default();
let this_arg = args.get_or_undefined(1);

// 4. Let k be 0.
let mut k = 0;
Expand All @@ -1299,7 +1301,7 @@ impl Array {
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
let test_result = predicate
.call(
&this_arg,
this_arg,
&[k_value.clone(), k.into(), o.clone().into()],
context,
)?
Expand Down Expand Up @@ -1347,7 +1349,7 @@ impl Array {
}
};

let this_arg = args.get(1).cloned().unwrap_or_default();
let this_arg = args.get_or_undefined(1);

// 4. Let k be 0.
let mut k = 0;
Expand All @@ -1359,7 +1361,7 @@ impl Array {
let k_value = o.get(pk, context)?;
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
let test_result = predicate
.call(&this_arg, &[k_value, k.into(), o.clone().into()], context)?
.call(this_arg, &[k_value, k.into(), o.clone().into()], context)?
.to_boolean();
// d. If testResult is true, return 𝔽(k).
if test_result {
Expand Down Expand Up @@ -1451,7 +1453,7 @@ impl Array {
let source_len = o.length_of_array_like(context)?;

// 3. If ! IsCallable(mapperFunction) is false, throw a TypeError exception.
let mapper_function = args.get(0).cloned().unwrap_or_default();
let mapper_function = args.get_or_undefined(0);
if !mapper_function.is_function() {
return context.throw_type_error("flatMap mapper function is not callable");
}
Expand All @@ -1467,7 +1469,7 @@ impl Array {
0,
1,
Some(mapper_function.as_object().unwrap()),
&args.get(1).cloned().unwrap_or_default(),
args.get_or_undefined(1),
context,
)?;

Expand Down Expand Up @@ -1622,7 +1624,7 @@ impl Array {
// 10. Else, let final be min(relativeEnd, len).
let final_ = Self::get_relative_end(context, args.get(2), len)?;

let value = args.get(0).cloned().unwrap_or_default();
let value = args.get_or_undefined(0);

// 11. Repeat, while k < final,
while k < final_ {
Expand Down Expand Up @@ -1693,14 +1695,14 @@ impl Array {
}
}

let search_element = args.get(0).cloned().unwrap_or_default();
let search_element = args.get_or_undefined(0);

// 10. Repeat, while k < len,
while k < len {
// 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 JsValue::same_value_zero(&search_element, &element_k) {
if JsValue::same_value_zero(search_element, &element_k) {
return Ok(JsValue::new(true));
}
// c. Set k to k + 1.
Expand Down Expand Up @@ -1813,7 +1815,7 @@ impl Array {
"missing argument 0 when calling function Array.prototype.filter",
)
})?;
let this_val = args.get(1).cloned().unwrap_or_else(JsValue::undefined);
let this_arg = args.get_or_undefined(1);

if !callback.is_callable() {
return context.throw_type_error("the callback must be callable");
Expand All @@ -1837,7 +1839,7 @@ impl Array {
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();
let selected = callback.call(this_arg, &args, context)?.to_boolean();

// iii. If selected is true, then
if selected {
Expand Down Expand Up @@ -1899,9 +1901,9 @@ impl Array {
// i. Let kValue be ? Get(O, Pk).
let k_value = o.get(k, context)?;
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
let this_arg = args.get(1).cloned().unwrap_or_default();
let this_arg = args.get_or_undefined(1);
let test_result = callback
.call(&this_arg, &[k_value, k.into(), o.clone().into()], context)?
.call(this_arg, &[k_value, k.into(), o.clone().into()], context)?
.to_boolean();
// iii. If testResult is true, return true.
if test_result {
Expand Down
16 changes: 9 additions & 7 deletions boa/src/builtins/bigint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

use crate::{
builtins::BuiltIn, object::ConstructorBuilder, property::Attribute, symbol::WellKnownSymbols,
value::IntegerOrInfinity, BoaProfiler, Context, JsBigInt, JsResult, JsValue,
builtins::{BuiltIn, JsArgs},
object::ConstructorBuilder,
property::Attribute,
symbol::WellKnownSymbols,
value::IntegerOrInfinity,
BoaProfiler, Context, JsBigInt, JsResult, JsValue,
};
#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -131,7 +135,7 @@ impl BigInt {
// 1. Let x be ? thisBigIntValue(this value).
let x = Self::this_bigint_value(this, context)?;

let radix = args.get(0).cloned().unwrap_or_default();
let radix = args.get_or_undefined(0);

// 2. If radix is undefined, let radixMV be 10.
let radix_mv = if radix.is_undefined() {
Expand Down Expand Up @@ -234,10 +238,8 @@ impl BigInt {
fn calculate_as_uint_n(args: &[JsValue], context: &mut Context) -> JsResult<(JsBigInt, u32)> {
use std::convert::TryFrom;

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);
let bits_arg = args.get_or_undefined(0);
let bigint_arg = args.get_or_undefined(1);

let bits = bits_arg.to_index(context)?;
let bits = u32::try_from(bits).unwrap_or(u32::MAX);
Expand Down
7 changes: 3 additions & 4 deletions boa/src/builtins/console/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
mod tests;

use crate::{
builtins::BuiltIn,
builtins::{BuiltIn, JsArgs},
object::ObjectInitializer,
property::Attribute,
value::{display::display_obj, JsValue},
Expand Down Expand Up @@ -90,7 +90,7 @@ pub fn formatter(data: &[JsValue], context: &mut Context) -> JsResult<String> {
}
/* object, FIXME: how to render this properly? */
'o' | 'O' => {
let arg = data.get(arg_index).cloned().unwrap_or_default();
let arg = data.get_or_undefined(arg_index);
formatted.push_str(&format!("{}", arg.display()));
arg_index += 1
}
Expand Down Expand Up @@ -564,9 +564,8 @@ 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(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
let undefined = JsValue::undefined();
logger(
LogMessage::Info(display_obj(args.get(0).unwrap_or(&undefined), true)),
LogMessage::Info(display_obj(args.get_or_undefined(0), true)),
context.console(),
);

Expand Down
4 changes: 3 additions & 1 deletion boa/src/builtins/date/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use crate::{
use chrono::{prelude::*, Duration, LocalResult};
use std::fmt::Display;

use super::JsArgs;

/// The number of nanoseconds in a millisecond.
const NANOS_PER_MS: i64 = 1_000_000;
/// The number of milliseconds in an hour.
Expand Down Expand Up @@ -523,7 +525,7 @@ impl Date {
return context.throw_type_error("Date.prototype[@@toPrimitive] called on non object");
};

let hint = args.get(0).cloned().unwrap_or_default();
let hint = args.get_or_undefined(0);

let try_first = match hint.as_string().map(|s| s.as_str()) {
// 3. If hint is "string" or "default", then
Expand Down
14 changes: 8 additions & 6 deletions boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ use bitflags::bitflags;
use std::fmt::{self, Debug};
use std::rc::Rc;

use super::JsArgs;

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -322,10 +324,10 @@ impl BuiltInFunctionObject {
if !this.is_function() {
return context.throw_type_error(format!("{} is not a function", this.display()));
}
let this_arg: JsValue = args.get(0).cloned().unwrap_or_default();
let this_arg = args.get_or_undefined(0);
// TODO?: 3. Perform PrepareForTailCall
let start = if !args.is_empty() { 1 } else { 0 };
context.call(this, &this_arg, &args[start..])
context.call(this, this_arg, &args[start..])
}

/// `Function.prototype.apply`
Expand All @@ -343,15 +345,15 @@ impl BuiltInFunctionObject {
if !this.is_function() {
return context.throw_type_error(format!("{} is not a function", this.display()));
}
let this_arg = args.get(0).cloned().unwrap_or_default();
let arg_array = args.get(1).cloned().unwrap_or_default();
let this_arg = args.get_or_undefined(0);
let arg_array = args.get_or_undefined(1);
if arg_array.is_null_or_undefined() {
// TODO?: 3.a. PrepareForTailCall
return context.call(this, &this_arg, &[]);
return context.call(this, this_arg, &[]);
}
let arg_list = arg_array.create_list_from_array_like(&[], context)?;
// TODO?: 5. PrepareForTailCall
context.call(this, &this_arg, &arg_list)
context.call(this, this_arg, &arg_list)
}
}

Expand Down
8 changes: 5 additions & 3 deletions boa/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ use crate::{
};
use serde_json::{self, Value as JSONValue};

use super::JsArgs;

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -158,7 +160,7 @@ impl Json {
let mut property_list = None;
let mut replacer_function = None;

let replacer = args.get(1).cloned().unwrap_or_default();
let replacer = args.get_or_undefined(1);

// 4. If Type(replacer) is Object, then
if let Some(replacer_obj) = replacer.as_object() {
Expand Down Expand Up @@ -214,7 +216,7 @@ impl Json {
}
}

let mut space = args.get(2).cloned().unwrap_or_default();
let mut space = args.get_or_undefined(2).clone();

// 5. If Type(space) is Object, then
if let Some(space_obj) = space.as_object() {
Expand Down Expand Up @@ -266,7 +268,7 @@ impl Json {

// 10. Perform ! CreateDataPropertyOrThrow(wrapper, the empty String, value).
wrapper
.create_data_property_or_throw("", args.get(0).cloned().unwrap_or_default(), context)
.create_data_property_or_throw("", args.get_or_undefined(0).clone(), context)
.expect("CreateDataPropertyOrThrow should never fail here");

// 11. Let state be the Record { [[ReplacerFunction]]: ReplacerFunction, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: PropertyList }.
Expand Down
Loading