Skip to content

Commit

Permalink
Close iterator after generator return call while array destructuring …
Browse files Browse the repository at this point in the history
…assignment (#3164)

* Close iterator after generator return while array destructuring

* Add MaybeException opcode and remove handler check
  • Loading branch information
HalidOdat authored Jul 30, 2023
1 parent be055a3 commit 2b01ef1
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 14 deletions.
10 changes: 3 additions & 7 deletions boa_engine/src/bytecompiler/declaration/declaration_pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,19 +180,15 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::ValueNotNullOrUndefined);
self.emit_opcode(Opcode::GetIterator);

// TODO: maybe, refactor this to be more condensed.
let handler_index = self.push_handler();
for element in pattern.bindings() {
self.compile_array_pattern_element(element, def);
}

self.emit_opcode(Opcode::PushFalse);

let exit = self.jump();
self.patch_handler(handler_index);
self.emit_opcode(Opcode::Exception);
self.emit_opcode(Opcode::PushTrue);
self.patch_jump(exit);
self.emit_opcode(Opcode::MaybeException);

// stack: hasPending, exception?

self.current_stack_value_count += 2;

Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/vm/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ impl CodeBlock {
| Opcode::Throw
| Opcode::ReThrow
| Opcode::Exception
| Opcode::MaybeException
| Opcode::This
| Opcode::Super
| Opcode::Return
Expand Down Expand Up @@ -677,8 +678,7 @@ impl CodeBlock {
| Opcode::Reserved60
| Opcode::Reserved61
| Opcode::Reserved62
| Opcode::Reserved63
| Opcode::Reserved64 => unreachable!("Reserved opcodes are unrechable"),
| Opcode::Reserved63 => unreachable!("Reserved opcodes are unrechable"),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/vm/flowgraph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ impl CodeBlock {
| Opcode::GetReturnValue
| Opcode::SetReturnValue
| Opcode::Exception
| Opcode::MaybeException
| Opcode::Nop => {
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
Expand Down Expand Up @@ -606,8 +607,7 @@ impl CodeBlock {
| Opcode::Reserved60
| Opcode::Reserved61
| Opcode::Reserved62
| Opcode::Reserved63
| Opcode::Reserved64 => unreachable!("Reserved opcodes are unrechable"),
| Opcode::Reserved63 => unreachable!("Reserved opcodes are unrechable"),
}
}

Expand Down
24 changes: 24 additions & 0 deletions boa_engine/src/vm/opcode/control_flow/throw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,30 @@ impl Operation for Exception {
}
}

/// `MaybeException` implements the Opcode Operation for `Opcode::MaybeException`
///
/// Operation:
/// - Get the thrown pending exception if it's set and push `true`, otherwise push only `false`.
#[derive(Debug, Clone, Copy)]
pub(crate) struct MaybeException;

impl Operation for MaybeException {
const NAME: &'static str = "MaybeException";
const INSTRUCTION: &'static str = "INST - MaybeException";

fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
if let Some(error) = context.vm.pending_exception.take() {
let error = error.to_opaque(context);
context.vm.push(error);
context.vm.push(true);
return Ok(CompletionType::Normal);
}

context.vm.push(false);
Ok(CompletionType::Normal)
}
}

/// `ThrowNewTypeError` implements the Opcode Operation for `Opcode::ThrowNewTypeError`
///
/// Operation:
Expand Down
11 changes: 8 additions & 3 deletions boa_engine/src/vm/opcode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,7 @@ generate_impl! {
/// Stack: **=>**
ReThrow,

/// Get the thrown pending exception and push on the stack.
/// Get the thrown pending exception (if it's set) and push on the stack.
///
/// If there is no pending exception, which can happend if we are handling `return()` call on generator,
/// then we rethrow the empty exception. See [`Opcode::ReThrow`].
Expand All @@ -1157,6 +1157,13 @@ generate_impl! {
/// Stack: **=>** exception
Exception,

/// Get the thrown pending exception if it's set and push `true`, otherwise push only `false`.
///
/// Operands:
///
/// Stack: **=>** (`true`, exception) or `false`
MaybeException,

/// Throw a new `TypeError` exception
///
/// Operands: message: u32
Expand Down Expand Up @@ -1764,8 +1771,6 @@ generate_impl! {
Reserved62 => Reserved,
/// Reserved [`Opcode`].
Reserved63 => Reserved,
/// Reserved [`Opcode`].
Reserved64 => Reserved,
}
}

Expand Down

0 comments on commit 2b01ef1

Please sign in to comment.