1use std::hash::Hash;
2use std::hash::Hasher;
3use std::mem::MaybeUninit;
4use std::ptr::null;
5
6use crate::support::int;
7use crate::support::MapFnFrom;
8use crate::support::MapFnTo;
9use crate::support::MaybeBool;
10use crate::support::ToCFn;
11use crate::support::UnitType;
12use crate::Context;
13use crate::FixedArray;
14use crate::HandleScope;
15use crate::Isolate;
16use crate::Local;
17use crate::Module;
18use crate::ModuleRequest;
19use crate::String;
20use crate::UnboundModuleScript;
21use crate::Value;
22
23#[cfg(not(target_os = "windows"))]
44pub type ResolveModuleCallback<'a> = extern "C" fn(
45 Local<'a, Context>,
46 Local<'a, String>,
47 Local<'a, FixedArray>,
48 Local<'a, Module>,
49) -> *const Module;
50
51#[cfg(target_os = "windows")]
53pub type ResolveModuleCallback<'a> = extern "C" fn(
54 *mut *const Module,
55 Local<'a, Context>,
56 Local<'a, String>,
57 Local<'a, FixedArray>,
58 Local<'a, Module>,
59) -> *mut *const Module;
60
61impl<'a, F> MapFnFrom<F> for ResolveModuleCallback<'a>
62where
63 F: UnitType
64 + Fn(
65 Local<'a, Context>,
66 Local<'a, String>,
67 Local<'a, FixedArray>,
68 Local<'a, Module>,
69 ) -> Option<Local<'a, Module>>,
70{
71 #[cfg(not(target_os = "windows"))]
72 fn mapping() -> Self {
73 let f = |context, specifier, import_assertions, referrer| {
74 (F::get())(context, specifier, import_assertions, referrer)
75 .map(|r| -> *const Module { &*r })
76 .unwrap_or(null())
77 };
78 f.to_c_fn()
79 }
80
81 #[cfg(target_os = "windows")]
82 fn mapping() -> Self {
83 let f = |ret_ptr, context, specifier, import_assertions, referrer| {
84 let r = (F::get())(context, specifier, import_assertions, referrer)
85 .map(|r| -> *const Module { &*r })
86 .unwrap_or(null());
87 unsafe { std::ptr::write(ret_ptr, r) }; ret_ptr };
90 f.to_c_fn()
91 }
92}
93
94#[cfg(not(target_os = "windows"))]
96pub type SyntheticModuleEvaluationSteps<'a> =
97 extern "C" fn(Local<'a, Context>, Local<'a, Module>) -> *const Value;
98
99#[cfg(target_os = "windows")]
101pub type SyntheticModuleEvaluationSteps<'a> =
102 extern "C" fn(
103 *mut *const Value,
104 Local<'a, Context>,
105 Local<'a, Module>,
106 ) -> *mut *const Value;
107
108impl<'a, F> MapFnFrom<F> for SyntheticModuleEvaluationSteps<'a>
109where
110 F: UnitType
111 + Fn(Local<'a, Context>, Local<'a, Module>) -> Option<Local<'a, Value>>,
112{
113 #[cfg(not(target_os = "windows"))]
114 fn mapping() -> Self {
115 let f = |context, module| {
116 (F::get())(context, module)
117 .map(|r| -> *const Value { &*r })
118 .unwrap_or(null())
119 };
120 f.to_c_fn()
121 }
122
123 #[cfg(target_os = "windows")]
124 fn mapping() -> Self {
125 let f = |ret_ptr, context, module| {
126 let r = (F::get())(context, module)
127 .map(|r| -> *const Value { &*r })
128 .unwrap_or(null());
129 unsafe { std::ptr::write(ret_ptr, r) }; ret_ptr };
132 f.to_c_fn()
133 }
134}
135
136extern "C" {
137 fn v8__Module__GetStatus(this: *const Module) -> ModuleStatus;
138 fn v8__Module__GetException(this: *const Module) -> *const Value;
139 fn v8__Module__GetModuleRequests(this: *const Module) -> *const FixedArray;
140 fn v8__Module__SourceOffsetToLocation(
141 this: *const Module,
142 offset: int,
143 out: *mut MaybeUninit<Location>,
144 ) -> Location;
145 fn v8__Module__GetModuleNamespace(this: *const Module) -> *const Value;
146 fn v8__Module__GetIdentityHash(this: *const Module) -> int;
147 fn v8__Module__ScriptId(this: *const Module) -> int;
148 fn v8__Module__InstantiateModule(
149 this: *const Module,
150 context: *const Context,
151 cb: ResolveModuleCallback,
152 ) -> MaybeBool;
153 fn v8__Module__Evaluate(
154 this: *const Module,
155 context: *const Context,
156 ) -> *const Value;
157 fn v8__Module__IsSourceTextModule(this: *const Module) -> bool;
158 fn v8__Module__IsSyntheticModule(this: *const Module) -> bool;
159 fn v8__Module__CreateSyntheticModule(
160 isolate: *const Isolate,
161 module_name: *const String,
162 export_names_len: usize,
163 export_names_raw: *const *const String,
164 evaluation_steps: SyntheticModuleEvaluationSteps,
165 ) -> *const Module;
166 fn v8__Module__SetSyntheticModuleExport(
167 this: *const Module,
168 isolate: *const Isolate,
169 export_name: *const String,
170 export_value: *const Value,
171 ) -> MaybeBool;
172 fn v8__Module__GetUnboundModuleScript(
173 this: *const Module,
174 ) -> *const UnboundModuleScript;
175 fn v8__Location__GetLineNumber(this: *const Location) -> int;
176 fn v8__Location__GetColumnNumber(this: *const Location) -> int;
177 fn v8__ModuleRequest__GetSpecifier(
178 this: *const ModuleRequest,
179 ) -> *const String;
180 fn v8__ModuleRequest__GetSourceOffset(this: *const ModuleRequest) -> int;
181 fn v8__ModuleRequest__GetImportAssertions(
182 this: *const ModuleRequest,
183 ) -> *const FixedArray;
184}
185
186#[repr(C)]
188#[derive(Debug)]
189pub struct Location([i32; 2]);
190
191impl Location {
192 pub fn get_line_number(&self) -> int {
193 unsafe { v8__Location__GetLineNumber(self) }
194 }
195
196 pub fn get_column_number(&self) -> int {
197 unsafe { v8__Location__GetColumnNumber(self) }
198 }
199}
200
201#[derive(Debug, PartialEq)]
207#[repr(C)]
208pub enum ModuleStatus {
209 Uninstantiated,
210 Instantiating,
211 Instantiated,
212 Evaluating,
213 Evaluated,
214 Errored,
215}
216
217impl Module {
218 pub fn get_status(&self) -> ModuleStatus {
220 unsafe { v8__Module__GetStatus(self) }
221 }
222
223 pub fn get_exception(&self) -> Local<Value> {
225 unsafe { Local::from_raw(v8__Module__GetException(self)) }.unwrap()
228 }
229
230 pub fn get_module_requests(&self) -> Local<FixedArray> {
232 unsafe { Local::from_raw(v8__Module__GetModuleRequests(self)) }.unwrap()
233 }
234
235 pub fn source_offset_to_location(&self, offset: int) -> Location {
238 let mut out = MaybeUninit::<Location>::uninit();
239 unsafe {
240 v8__Module__SourceOffsetToLocation(self, offset, &mut out);
241 out.assume_init()
242 }
243 }
244
245 #[doc(hidden)]
248 pub fn get_identity_hash(&self) -> int {
249 unsafe { v8__Module__GetIdentityHash(self) }
250 }
251
252 pub fn script_id(&self) -> Option<int> {
256 if !self.is_source_text_module() {
257 return None;
258 }
259 if self.get_status() == ModuleStatus::Errored {
260 return None;
261 }
262 Some(unsafe { v8__Module__ScriptId(self) })
263 }
264
265 pub fn get_module_namespace(&self) -> Local<Value> {
269 unsafe { Local::from_raw(v8__Module__GetModuleNamespace(self)).unwrap() }
272 }
273
274 #[must_use]
282 pub fn instantiate_module<'a>(
283 &self,
284 scope: &mut HandleScope,
285 callback: impl MapFnTo<ResolveModuleCallback<'a>>,
286 ) -> Option<bool> {
287 unsafe {
288 v8__Module__InstantiateModule(
289 self,
290 &*scope.get_current_context(),
291 callback.map_fn_to(),
292 )
293 }
294 .into()
295 }
296
297 #[must_use]
304 pub fn evaluate<'s>(
305 &self,
306 scope: &mut HandleScope<'s>,
307 ) -> Option<Local<'s, Value>> {
308 unsafe {
309 scope
310 .cast_local(|sd| v8__Module__Evaluate(&*self, sd.get_current_context()))
311 }
312 }
313
314 pub fn is_source_text_module(&self) -> bool {
316 unsafe { v8__Module__IsSourceTextModule(&*self) }
317 }
318
319 pub fn is_synthetic_module(&self) -> bool {
321 unsafe { v8__Module__IsSyntheticModule(&*self) }
322 }
323
324 pub fn create_synthetic_module<'s, 'a>(
330 scope: &mut HandleScope<'s>,
331 module_name: Local<String>,
332 export_names: &[Local<String>],
333 evaluation_steps: impl MapFnTo<SyntheticModuleEvaluationSteps<'a>>,
334 ) -> Local<'s, Module> {
335 let export_names = Local::slice_into_raw(export_names);
336 let export_names_len = export_names.len();
337 let export_names = export_names.as_ptr();
338 unsafe {
339 scope
340 .cast_local(|sd| {
341 v8__Module__CreateSyntheticModule(
342 sd.get_isolate_ptr(),
343 &*module_name,
344 export_names_len,
345 export_names,
346 evaluation_steps.map_fn_to(),
347 )
348 })
349 .unwrap()
350 }
351 }
352
353 #[must_use]
359 pub fn set_synthetic_module_export(
360 &self,
361 scope: &mut HandleScope,
362 export_name: Local<String>,
363 export_value: Local<Value>,
364 ) -> Option<bool> {
365 unsafe {
366 v8__Module__SetSyntheticModuleExport(
367 &*self,
368 scope.get_isolate_ptr(),
369 &*export_name,
370 &*export_value,
371 )
372 }
373 .into()
374 }
375
376 pub fn get_unbound_module_script<'s>(
377 &self,
378 scope: &mut HandleScope<'s>,
379 ) -> Local<'s, UnboundModuleScript> {
380 unsafe {
381 scope
382 .cast_local(|_| v8__Module__GetUnboundModuleScript(self))
383 .unwrap()
384 }
385 }
386}
387
388impl Hash for Module {
389 fn hash<H: Hasher>(&self, state: &mut H) {
390 state.write_i32(self.get_identity_hash());
391 }
392}
393
394impl ModuleRequest {
395 pub fn get_specifier(&self) -> Local<String> {
397 unsafe { Local::from_raw(v8__ModuleRequest__GetSpecifier(self)) }.unwrap()
398 }
399
400 pub fn get_source_offset(&self) -> int {
403 unsafe { v8__ModuleRequest__GetSourceOffset(self) }
404 }
405
406 pub fn get_import_assertions(&self) -> Local<FixedArray> {
419 unsafe { Local::from_raw(v8__ModuleRequest__GetImportAssertions(self)) }
420 .unwrap()
421 }
422}