mirror of https://github.com/boa-dev/boa.git
Browse Source
* Fix tagged template creation * Fix template identifier hash * Apply suggestion * Apply suggestionpull/2939/head
raskad
2 years ago
committed by
GitHub
13 changed files with 241 additions and 33 deletions
@ -0,0 +1,104 @@
|
||||
use crate::{ |
||||
builtins::array::Array, |
||||
object::IntegrityLevel, |
||||
property::PropertyDescriptor, |
||||
vm::{opcode::Operation, CompletionType}, |
||||
Context, JsResult, |
||||
}; |
||||
use boa_macros::utf16; |
||||
|
||||
/// `TemplateLookup` implements the Opcode Operation for `Opcode::TemplateLookup`
|
||||
///
|
||||
/// Operation:
|
||||
/// - Lookup if a tagged template object is cached and skip the creation if it is.
|
||||
#[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 as usize; |
||||
} |
||||
|
||||
Ok(CompletionType::Normal) |
||||
} |
||||
} |
||||
|
||||
/// `TemplateCreate` implements the Opcode Operation for `Opcode::TemplateCreate`
|
||||
///
|
||||
/// Operation:
|
||||
/// - Create a new tagged template object and cache it.
|
||||
#[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) |
||||
} |
||||
} |
Loading…
Reference in new issue