use super::VaryingOperand;
use crate::{Context, JsResult, error::JsNativeError, vm::opcode::Operation};
#[derive(Debug, Clone, Copy)]
pub(crate) struct New;
impl New {
#[inline(always)]
pub(super) fn operation(argument_count: VaryingOperand, context: &mut Context) -> JsResult<()> {
let func = context
.vm
.stack
.calling_convention_get_function(argument_count.into());
let cons = func
.as_object()
.ok_or_else(|| JsNativeError::typ().with_message("not a constructor"))?
.clone();
context.vm.stack.push(cons.clone());
cons.__construct__(argument_count.into()).resolve(context)?;
Ok(())
}
}
impl Operation for New {
const NAME: &'static str = "New";
const INSTRUCTION: &'static str = "INST - New";
const COST: u8 = 3;
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct NewSpread;
impl NewSpread {
#[inline(always)]
pub(super) fn operation((): (), context: &mut Context) -> JsResult<()> {
let arguments_array = context.vm.stack.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.stack.pop();
let cons = func
.as_object()
.ok_or_else(|| JsNativeError::typ().with_message("not a constructor"))?
.clone();
let argument_count = arguments.len();
context.vm.stack.push(func);
context
.vm
.stack
.calling_convention_push_arguments(&arguments);
context.vm.stack.push(cons.clone());
cons.__construct__(argument_count).resolve(context)?;
Ok(())
}
}
impl Operation for NewSpread {
const NAME: &'static str = "NewSpread";
const INSTRUCTION: &'static str = "INST - NewSpread";
const COST: u8 = 3;
}