use crate::{
builtins::function::OrdinaryFunction,
js_str, js_string,
object::{internal_methods::InternalMethodContext, PrivateElement},
property::PropertyDescriptor,
vm::{opcode::Operation, CompletionType},
Context, JsResult,
};
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassPrivateMethod;
impl PushClassPrivateMethod {
#[allow(clippy::unnecessary_wraps)]
fn operation(context: &mut Context, index: usize) -> JsResult<CompletionType> {
let name = context.vm.frame().code_block().constant_string(index);
let method = context.vm.pop();
let method_object = method.as_callable().expect("method must be callable");
let class_proto = context.vm.pop();
let class_proto_object = class_proto
.as_object()
.expect("class_proto must be function object");
let class = context.vm.pop();
let class_object = class.as_object().expect("class must be function object");
let name_string = js_string!(js_str!("#"), &name);
let desc = PropertyDescriptor::builder()
.value(name_string)
.writable(false)
.enumerable(false)
.configurable(true)
.build();
method_object
.__define_own_property__(
&js_str!("name").into(),
desc,
&mut InternalMethodContext::new(context),
)
.expect("failed to set name property on private method");
method_object
.downcast_mut::<OrdinaryFunction>()
.expect("method must be function object")
.set_home_object(class_proto_object.clone());
class_object
.downcast_mut::<OrdinaryFunction>()
.expect("class must be function object")
.push_private_method(
class_object.private_name(name),
PrivateElement::Method(method_object.clone()),
);
Ok(CompletionType::Normal)
}
}
impl Operation for PushClassPrivateMethod {
const NAME: &'static str = "PushClassPrivateMethod";
const INSTRUCTION: &'static str = "INST - PushClassPrivateMethod";
const COST: u8 = 6;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize;
Self::operation(context, index)
}
fn execute_with_u16_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u16>() as usize;
Self::operation(context, index)
}
fn execute_with_u32_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u32>() as usize;
Self::operation(context, index)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassPrivateGetter;
impl PushClassPrivateGetter {
#[allow(clippy::unnecessary_wraps)]
fn operation(context: &mut Context, index: usize) -> JsResult<CompletionType> {
let name = context.vm.frame().code_block().constant_string(index);
let getter = context.vm.pop();
let getter_object = getter.as_callable().expect("getter must be callable");
let class = context.vm.pop();
let class_object = class.as_object().expect("class must be function object");
class_object
.downcast_mut::<OrdinaryFunction>()
.expect("class must be function object")
.push_private_method(
class_object.private_name(name),
PrivateElement::Accessor {
getter: Some(getter_object.clone()),
setter: None,
},
);
Ok(CompletionType::Normal)
}
}
impl Operation for PushClassPrivateGetter {
const NAME: &'static str = "PushClassPrivateGetter";
const INSTRUCTION: &'static str = "INST - PushClassPrivateGetter";
const COST: u8 = 6;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize;
Self::operation(context, index)
}
fn execute_with_u16_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u16>() as usize;
Self::operation(context, index)
}
fn execute_with_u32_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u32>() as usize;
Self::operation(context, index)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassPrivateSetter;
impl PushClassPrivateSetter {
#[allow(clippy::unnecessary_wraps)]
fn operation(context: &mut Context, index: usize) -> JsResult<CompletionType> {
let name = context.vm.frame().code_block().constant_string(index);
let setter = context.vm.pop();
let setter_object = setter.as_callable().expect("getter must be callable");
let class = context.vm.pop();
let class_object = class.as_object().expect("class must be function object");
class_object
.downcast_mut::<OrdinaryFunction>()
.expect("class must be function object")
.push_private_method(
class_object.private_name(name),
PrivateElement::Accessor {
getter: None,
setter: Some(setter_object.clone()),
},
);
Ok(CompletionType::Normal)
}
}
impl Operation for PushClassPrivateSetter {
const NAME: &'static str = "PushClassPrivateSetter";
const INSTRUCTION: &'static str = "INST - PushClassPrivateSetter";
const COST: u8 = 6;
fn execute(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u8>() as usize;
Self::operation(context, index)
}
fn execute_with_u16_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u16>() as usize;
Self::operation(context, index)
}
fn execute_with_u32_operands(context: &mut Context) -> JsResult<CompletionType> {
let index = context.vm.read::<u32>() as usize;
Self::operation(context, index)
}
}