use crate::{
Context, JsExpect, JsResult, JsValue,
error::JsNativeError,
object::PROTOTYPE,
vm::opcode::{Operation, RegisterOperand},
};
pub(crate) mod field;
pub(crate) mod private;
pub(crate) use field::*;
pub(crate) use private::*;
#[derive(Debug, Clone, Copy)]
pub(crate) struct StoreClassPrototype;
impl StoreClassPrototype {
#[inline(always)]
pub(crate) fn operation(
(dst, class, superclass): (RegisterOperand, RegisterOperand, RegisterOperand),
context: &mut Context,
) -> JsResult<()> {
let class = context.vm.get_register(class.into()).clone();
let superclass = context.vm.get_register(superclass.into()).clone();
let (proto_parent, constructor_parent) = if superclass.is_null() {
(JsValue::null(), None)
} else if let Some(superclass) = superclass.as_constructor() {
let proto = superclass.get(PROTOTYPE, context)?;
if !proto.is_object() && !proto.is_null() {
return Err(JsNativeError::typ()
.with_message("superclass prototype must be an object or null")
.into());
}
(proto, Some(superclass.clone()))
} else {
return Err(JsNativeError::typ()
.with_message("superclass must be a constructor")
.into());
};
let class_object = class.as_object().js_expect("class must be object")?;
if let Some(constructor_parent) = constructor_parent {
class_object.set_prototype(Some(constructor_parent));
}
context.vm.set_register(dst.into(), proto_parent);
Ok(())
}
}
impl Operation for StoreClassPrototype {
const NAME: &'static str = "StoreClassPrototype";
const INSTRUCTION: &'static str = "INST - StoreClassPrototype";
const COST: u8 = 6;
}