Browse Source

[exec Array] implement spread operator using iterator (#811)

pull/849/head
croraf 4 years ago committed by GitHub
parent
commit
4e41b44f75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      boa/src/builtins/array/tests.rs
  2. 2
      boa/src/builtins/map/tests.rs
  3. 1
      boa/src/context.rs
  4. 27
      boa/src/syntax/ast/node/array/mod.rs

24
boa/src/builtins/array/tests.rs

@ -1210,3 +1210,27 @@ fn array_values_symbol_iterator() {
"#;
assert_eq!(forward(&mut engine, init), "true");
}
#[test]
fn array_spread_arrays() {
let mut engine = Context::new();
let init = r#"
const array1 = [2, 3];
const array2 = [1, ...array1];
array2[0] === 1 && array2[1] === 2 && array2[2] === 3;
"#;
assert_eq!(forward(&mut engine, init), "true");
}
#[test]
fn array_spread_non_iterable() {
let mut engine = Context::new();
let init = r#"
try {
const array2 = [...5];
} catch (err) {
err.name === "TypeError" && err.message === "Not an iterable"
}
"#;
assert_eq!(forward(&mut engine, init), "true");
}

2
boa/src/builtins/map/tests.rs

@ -43,7 +43,9 @@ fn clone() {
assert_eq!(result, "2");
}
// TODO depends on the https://github.com/boa-dev/boa/issues/810
#[test]
#[ignore]
fn merge() {
let mut engine = Context::new();
let init = r#"

1
boa/src/context.rs

@ -508,6 +508,7 @@ impl Context {
/// Converts an array object into a rust vector of values.
///
/// This is useful for the spread operator, for any other object an `Err` is returned
/// TODO: Not needed for spread of arrays. Check in the future for Map and remove if necessary
pub(crate) fn extract_array_properties(&mut self, value: &Value) -> StdResult<Vec<Value>, ()> {
if let Value::Object(ref x) = value {
// Check if object is array

27
boa/src/syntax/ast/node/array/mod.rs

@ -1,7 +1,11 @@
//! Array declaration node.
use super::{join_nodes, Node};
use crate::{builtins::Array, exec::Executable, BoaProfiler, Context, Result, Value};
use crate::{
builtins::{iterable, Array},
exec::Executable,
BoaProfiler, Context, Result, Value,
};
use gc::{Finalize, Trace};
use std::fmt;
@ -39,14 +43,25 @@ impl Executable for ArrayDecl {
for elem in self.as_ref() {
if let Node::Spread(ref x) = elem {
let val = x.run(interpreter)?;
let mut vals = interpreter.extract_array_properties(&val).unwrap();
elements.append(&mut vals);
continue; // Don't push array after spread
let iterator_record = iterable::get_iterator(interpreter, val)?;
// TODO after proper internal Array representation as per https://github.com/boa-dev/boa/pull/811#discussion_r502460858
// next_index variable should be utilized here as per https://tc39.es/ecma262/#sec-runtime-semantics-arrayaccumulation
// let mut next_index = 0;
loop {
let next = iterator_record.next(interpreter)?;
if next.is_done() {
break;
}
let next_value = next.value();
//next_index += 1;
elements.push(next_value.clone());
}
} else {
elements.push(elem.run(interpreter)?);
}
elements.push(elem.run(interpreter)?);
}
Array::add_to_array_object(&array, &elements)?;
Array::add_to_array_object(&array, &elements)?;
Ok(array)
}
}

Loading…
Cancel
Save