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