mirror of https://github.com/boa-dev/boa.git
Haled Odat
1 year ago
committed by
GitHub
30 changed files with 314 additions and 633 deletions
@ -1,33 +1,18 @@ |
|||||||
use crate::{bytecompiler::ByteCompiler, vm::Opcode}; |
use crate::bytecompiler::ByteCompiler; |
||||||
use boa_ast::{operations::returns_value, statement::If}; |
use boa_ast::statement::If; |
||||||
|
|
||||||
impl ByteCompiler<'_, '_> { |
impl ByteCompiler<'_, '_> { |
||||||
pub(crate) fn compile_if(&mut self, node: &If, use_expr: bool) { |
pub(crate) fn compile_if(&mut self, node: &If, use_expr: bool) { |
||||||
self.compile_expr(node.cond(), true); |
self.compile_expr(node.cond(), true); |
||||||
let jelse = self.jump_if_false(); |
let jelse = self.jump_if_false(); |
||||||
|
|
||||||
if !returns_value(node.body()) { |
self.compile_stmt(node.body(), use_expr, true); |
||||||
self.emit_opcode(Opcode::PushUndefined); |
|
||||||
} |
|
||||||
self.compile_stmt(node.body(), true); |
|
||||||
|
|
||||||
let exit = self.jump(); |
let exit = self.jump(); |
||||||
self.patch_jump(jelse); |
self.patch_jump(jelse); |
||||||
match node.else_node() { |
if let Some(else_body) = node.else_node() { |
||||||
None => { |
self.compile_stmt(else_body, use_expr, true); |
||||||
self.emit_opcode(Opcode::PushUndefined); |
|
||||||
} |
|
||||||
Some(else_body) => { |
|
||||||
if !returns_value(else_body) { |
|
||||||
self.emit_opcode(Opcode::PushUndefined); |
|
||||||
} |
|
||||||
self.compile_stmt(else_body, true); |
|
||||||
} |
|
||||||
} |
} |
||||||
self.patch_jump(exit); |
self.patch_jump(exit); |
||||||
|
|
||||||
if !use_expr { |
|
||||||
self.emit_opcode(Opcode::Pop); |
|
||||||
} |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -1,91 +0,0 @@ |
|||||||
use crate::{ |
|
||||||
vm::{call_frame::EnvStackEntry, opcode::Operation, CompletionType}, |
|
||||||
Context, JsResult, |
|
||||||
}; |
|
||||||
|
|
||||||
/// `CatchStart` implements the Opcode Operation for `Opcode::CatchStart`
|
|
||||||
///
|
|
||||||
/// Operation:
|
|
||||||
/// - Start of a catch block.
|
|
||||||
#[derive(Debug, Clone, Copy)] |
|
||||||
pub(crate) struct CatchStart; |
|
||||||
|
|
||||||
impl Operation for CatchStart { |
|
||||||
const NAME: &'static str = "CatchStart"; |
|
||||||
const INSTRUCTION: &'static str = "INST - CatchStart"; |
|
||||||
|
|
||||||
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { |
|
||||||
let start = context.vm.frame().pc - 1; |
|
||||||
let finally = context.vm.read::<u32>(); |
|
||||||
|
|
||||||
context |
|
||||||
.vm |
|
||||||
.frame_mut() |
|
||||||
.env_stack |
|
||||||
.push(EnvStackEntry::new(start, finally - 1).with_catch_flag()); |
|
||||||
|
|
||||||
context.vm.frame_mut().abrupt_completion = None; |
|
||||||
Ok(CompletionType::Normal) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// `CatchEnd` implements the Opcode Operation for `Opcode::CatchEnd`
|
|
||||||
///
|
|
||||||
/// Operation:
|
|
||||||
/// - End of a catch block.
|
|
||||||
#[derive(Debug, Clone, Copy)] |
|
||||||
pub(crate) struct CatchEnd; |
|
||||||
|
|
||||||
impl Operation for CatchEnd { |
|
||||||
const NAME: &'static str = "CatchEnd"; |
|
||||||
const INSTRUCTION: &'static str = "INST - CatchEnd"; |
|
||||||
|
|
||||||
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { |
|
||||||
let mut envs_to_pop = 0_usize; |
|
||||||
while let Some(env_entry) = context.vm.frame_mut().env_stack.pop() { |
|
||||||
envs_to_pop += env_entry.env_num(); |
|
||||||
|
|
||||||
if env_entry.is_catch_env() { |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
let env_truncation_len = context.vm.environments.len().saturating_sub(envs_to_pop); |
|
||||||
context.vm.environments.truncate(env_truncation_len); |
|
||||||
|
|
||||||
Ok(CompletionType::Normal) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// `CatchEnd2` implements the Opcode Operation for `Opcode::CatchEnd2`
|
|
||||||
///
|
|
||||||
/// Operation:
|
|
||||||
/// - End of a catch block
|
|
||||||
#[derive(Debug, Clone, Copy)] |
|
||||||
pub(crate) struct CatchEnd2; |
|
||||||
|
|
||||||
impl Operation for CatchEnd2 { |
|
||||||
const NAME: &'static str = "CatchEnd2"; |
|
||||||
const INSTRUCTION: &'static str = "INST - CatchEnd2"; |
|
||||||
|
|
||||||
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { |
|
||||||
if let Some(catch_entry) = context |
|
||||||
.vm |
|
||||||
.frame() |
|
||||||
.env_stack |
|
||||||
.last() |
|
||||||
.filter(|entry| entry.is_catch_env()) |
|
||||||
{ |
|
||||||
let env_truncation_len = context |
|
||||||
.vm |
|
||||||
.environments |
|
||||||
.len() |
|
||||||
.saturating_sub(catch_entry.env_num()); |
|
||||||
context.vm.environments.truncate(env_truncation_len); |
|
||||||
|
|
||||||
context.vm.frame_mut().env_stack.pop(); |
|
||||||
} |
|
||||||
|
|
||||||
Ok(CompletionType::Normal) |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue