diff --git a/boa/src/builtins/array/mod.rs b/boa/src/builtins/array/mod.rs index 1f94209b4d..9bebb05a27 100644 --- a/boa/src/builtins/array/mod.rs +++ b/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, context: &mut Context, ) -> Result { // 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: pub(crate) fn array_species_create( original_array: &GcObject, - length: u64, + length: usize, context: &mut Context, ) -> Result { // 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 { - 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::>>()?; - - 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 ] )` diff --git a/boa/src/builtins/regexp/mod.rs b/boa/src/builtins/regexp/mod.rs index b358477264..62defc8d09 100644 --- a/boa/src/builtins/regexp/mod.rs +++ b/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. diff --git a/boa/src/builtins/string/mod.rs b/boa/src/builtins/string/mod.rs index 7663e61bb1..d462faad89 100644 --- a/boa/src/builtins/string/mod.rs +++ b/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; diff --git a/test_ignore.txt b/test_ignore.txt index 86b4f63480..0341de38c3 100644 --- a/test_ignore.txt +++ b/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