boa_engine/vm/opcode/control_flow/
throw.rs1use crate::{
2 vm::{opcode::Operation, CompletionType},
3 Context, JsError, JsNativeError, JsResult,
4};
5
6#[derive(Debug, Clone, Copy)]
11pub(crate) struct Throw;
12
13impl Operation for Throw {
14 const NAME: &'static str = "Throw";
15 const INSTRUCTION: &'static str = "INST - Throw";
16 const COST: u8 = 6;
17
18 fn execute(context: &mut Context) -> JsResult<CompletionType> {
19 let error = JsError::from_opaque(context.vm.pop());
20 context.vm.pending_exception = Some(error);
21
22 let pc = context.vm.frame().pc - 1;
24 if context.vm.handle_exception_at(pc) {
25 return Ok(CompletionType::Normal);
26 }
27
28 Ok(CompletionType::Throw)
29 }
30}
31
32#[derive(Debug, Clone, Copy)]
37pub(crate) struct ReThrow;
38
39impl Operation for ReThrow {
40 const NAME: &'static str = "ReThrow";
41 const INSTRUCTION: &'static str = "INST - ReThrow";
42 const COST: u8 = 2;
43
44 fn execute(context: &mut Context) -> JsResult<CompletionType> {
45 let pc = context.vm.frame().pc.saturating_sub(1);
47 if context.vm.handle_exception_at(pc) {
48 return Ok(CompletionType::Normal);
49 }
50
51 if context.vm.pending_exception.is_none() {
57 return Ok(CompletionType::Return);
58 }
59
60 Ok(CompletionType::Throw)
61 }
62}
63
64#[derive(Debug, Clone, Copy)]
69pub(crate) struct Exception;
70
71impl Operation for Exception {
72 const NAME: &'static str = "Exception";
73 const INSTRUCTION: &'static str = "INST - Exception";
74 const COST: u8 = 2;
75
76 fn execute(context: &mut Context) -> JsResult<CompletionType> {
77 if let Some(error) = context.vm.pending_exception.take() {
78 let error = error.to_opaque(context);
79 context.vm.push(error);
80 return Ok(CompletionType::Normal);
81 }
82
83 ReThrow::execute(context)
89 }
90}
91
92#[derive(Debug, Clone, Copy)]
97pub(crate) struct MaybeException;
98
99impl Operation for MaybeException {
100 const NAME: &'static str = "MaybeException";
101 const INSTRUCTION: &'static str = "INST - MaybeException";
102 const COST: u8 = 3;
103
104 fn execute(context: &mut Context) -> JsResult<CompletionType> {
105 if let Some(error) = context.vm.pending_exception.take() {
106 let error = error.to_opaque(context);
107 context.vm.push(error);
108 context.vm.push(true);
109 return Ok(CompletionType::Normal);
110 }
111
112 context.vm.push(false);
113 Ok(CompletionType::Normal)
114 }
115}
116
117#[derive(Debug, Clone, Copy)]
122pub(crate) struct ThrowNewTypeError;
123
124impl ThrowNewTypeError {
125 fn operation(context: &mut Context, index: usize) -> JsResult<CompletionType> {
126 let msg = context.vm.frame().code_block().constant_string(index);
127 let msg = msg
128 .to_std_string()
129 .expect("throw message must be an ASCII string");
130 Err(JsNativeError::typ().with_message(msg).into())
131 }
132}
133
134impl Operation for ThrowNewTypeError {
135 const NAME: &'static str = "ThrowNewTypeError";
136 const INSTRUCTION: &'static str = "INST - ThrowNewTypeError";
137 const COST: u8 = 2;
138
139 fn execute(context: &mut Context) -> JsResult<CompletionType> {
140 let index = context.vm.read::<u8>() as usize;
141 Self::operation(context, index)
142 }
143
144 fn execute_with_u16_operands(context: &mut Context) -> JsResult<CompletionType> {
145 let index = context.vm.read::<u16>() as usize;
146 Self::operation(context, index)
147 }
148
149 fn execute_with_u32_operands(context: &mut Context) -> JsResult<CompletionType> {
150 let index = context.vm.read::<u32>() as usize;
151 Self::operation(context, index)
152 }
153}
154
155#[derive(Debug, Clone, Copy)]
160pub(crate) struct ThrowNewSyntaxError;
161
162impl ThrowNewSyntaxError {
163 fn operation(context: &mut Context, index: usize) -> JsResult<CompletionType> {
164 let msg = context.vm.frame().code_block().constant_string(index);
165 let msg = msg
166 .to_std_string()
167 .expect("throw message must be an ASCII string");
168 Err(JsNativeError::syntax().with_message(msg).into())
169 }
170}
171
172impl Operation for ThrowNewSyntaxError {
173 const NAME: &'static str = "ThrowNewSyntaxError";
174 const INSTRUCTION: &'static str = "INST - ThrowNewSyntaxError";
175 const COST: u8 = 2;
176
177 fn execute(context: &mut Context) -> JsResult<CompletionType> {
178 let index = context.vm.read::<u8>() as usize;
179 Self::operation(context, index)
180 }
181
182 fn execute_with_u16_operands(context: &mut Context) -> JsResult<CompletionType> {
183 let index = context.vm.read::<u16>() as usize;
184 Self::operation(context, index)
185 }
186
187 fn execute_with_u32_operands(context: &mut Context) -> JsResult<CompletionType> {
188 let index = context.vm.read::<u32>() as usize;
189 Self::operation(context, index)
190 }
191}