use crate::{
error::JsNativeError,
vm::{opcode::Operation, CompletionType},
Context, JsResult,
};
#[derive(Debug, Clone, Copy)]
pub(crate) struct New;
impl New {
fn operation(context: &mut Context, argument_count: usize) -> JsResult<CompletionType> {
let at = context.vm.stack.len() - argument_count;
let func = &context.vm.stack[at - 1];
let cons = func
.as_object()
.ok_or_else(|| JsNativeError::typ().with_message("not a constructor"))?
.clone();
context.vm.push(cons.clone());
cons.__construct__(argument_count).resolve(context)?;
Ok(CompletionType::Normal)
}
}
impl Operation for New {
const NAME: &'static str = "New";
const INSTRUCTION: &'static str = "INST - New";
const COST: u8 = 3;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let argument_count = context.vm.read::<u8>() as usize;
Self::operation(context, argument_count)
}
fn execute_with_u16_operands(context: &mut Context) -> JsResult<CompletionType> {
let argument_count = context.vm.read::<u16>() as usize;
Self::operation(context, argument_count)
}
fn execute_with_u32_operands(context: &mut Context) -> JsResult<CompletionType> {
let argument_count = context.vm.read::<u32>() as usize;
Self::operation(context, argument_count)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct NewSpread;
impl Operation for NewSpread {
const NAME: &'static str = "NewSpread";
const INSTRUCTION: &'static str = "INST - NewSpread";
const COST: u8 = 3;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let arguments_array = context.vm.pop();
let arguments_array_object = arguments_array
.as_object()
.expect("arguments array in call spread function must be an object");
let arguments = arguments_array_object
.borrow()
.properties()
.to_dense_indexed_properties()
.expect("arguments array in call spread function must be dense");
let func = context.vm.pop();
let cons = func
.as_object()
.ok_or_else(|| JsNativeError::typ().with_message("not a constructor"))?
.clone();
let argument_count = arguments.len();
context.vm.push(func);
context.vm.push_values(&arguments);
context.vm.push(cons.clone());
cons.__construct__(argument_count).resolve(context)?;
Ok(CompletionType::Normal)
}
}