Skip to content

Commit

Permalink
Implement abstract operation CreateArrayFromList (#1485)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 authored Aug 20, 2021
1 parent bc12f95 commit 0f380a9
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 58 deletions.
9 changes: 3 additions & 6 deletions boa/src/builtins/array/array_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,9 @@ impl ArrayIterator {
}
ArrayIterationKind::KeyAndValue => {
let element_value = array_iterator.array.get_field(index, context)?;
let result = Array::constructor(
&JsValue::new_object(context),
&[index.into(), element_value],
context,
)?;
Ok(create_iter_result_object(context, result, false))
let result =
Array::create_array_from_list([index.into(), element_value], context);
Ok(create_iter_result_object(context, result.into(), false))
}
}
} else {
Expand Down
70 changes: 28 additions & 42 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ impl Array {
array.ordinary_define_own_property(
"length".into(),
PropertyDescriptor::builder()
.value(length as f64)
.value(length)
.writable(true)
.enumerable(false)
.configurable(false)
Expand All @@ -243,6 +243,33 @@ impl Array {
Ok(array)
}

/// Utility for constructing `Array` objects from an iterator of `JsValue`s.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-createarrayfromlist
pub(crate) fn create_array_from_list<I>(elements: I, context: &mut Context) -> GcObject
where
I: IntoIterator<Item = JsValue>,
{
// 1. Assert: elements is a List whose elements are all ECMAScript language values.
// 2. Let array be ! ArrayCreate(0).
let array = Self::array_create(0, None, context)
.expect("creating an empty array with the default prototype must not fail");
// 3. Let n be 0.
// 4. For each element e of elements, do
for (i, elem) in elements.into_iter().enumerate() {
// a. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), e).
array
.create_data_property_or_throw(i, elem, context)
.expect("new array must be extensible");
// b. Set n to n + 1.
}
// 5. Return array.
array
}

/// Creates a new `Array` instance.
pub(crate) fn new_array(context: &Context) -> JsValue {
let array = JsValue::new_object(context);
Expand All @@ -263,47 +290,6 @@ impl Array {
array
}

/// Utility function for creating array objects.
///
/// `array_obj` can be any array with prototype already set (it will be wiped and
/// recreated from `array_contents`)
pub(crate) fn construct_array(
array_obj: &JsValue,
array_contents: &[JsValue],
context: &mut Context,
) -> Result<JsValue> {
let array_obj_ptr = array_obj.clone();

// Wipe existing contents of the array object
let orig_length = array_obj.get_field("length", context)?.to_length(context)?;
for n in 0..orig_length {
array_obj_ptr.remove_property(n);
}

// Create length
array_obj_ptr.set_property(
"length".to_string(),
PropertyDescriptor::builder()
.value(array_contents.len())
.writable(true)
.enumerable(false)
.configurable(false)
.build(),
);

for (n, value) in array_contents.iter().enumerate() {
array_obj_ptr.set_property(
n,
PropertyDescriptor::builder()
.value(value)
.configurable(true)
.enumerable(true)
.writable(true),
);
}
Ok(array_obj_ptr)
}

/// Utility function for concatenating array objects.
///
/// Returns a Boolean valued property that if `true` indicates that
Expand Down
11 changes: 6 additions & 5 deletions boa/src/builtins/map/map_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,14 @@ impl MapIterator {
));
}
MapIterationKind::KeyAndValue => {
let result = Array::construct_array(
&Array::new_array(context),
&[key.clone(), value.clone()],
let result = Array::create_array_from_list(
[key.clone(), value.clone()],
context,
)?;
);
return Ok(create_iter_result_object(
context, result, false,
context,
result.into(),
false,
));
}
}
Expand Down
11 changes: 6 additions & 5 deletions boa/src/builtins/set/set_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,14 @@ impl SetIterator {
));
}
SetIterationKind::KeyAndValue => {
let result = Array::construct_array(
&Array::new_array(context),
&[value.clone(), value.clone()],
let result = Array::create_array_from_list(
[value.clone(), value.clone()],
context,
)?;
);
return Ok(create_iter_result_object(
context, result, false,
context,
result.into(),
false,
));
}
}
Expand Down

0 comments on commit 0f380a9

Please sign in to comment.