diff --git a/boa/src/builtins/array/tests.rs b/boa/src/builtins/array/tests.rs index 876de0e853..464383d75b 100644 --- a/boa/src/builtins/array/tests.rs +++ b/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"); +} diff --git a/boa/src/builtins/map/tests.rs b/boa/src/builtins/map/tests.rs index 761cbdf025..fa714cc896 100644 --- a/boa/src/builtins/map/tests.rs +++ b/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#" diff --git a/boa/src/context.rs b/boa/src/context.rs index e94b1f9eb5..82a3350a3a 100644 --- a/boa/src/context.rs +++ b/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, ()> { if let Value::Object(ref x) = value { // Check if object is array diff --git a/boa/src/syntax/ast/node/array/mod.rs b/boa/src/syntax/ast/node/array/mod.rs index b98f951494..02dda7badd 100644 --- a/boa/src/syntax/ast/node/array/mod.rs +++ b/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) } }