Browse Source

Fix spread in new and call expressions (#1021)

* Fix spread in new and call expressions

* Fix formatting

* Add unit tests

* Fix unit test

Co-authored-by: tofpie <tofpie@users.noreply.github.com>
pull/1023/head
tofpie 4 years ago committed by GitHub
parent
commit
a77c879298
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      boa/src/syntax/ast/node/call/mod.rs
  2. 17
      boa/src/syntax/ast/node/new/mod.rs
  3. 3
      boa/src/syntax/ast/node/spread/mod.rs
  4. 31
      boa/src/syntax/ast/node/spread/tests.rs

15
boa/src/syntax/ast/node/call/mod.rs

@ -1,4 +1,5 @@
use crate::{
builtins::iterable,
exec::Executable,
exec::InterpreterState,
gc::{Finalize, Trace},
@ -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

17
boa/src/syntax/ast/node/new/mod.rs

@ -1,4 +1,5 @@
use crate::{
builtins::iterable,
exec::Executable,
gc::{Finalize, Trace},
syntax::ast::node::{Call, Node},
@ -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 {

3
boa/src/syntax/ast/node/spread/mod.rs

@ -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.
///

31
boa/src/syntax/ast/node/spread/tests.rs

@ -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""#);
}
Loading…
Cancel
Save