use crate::{
builtins::array::Array,
object::IntegrityLevel,
property::PropertyDescriptor,
vm::{opcode::Operation, CompletionType},
Context, JsResult,
};
use boa_macros::utf16;
#[derive(Debug, Clone, Copy)]
pub(crate) struct TemplateLookup;
impl Operation for TemplateLookup {
const NAME: &'static str = "TemplateLookup";
const INSTRUCTION: &'static str = "INST - TemplateLookup";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let jump = context.vm.read::<u32>();
let site = context.vm.read::<u64>();
if let Some(template) = context.realm().lookup_template(site) {
context.vm.push(template);
context.vm.frame_mut().pc = jump;
}
Ok(CompletionType::Normal)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct TemplateCreate;
impl Operation for TemplateCreate {
const NAME: &'static str = "TemplateCreate";
const INSTRUCTION: &'static str = "INST - TemplateCreate";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let count = context.vm.read::<u32>();
let site = context.vm.read::<u64>();
let template =
Array::array_create(count.into(), None, context).expect("cannot fail per spec");
let raw_obj =
Array::array_create(count.into(), None, context).expect("cannot fail per spec");
for index in (0..count).rev() {
let raw_value = context.vm.pop();
let cooked_value = context.vm.pop();
template
.define_property_or_throw(
index,
PropertyDescriptor::builder()
.value(cooked_value)
.writable(false)
.enumerable(true)
.configurable(false),
context,
)
.expect("should not fail on new array");
raw_obj
.define_property_or_throw(
index,
PropertyDescriptor::builder()
.value(raw_value)
.writable(false)
.enumerable(true)
.configurable(false),
context,
)
.expect("should not fail on new array");
}
raw_obj
.set_integrity_level(IntegrityLevel::Frozen, context)
.expect("should never fail per spec");
template
.define_property_or_throw(
utf16!("raw"),
PropertyDescriptor::builder()
.value(raw_obj)
.writable(false)
.enumerable(false)
.configurable(false),
context,
)
.expect("should never fail per spec");
template
.set_integrity_level(IntegrityLevel::Frozen, context)
.expect("should never fail per spec");
context.realm().push_template(site, template.clone());
context.vm.push(template);
Ok(CompletionType::Normal)
}
}