quickjs_oxide/engine/code/
module.rs1use crate::engine::code::function::UnlinkedFunction;
11use crate::engine::value::JsString;
12
13pub const MODULE_DEFAULT_BINDING_NAME: &str = "<module-default>";
16
17pub const MODULE_IMPORT_META_BINDING_NAME: &str = "<import.meta>";
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
22pub struct ModuleRequestIndex(pub u32);
23
24#[derive(Clone, Debug, PartialEq, Eq)]
31pub struct ModuleImportAttribute {
32 pub key: JsString,
34 pub value: JsString,
36}
37
38#[derive(Clone, Debug, PartialEq, Eq)]
46pub enum ModuleImportAttributes {
47 Absent,
49 Present(Box<[ModuleImportAttribute]>),
51}
52
53impl ModuleImportAttributes {
54 #[must_use]
56 pub fn effective(&self) -> Option<&[ModuleImportAttribute]> {
57 match self {
58 Self::Present(attributes) if !attributes.is_empty() => Some(attributes),
59 Self::Absent | Self::Present(_) => None,
60 }
61 }
62
63 #[must_use]
65 pub fn syntactic(&self) -> Option<&[ModuleImportAttribute]> {
66 match self {
67 Self::Absent => None,
68 Self::Present(attributes) => Some(attributes),
69 }
70 }
71}
72
73#[derive(Clone, Debug, PartialEq, Eq)]
75pub struct ModuleRequest {
76 pub specifier: JsString,
77 pub attributes: ModuleImportAttributes,
78}
79
80#[derive(Clone, Debug, PartialEq, Eq)]
82pub struct ModuleImport {
83 pub request: ModuleRequestIndex,
84 pub import_name: ModuleImportName,
85 pub closure_index: u16,
86}
87
88#[derive(Clone, Debug, PartialEq, Eq)]
94pub enum ModuleImportName {
95 Name(JsString),
96 Namespace,
97}
98
99#[derive(Clone, Copy, Debug, PartialEq, Eq)]
102pub enum ModuleLinkInitializerValue {
103 Undefined,
104 Function {
105 constant: u32,
106 inferred_name: Option<u32>,
110 },
111}
112
113#[derive(Clone, Copy, Debug, PartialEq, Eq)]
115pub struct ModuleLinkInitializer {
116 pub closure_index: u16,
117 pub value: ModuleLinkInitializerValue,
118}
119
120#[derive(Clone, Copy, Debug, PartialEq, Eq)]
126pub struct ModuleImportCollision {
127 pub closure_index: u16,
128 pub declaration: ModuleImportCollisionDeclaration,
129}
130
131#[derive(Clone, Copy, Debug, PartialEq, Eq)]
133pub enum ModuleImportCollisionDeclaration {
134 Var,
135 Lexical,
136 Function,
137}
138
139#[derive(Clone, Debug, PartialEq, Eq)]
141pub enum ModuleExportTarget {
142 Local { closure_index: u16 },
144 Indirect {
146 request: ModuleRequestIndex,
147 import_name: ModuleImportName,
148 },
149}
150
151#[derive(Clone, Debug, PartialEq, Eq)]
154pub struct ModuleExport {
155 pub export_name: JsString,
156 pub target: ModuleExportTarget,
157}
158
159#[derive(Clone, Copy, Debug, PartialEq, Eq)]
161pub struct ModuleStarExport {
162 pub request: ModuleRequestIndex,
163}
164
165#[derive(Debug)]
167pub struct UnlinkedModule {
168 function: UnlinkedFunction,
169 has_top_level_await: bool,
170 declaration_order: Box<[u16]>,
171 link_initializers: Box<[ModuleLinkInitializer]>,
172 import_collisions: Box<[ModuleImportCollision]>,
173 requested_modules: Box<[ModuleRequest]>,
174 imports: Box<[ModuleImport]>,
175 exports: Box<[ModuleExport]>,
176 star_exports: Box<[ModuleStarExport]>,
177}
178
179pub struct UnlinkedModuleTables {
181 pub declaration_order: Vec<u16>,
182 pub link_initializers: Vec<ModuleLinkInitializer>,
183 pub import_collisions: Vec<ModuleImportCollision>,
184 pub requested_modules: Vec<ModuleRequest>,
185 pub imports: Vec<ModuleImport>,
186 pub exports: Vec<ModuleExport>,
187 pub star_exports: Vec<ModuleStarExport>,
188}
189
190impl UnlinkedModule {
191 #[must_use]
192 pub fn new(
193 function: UnlinkedFunction,
194 has_top_level_await: bool,
195 tables: UnlinkedModuleTables,
196 ) -> Self {
197 let UnlinkedModuleTables {
198 declaration_order,
199 link_initializers,
200 import_collisions,
201 requested_modules,
202 imports,
203 exports,
204 star_exports,
205 } = tables;
206 Self {
207 function,
208 has_top_level_await,
209 declaration_order: declaration_order.into_boxed_slice(),
210 link_initializers: link_initializers.into_boxed_slice(),
211 import_collisions: import_collisions.into_boxed_slice(),
212 requested_modules: requested_modules.into_boxed_slice(),
213 imports: imports.into_boxed_slice(),
214 exports: exports.into_boxed_slice(),
215 star_exports: star_exports.into_boxed_slice(),
216 }
217 }
218
219 #[must_use]
220 #[cfg_attr(not(test), allow(dead_code))]
221 pub const fn function(&self) -> &UnlinkedFunction {
222 &self.function
223 }
224
225 #[must_use]
226 #[cfg_attr(not(test), allow(dead_code))]
227 pub const fn has_top_level_await(&self) -> bool {
228 self.has_top_level_await
229 }
230
231 #[must_use]
232 #[cfg_attr(not(test), allow(dead_code))]
233 pub const fn declaration_order(&self) -> &[u16] {
234 &self.declaration_order
235 }
236
237 #[must_use]
238 #[cfg_attr(not(test), allow(dead_code))]
239 pub const fn link_initializers(&self) -> &[ModuleLinkInitializer] {
240 &self.link_initializers
241 }
242
243 #[must_use]
244 #[cfg_attr(not(test), allow(dead_code))]
245 pub const fn import_collisions(&self) -> &[ModuleImportCollision] {
246 &self.import_collisions
247 }
248
249 #[must_use]
250 #[cfg_attr(not(test), allow(dead_code))]
251 pub const fn requested_modules(&self) -> &[ModuleRequest] {
252 &self.requested_modules
253 }
254
255 #[must_use]
256 #[cfg_attr(not(test), allow(dead_code))]
257 pub const fn imports(&self) -> &[ModuleImport] {
258 &self.imports
259 }
260
261 #[must_use]
262 #[cfg_attr(not(test), allow(dead_code))]
263 pub const fn exports(&self) -> &[ModuleExport] {
264 &self.exports
265 }
266
267 #[must_use]
268 #[cfg_attr(not(test), allow(dead_code))]
269 pub const fn star_exports(&self) -> &[ModuleStarExport] {
270 &self.star_exports
271 }
272}