From 2b01ef1c2780e5a82b9660717ead021edce6e280 Mon Sep 17 00:00:00 2001 From: Haled Odat <8566042+HalidOdat@users.noreply.github.com> Date: Sun, 30 Jul 2023 05:50:15 +0200 Subject: [PATCH] Close iterator after generator return call while array destructuring assignment (#3164) * Close iterator after generator return while array destructuring * Add MaybeException opcode and remove handler check --- .../declaration/declaration_pattern.rs | 10 +++----- boa_engine/src/vm/code_block.rs | 4 ++-- boa_engine/src/vm/flowgraph/mod.rs | 4 ++-- .../src/vm/opcode/control_flow/throw.rs | 24 +++++++++++++++++++ boa_engine/src/vm/opcode/mod.rs | 11 ++++++--- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/boa_engine/src/bytecompiler/declaration/declaration_pattern.rs b/boa_engine/src/bytecompiler/declaration/declaration_pattern.rs index 17a9bd4c12..a0a34b723c 100644 --- a/boa_engine/src/bytecompiler/declaration/declaration_pattern.rs +++ b/boa_engine/src/bytecompiler/declaration/declaration_pattern.rs @@ -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; diff --git a/boa_engine/src/vm/code_block.rs b/boa_engine/src/vm/code_block.rs index 1cf0bf5361..bce2c9ece8 100644 --- a/boa_engine/src/vm/code_block.rs +++ b/boa_engine/src/vm/code_block.rs @@ -566,6 +566,7 @@ impl CodeBlock { | Opcode::Throw | Opcode::ReThrow | Opcode::Exception + | Opcode::MaybeException | Opcode::This | Opcode::Super | Opcode::Return @@ -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"), } } } diff --git a/boa_engine/src/vm/flowgraph/mod.rs b/boa_engine/src/vm/flowgraph/mod.rs index 4499331ba2..ff210e418c 100644 --- a/boa_engine/src/vm/flowgraph/mod.rs +++ b/boa_engine/src/vm/flowgraph/mod.rs @@ -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); @@ -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"), } } diff --git a/boa_engine/src/vm/opcode/control_flow/throw.rs b/boa_engine/src/vm/opcode/control_flow/throw.rs index b5c31bea48..a9843ad8ec 100644 --- a/boa_engine/src/vm/opcode/control_flow/throw.rs +++ b/boa_engine/src/vm/opcode/control_flow/throw.rs @@ -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 { + 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: diff --git a/boa_engine/src/vm/opcode/mod.rs b/boa_engine/src/vm/opcode/mod.rs index d43841c732..f67794efa8 100644 --- a/boa_engine/src/vm/opcode/mod.rs +++ b/boa_engine/src/vm/opcode/mod.rs @@ -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`]. @@ -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 @@ -1764,8 +1771,6 @@ generate_impl! { Reserved62 => Reserved, /// Reserved [`Opcode`]. Reserved63 => Reserved, - /// Reserved [`Opcode`]. - Reserved64 => Reserved, } }