Browse Source

Return the correct value from a statement list (#2554)

When compiling a statement list we need to make sure that the last expression that returns a value is compiled with the `use_expr` flag. Currently we set `use_expr` on the last statement of the statement list. This leads to incorrect returns when the last statement does not return a value. This PR fixes this by looking up the last value returning expression in a statement list  and setting the `use_expr` appropriately.
pull/2559/head
raskad 2 years ago
parent
commit
96a6e0a346
  1. 46
      boa_engine/src/bytecompiler/mod.rs

46
boa_engine/src/bytecompiler/mod.rs

@ -660,17 +660,26 @@ impl<'b, 'host> ByteCompiler<'b, 'host> {
use_expr: bool, use_expr: bool,
configurable_globals: bool, configurable_globals: bool,
) -> JsResult<()> { ) -> JsResult<()> {
let mut items = list if use_expr {
let expr_index = list
.statements() .statements()
.iter() .iter()
.filter(|item| item != &&StatementListItem::Statement(Statement::Empty)) .rev()
.peekable(); .skip_while(|item| {
matches!(
item,
&&StatementListItem::Statement(Statement::Empty | Statement::Var(_))
| &&StatementListItem::Declaration(_)
)
})
.count();
while let Some(item) = items.next() { for (i, item) in list.statements().iter().enumerate() {
if items.peek().is_some() { self.compile_stmt_list_item(item, i + 1 == expr_index, configurable_globals)?;
self.compile_stmt_list_item(item, false, configurable_globals)?; }
} else { } else {
self.compile_stmt_list_item(item, use_expr, configurable_globals)?; for item in list.statements() {
self.compile_stmt_list_item(item, false, configurable_globals)?;
} }
} }
@ -689,17 +698,26 @@ impl<'b, 'host> ByteCompiler<'b, 'host> {
self.create_decls(list, true); self.create_decls(list, true);
let mut items = list if use_expr {
let expr_index = list
.statements() .statements()
.iter() .iter()
.filter(|item| item != &&StatementListItem::Statement(Statement::Empty)) .rev()
.peekable(); .skip_while(|item| {
matches!(
item,
&&StatementListItem::Statement(Statement::Empty | Statement::Var(_))
| &&StatementListItem::Declaration(_)
)
})
.count();
while let Some(item) = items.next() { for (i, item) in list.statements().iter().enumerate() {
if items.peek().is_some() { self.compile_stmt_list_item(item, i + 1 == expr_index, true)?;
self.compile_stmt_list_item(item, false, true)?; }
} else { } else {
self.compile_stmt_list_item(item, use_expr, true)?; for item in list.statements() {
self.compile_stmt_list_item(item, false, true)?;
} }
} }

Loading…
Cancel
Save