boa_engine/vm/opcode/meta/
mod.rs

1use super::VaryingOperand;
2use crate::{
3    Context, JsObject, JsValue,
4    module::ModuleKind,
5    vm::{ActiveRunnable, opcode::Operation},
6};
7use std::unreachable;
8
9/// `NewTarget` implements the Opcode Operation for `Opcode::NewTarget`
10///
11/// Operation:
12///  - Push the current new target to the stack.
13#[derive(Debug, Clone, Copy)]
14pub(crate) struct NewTarget;
15
16impl NewTarget {
17    #[inline(always)]
18    pub(super) fn operation(dst: VaryingOperand, context: &mut Context) {
19        let new_target = if let Some(new_target) = context
20            .vm
21            .environments
22            .get_this_environment()
23            .as_function()
24            .and_then(|env| env.slots().new_target().cloned())
25        {
26            new_target.into()
27        } else {
28            JsValue::undefined()
29        };
30        context.vm.set_register(dst.into(), new_target);
31    }
32}
33
34impl Operation for NewTarget {
35    const NAME: &'static str = "NewTarget";
36    const INSTRUCTION: &'static str = "INST - NewTarget";
37    const COST: u8 = 2;
38}
39
40/// `ImportMeta` implements the Opcode Operation for `Opcode::ImportMeta`
41///
42/// Operation:
43///  - Push the current `import.meta` to the stack
44#[derive(Debug, Clone, Copy)]
45pub(crate) struct ImportMeta;
46
47impl ImportMeta {
48    #[inline(always)]
49    pub(super) fn operation(dst: VaryingOperand, context: &mut Context) {
50        // Meta Properties
51        //
52        // ImportMeta : import . meta
53        //
54        // https://tc39.es/ecma262/#sec-meta-properties
55
56        // 1. Let module be GetActiveScriptOrModule().
57
58        let Some(ActiveRunnable::Module(module)) = context.get_active_script_or_module() else {
59            unreachable!("2. Assert: module is a Source Text Module Record.");
60        };
61
62        let ModuleKind::SourceText(src) = module.kind() else {
63            unreachable!("2. Assert: module is a Source Text Module Record.");
64        };
65
66        // 3. Let importMeta be module.[[ImportMeta]].
67        // 4. If importMeta is empty, then
68        // 5. Else,
69        //     a. Assert: importMeta is an Object.
70        let import_meta = src
71            .import_meta()
72            .borrow_mut()
73            .get_or_insert_with(|| {
74                // a. Set importMeta to OrdinaryObjectCreate(null).
75                let import_meta = JsObject::with_null_proto();
76
77                // b. Let importMetaValues be HostGetImportMetaProperties(module).
78                // c. For each Record { [[Key]], [[Value]] } p of importMetaValues, do
79                //     i. Perform ! CreateDataPropertyOrThrow(importMeta, p.[[Key]], p.[[Value]]).
80                // d. Perform HostFinalizeImportMeta(importMeta, module).
81                context
82                    .module_loader()
83                    .init_import_meta(&import_meta, &module, context);
84
85                // e. Set module.[[ImportMeta]] to importMeta.
86                import_meta
87            })
88            .clone();
89
90        //     b. Return importMeta.
91        //     f. Return importMeta.
92        context.vm.set_register(dst.into(), import_meta.into());
93    }
94}
95
96impl Operation for ImportMeta {
97    const NAME: &'static str = "ImportMeta";
98    const INSTRUCTION: &'static str = "INST - ImportMeta";
99    const COST: u8 = 6;
100}