use crate::{
Context, JsResult, JsValue,
error::JsNativeError,
object::PROTOTYPE,
vm::opcode::{Operation, VaryingOperand},
};
pub(crate) mod field;
pub(crate) mod private;
pub(crate) use field::*;
pub(crate) use private::*;
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassPrototype;
impl PushClassPrototype {
#[inline(always)]
pub(crate) fn operation(
(dst, class, superclass): (VaryingOperand, VaryingOperand, VaryingOperand),
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().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 PushClassPrototype {
const NAME: &'static str = "PushClassPrototype";
const INSTRUCTION: &'static str = "INST - PushClassPrototype";
const COST: u8 = 6;
}