Browse Source

fix(boa): 15.4.4.19-8-c-ii-1.js (#1351)

* fix(boa): 15.4.4.19-8-c-ii-1.js

- skips undefined values on callback
- formats

Closes #1306

* add map callbackfn check whether callable

* major rewrite of map function for es compliance

* fix testcase 15.4.4.19-8-c-ii-1.js

* fmt

* add range error in array constructor

* fix clippy errors & fmt

* rebase
pull/1431/head
neeldug 3 years ago committed by GitHub
parent
commit
a4a76fe87c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 68
      boa/src/builtins/array/mod.rs
  2. 6
      boa/src/builtins/regexp/mod.rs
  3. 2
      boa/src/builtins/string/mod.rs
  4. 1
      test_ignore.txt

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

@ -181,7 +181,7 @@ impl Array {
debug_assert!(number_of_args >= 2);
// b. Let array be ? ArrayCreate(numberOfArgs, proto).
let array = Array::array_create(number_of_args as u64, Some(prototype), context)?;
let array = Array::array_create(number_of_args, Some(prototype), context)?;
// c. Let k be 0.
// d. Repeat, while k < numberOfArgs,
for (i, item) in args.iter().cloned().enumerate() {
@ -206,12 +206,12 @@ impl Array {
///
/// [spec]: https://tc39.es/ecma262/#sec-arraycreate
pub(crate) fn array_create(
length: u64,
length: usize,
prototype: Option<GcObject>,
context: &mut Context,
) -> Result<GcObject> {
// 1. If length > 2^32 - 1, throw a RangeError exception.
if length > 2u64.pow(32) - 1 {
if length > 2usize.pow(32) - 1 {
return Err(context.construct_range_error("array exceeded max size"));
}
// 7. Return A.
@ -307,7 +307,7 @@ impl Array {
/// see: <https://tc39.es/ecma262/#sec-arrayspeciescreate>
pub(crate) fn array_species_create(
original_array: &GcObject,
length: u64,
length: usize,
context: &mut Context,
) -> Result<GcObject> {
// 1. Let isArray be ? IsArray(originalArray).
@ -428,7 +428,7 @@ impl Array {
.construct(&[len.into()], this, context)?
.as_object()
.unwrap(),
_ => Array::array_create(len as u64, None, context)?,
_ => Array::array_create(len, None, context)?,
};
// 6. Let k be 0.
@ -954,33 +954,41 @@ 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> {
if args.is_empty() {
return Err(Value::from(
"missing argument 0 when calling function Array.prototype.map",
));
}
let callback = args.get(0).cloned().unwrap_or_else(Value::undefined);
// 1. Let O be ? ToObject(this value).
let this_val = args.get(1).cloned().unwrap_or_else(Value::undefined);
let length = this.get_field("length", context)?.to_length(context)?;
if length > 2usize.pow(32) - 1 {
return context.throw_range_error("Invalid array length");
let obj = this.to_object(context)?;
// 2. Let len be ? LengthOfArrayLike(O).
let len = this.get_field("length", context)?.to_length(context)?;
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
let callback = args.get(0).cloned().unwrap_or_else(Value::undefined);
if !callback.is_function() {
return context.throw_type_error("Callbackfn is not callable");
}
let new = Self::new_array(context);
let values = (0..length)
.map(|idx| {
let element = this.get_field(idx, context)?;
let args = [element, Value::from(idx), new.clone()];
context.call(&callback, &this_val, &args)
})
.collect::<Result<Vec<Value>>>()?;
Self::construct_array(&new, &values, context)
// 4. Let A be ? ArraySpeciesCreate(O, len).
let arr = Self::array_species_create(&obj, len, context)?;
// 5. Let k be 0.
// 6. Repeat, while k < len,
for k in 0..len {
// a. Let Pk be ! ToString(𝔽(k)).
// b. Let k_present be ? HasProperty(O, Pk).
let k_present = this.has_field(k);
// c. If k_present is true, then
if k_present {
// i. Let kValue be ? Get(O, Pk).
let k_value = this.get_field(k, context)?;
let args = [k_value, Value::from(k), this.into()];
// ii. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
let value = context.call(&callback, &this_val, &args)?;
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
arr.ordinary_define_own_property(
k.into(),
DataDescriptor::new(value, Attribute::all()).into(),
);
}
// d. Set k to k + 1.
}
// 7. Return A.
Ok(Value::from(arr))
}
/// `Array.prototype.indexOf( searchElement[, fromIndex ] )`

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

@ -820,9 +820,9 @@ impl RegExp {
}
// 16. Let n be the number of elements in r's captures List. (This is the same value as 22.2.2.1's NcapturingParens.)
let n = match_value.captures.len() as u64;
let n = match_value.captures.len();
// 17. Assert: n < 23^2 - 1.
assert!(n < 23u64.pow(2) - 1);
debug_assert!(n < 23usize.pow(2) - 1);
// 18. Let A be ! ArrayCreate(n + 1).
// 19. Assert: The mathematical value of A's "length" property is n + 1.
@ -861,7 +861,7 @@ impl RegExp {
// 27. For each integer i such that i ≥ 1 and i ≤ n, in ascending order, do
for i in 1..=n {
// a. Let captureI be ith element of r's captures List.
let capture = match_value.group(i as usize);
let capture = match_value.group(i);
let captured_value = match capture {
// b. If captureI is undefined, let capturedValue be undefined.

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

@ -1189,7 +1189,7 @@ impl String {
let this_str = this.to_string(context)?;
// 4. Let A be ! ArrayCreate(0).
let a = Array::array_create(0, None, context).unwrap();
let a = Array::array_create(0, None, context)?;
// 5. Let lengthA be 0.
let mut length_a = 0;

1
test_ignore.txt

@ -11,7 +11,6 @@ feature:json-modules
// These seem to run forever:
arg-length-exceeding-integer-limit
15.4.4.19-8-c-ii-1
// These generate a stack overflow
tco-call

Loading…
Cancel
Save