use crate::{
vm::{opcode::Operation, CompletionType},
Context, JsError, JsNativeError, JsResult,
};
#[derive(Debug, Clone, Copy)]
pub(crate) struct Throw;
impl Operation for Throw {
const NAME: &'static str = "Throw";
const INSTRUCTION: &'static str = "INST - Throw";
const COST: u8 = 6;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let error = JsError::from_opaque(context.vm.pop());
context.vm.pending_exception = Some(error);
let pc = context.vm.frame().pc - 1;
if context.vm.handle_exception_at(pc) {
return Ok(CompletionType::Normal);
}
Ok(CompletionType::Throw)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct ReThrow;
impl Operation for ReThrow {
const NAME: &'static str = "ReThrow";
const INSTRUCTION: &'static str = "INST - ReThrow";
const COST: u8 = 2;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let pc = context.vm.frame().pc.saturating_sub(1);
if context.vm.handle_exception_at(pc) {
return Ok(CompletionType::Normal);
}
if context.vm.pending_exception.is_none() {
return Ok(CompletionType::Return);
}
Ok(CompletionType::Throw)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct Exception;
impl Operation for Exception {
const NAME: &'static str = "Exception";
const INSTRUCTION: &'static str = "INST - Exception";
const COST: u8 = 2;
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);
return Ok(CompletionType::Normal);
}
ReThrow::execute(context)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct MaybeException;
impl Operation for MaybeException {
const NAME: &'static str = "MaybeException";
const INSTRUCTION: &'static str = "INST - MaybeException";
const COST: u8 = 3;
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)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct ThrowNewTypeError;
impl ThrowNewTypeError {
fn operation(context: &mut Context, index: usize) -> JsResult<CompletionType> {
let msg = context.vm.frame().code_block().constant_string(index);
let msg = msg
.to_std_string()
.expect("throw message must be an ASCII string");
Err(JsNativeError::typ().with_message(msg).into())
}
}
impl Operation for ThrowNewTypeError {
const NAME: &'static str = "ThrowNewTypeError";
const INSTRUCTION: &'static str = "INST - ThrowNewTypeError";
const COST: u8 = 2;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize;
Self::operation(context, index)
}
fn execute_with_u16_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u16>() as usize;
Self::operation(context, index)
}
fn execute_with_u32_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u32>() as usize;
Self::operation(context, index)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct ThrowNewSyntaxError;
impl ThrowNewSyntaxError {
fn operation(context: &mut Context, index: usize) -> JsResult<CompletionType> {
let msg = context.vm.frame().code_block().constant_string(index);
let msg = msg
.to_std_string()
.expect("throw message must be an ASCII string");
Err(JsNativeError::syntax().with_message(msg).into())
}
}
impl Operation for ThrowNewSyntaxError {
const NAME: &'static str = "ThrowNewSyntaxError";
const INSTRUCTION: &'static str = "INST - ThrowNewSyntaxError";
const COST: u8 = 2;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize;
Self::operation(context, index)
}
fn execute_with_u16_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u16>() as usize;
Self::operation(context, index)
}
fn execute_with_u32_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u32>() as usize;
Self::operation(context, index)
}
}