Skip to content

Commit

Permalink
Fix spread in new and call expressions (#1021)
Browse files Browse the repository at this point in the history
* Fix spread in new and call expressions

* Fix formatting

* Add unit tests

* Fix unit test

Co-authored-by: tofpie <tofpie@users.noreply.github.com>
  • Loading branch information
tofpie and tofpie authored Jan 1, 2021
1 parent d6a5947 commit a77c879
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 4 deletions.
15 changes: 12 additions & 3 deletions boa/src/syntax/ast/node/call/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
builtins::iterable,
exec::Executable,
exec::InterpreterState,
gc::{Finalize, Trace},
Expand Down Expand Up @@ -84,11 +85,19 @@ impl Executable for Call {
for arg in self.args() {
if let Node::Spread(ref x) = arg {
let val = x.run(context)?;
let mut vals = context.extract_array_properties(&val)?.unwrap();
v_args.append(&mut vals);
let iterator_record = iterable::get_iterator(context, val)?;
loop {
let next = iterator_record.next(context)?;
if next.is_done() {
break;
}
let next_value = next.value();
v_args.push(next_value.clone());
}
break; // after spread we don't accept any new arguments
} else {
v_args.push(arg.run(context)?);
}
v_args.push(arg.run(context)?);
}

// execute the function call itself
Expand Down
17 changes: 16 additions & 1 deletion boa/src/syntax/ast/node/new/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
builtins::iterable,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{Call, Node},
Expand Down Expand Up @@ -50,7 +51,21 @@ impl Executable for New {
let func_object = self.expr().run(context)?;
let mut v_args = Vec::with_capacity(self.args().len());
for arg in self.args() {
v_args.push(arg.run(context)?);
if let Node::Spread(ref x) = arg {
let val = x.run(context)?;
let iterator_record = iterable::get_iterator(context, val)?;
loop {
let next = iterator_record.next(context)?;
if next.is_done() {
break;
}
let next_value = next.value();
v_args.push(next_value.clone());
}
break; // after spread we don't accept any new arguments
} else {
v_args.push(arg.run(context)?);
}
}

match func_object {
Expand Down
3 changes: 3 additions & 0 deletions boa/src/syntax/ast/node/spread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use std::fmt;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};

#[cfg(test)]
mod tests;

/// The `spread` operator allows an iterable such as an array expression or string to be
/// expanded.
///
Expand Down
31 changes: 31 additions & 0 deletions boa/src/syntax/ast/node/spread/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::exec;

#[test]
fn spread_with_new() {
let scenario = r#"
function F(m) {
this.m = m;
}
function f(...args) {
return new F(...args);
}
let a = f('message');
a.m;
"#;
assert_eq!(&exec(scenario), r#""message""#);
}

#[test]
fn spread_with_call() {
let scenario = r#"
function f(m) {
return m;
}
function g(...args) {
return f(...args);
}
let a = g('message');
a;
"#;
assert_eq!(&exec(scenario), r#""message""#);
}

0 comments on commit a77c879

Please sign in to comment.