use crate::{
error::JsNativeError,
object::PROTOTYPE,
vm::{opcode::Operation, CompletionType},
Context, JsResult, JsValue,
};
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 Operation for PushClassPrototype {
const NAME: &'static str = "PushClassPrototype";
const INSTRUCTION: &'static str = "INST - PushClassPrototype";
const COST: u8 = 6;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let superclass = context.vm.pop();
let class = context.vm.pop();
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.push(class);
context.vm.push(proto_parent);
Ok(CompletionType::Normal)
}
}