1use std::mem::MaybeUninit;
2use std::num::NonZeroI32;
3use std::ptr::null;
4
5use crate::Context;
6use crate::FixedArray;
7use crate::Local;
8use crate::Message;
9use crate::Module;
10use crate::ModuleRequest;
11use crate::Object;
12use crate::String;
13use crate::UnboundModuleScript;
14use crate::Value;
15use crate::isolate::ModuleImportPhase;
16use crate::isolate::RealIsolate;
17use crate::scope::GetIsolate;
18use crate::scope::PinScope;
19use crate::support::MapFnFrom;
20use crate::support::MapFnTo;
21use crate::support::MaybeBool;
22use crate::support::ToCFn;
23use crate::support::UnitType;
24use crate::support::int;
25
26#[cfg(not(target_os = "windows"))]
45#[repr(C)]
46pub struct ResolveModuleCallbackRet(*const Module);
48
49#[cfg(not(target_os = "windows"))]
50pub type ResolveModuleCallback<'s> =
51 unsafe extern "C" fn(
52 Local<'s, Context>,
53 Local<'s, String>,
54 Local<'s, FixedArray>,
55 Local<'s, Module>,
56 ) -> ResolveModuleCallbackRet;
57
58#[cfg(target_os = "windows")]
60pub type ResolveModuleCallback<'s> = unsafe extern "C" fn(
61 *mut *const Module,
62 Local<'s, Context>,
63 Local<'s, String>,
64 Local<'s, FixedArray>,
65 Local<'s, Module>,
66)
67 -> *mut *const Module;
68
69impl<'s, F> MapFnFrom<F> for ResolveModuleCallback<'s>
70where
71 F: UnitType
72 + Fn(
73 Local<'s, Context>,
74 Local<'s, String>,
75 Local<'s, FixedArray>,
76 Local<'s, Module>,
77 ) -> Option<Local<'s, Module>>,
78{
79 #[cfg(not(target_os = "windows"))]
80 fn mapping() -> Self {
81 let f = |context, specifier, import_attributes, referrer| {
82 ResolveModuleCallbackRet(
83 (F::get())(context, specifier, import_attributes, referrer)
84 .map(|r| -> *const Module { &*r })
85 .unwrap_or(null()),
86 )
87 };
88 f.to_c_fn()
89 }
90
91 #[cfg(target_os = "windows")]
92 fn mapping() -> Self {
93 let f = |ret_ptr, context, specifier, import_attributes, referrer| {
94 let r = (F::get())(context, specifier, import_attributes, referrer)
95 .map(|r| -> *const Module { &*r })
96 .unwrap_or(null());
97 unsafe { std::ptr::write(ret_ptr, r) }; ret_ptr };
100 f.to_c_fn()
101 }
102}
103
104#[cfg(not(target_os = "windows"))]
106#[repr(C)]
107pub struct SyntheticModuleEvaluationStepsRet(*const Value);
108
109#[cfg(not(target_os = "windows"))]
110pub type SyntheticModuleEvaluationSteps<'s> =
111 unsafe extern "C" fn(
112 Local<'s, Context>,
113 Local<'s, Module>,
114 ) -> SyntheticModuleEvaluationStepsRet;
115
116#[cfg(target_os = "windows")]
118pub type SyntheticModuleEvaluationSteps<'s> =
119 unsafe extern "C" fn(
120 *mut *const Value,
121 Local<'s, Context>,
122 Local<'s, Module>,
123 ) -> *mut *const Value;
124
125impl<'s, F> MapFnFrom<F> for SyntheticModuleEvaluationSteps<'s>
126where
127 F: UnitType
128 + Fn(Local<'s, Context>, Local<'s, Module>) -> Option<Local<'s, Value>>,
129{
130 #[cfg(not(target_os = "windows"))]
131 fn mapping() -> Self {
132 let f = |context, module| {
133 SyntheticModuleEvaluationStepsRet(
134 (F::get())(context, module).map_or(null(), |r| -> *const Value { &*r }),
135 )
136 };
137 f.to_c_fn()
138 }
139
140 #[cfg(target_os = "windows")]
141 fn mapping() -> Self {
142 let f = |ret_ptr, context, module| {
143 let r = (F::get())(context, module)
144 .map(|r| -> *const Value { &*r })
145 .unwrap_or(null());
146 unsafe { std::ptr::write(ret_ptr, r) }; ret_ptr };
149 f.to_c_fn()
150 }
151}
152
153#[cfg(not(target_os = "windows"))]
155#[repr(C)]
156pub struct ResolveSourceCallbackRet(*const Object);
157
158#[cfg(not(target_os = "windows"))]
159pub type ResolveSourceCallback<'s> =
160 unsafe extern "C" fn(
161 Local<'s, Context>,
162 Local<'s, String>,
163 Local<'s, FixedArray>,
164 Local<'s, Module>,
165 ) -> ResolveSourceCallbackRet;
166
167#[cfg(target_os = "windows")]
169pub type ResolveSourceCallback<'s> = unsafe extern "C" fn(
170 *mut *const Object,
171 Local<'s, Context>,
172 Local<'s, String>,
173 Local<'s, FixedArray>,
174 Local<'s, Module>,
175)
176 -> *mut *const Object;
177
178impl<'s, F> MapFnFrom<F> for ResolveSourceCallback<'s>
179where
180 F: UnitType
181 + Fn(
182 Local<'s, Context>,
183 Local<'s, String>,
184 Local<'s, FixedArray>,
185 Local<'s, Module>,
186 ) -> Option<Local<'s, Object>>,
187{
188 #[cfg(not(target_os = "windows"))]
189 fn mapping() -> Self {
190 let f = |context, specifier, import_attributes, referrer| {
191 ResolveSourceCallbackRet(
192 (F::get())(context, specifier, import_attributes, referrer)
193 .map(|r| -> *const Object { &*r })
194 .unwrap_or(null()),
195 )
196 };
197 f.to_c_fn()
198 }
199
200 #[cfg(target_os = "windows")]
201 fn mapping() -> Self {
202 let f = |ret_ptr, context, specifier, import_attributes, referrer| {
203 let r = (F::get())(context, specifier, import_attributes, referrer)
204 .map(|r| -> *const Object { &*r })
205 .unwrap_or(null());
206 unsafe { std::ptr::write(ret_ptr, r) }; ret_ptr };
209 f.to_c_fn()
210 }
211}
212
213unsafe extern "C" {
214 fn v8__Module__GetStatus(this: *const Module) -> ModuleStatus;
215 fn v8__Module__GetException(this: *const Module) -> *const Value;
216 fn v8__Module__GetModuleRequests(this: *const Module) -> *const FixedArray;
217 fn v8__Module__SourceOffsetToLocation(
218 this: *const Module,
219 offset: int,
220 out: *mut Location,
221 );
222 fn v8__Module__GetModuleNamespace(this: *const Module) -> *const Value;
223 fn v8__Module__GetModuleNamespace2(
224 this: *const Module,
225 phase: ModuleImportPhase,
226 ) -> *const Value;
227 fn v8__Module__EvaluateForImportDefer(
228 this: *const Module,
229 context: *const Context,
230 ) -> *const Value;
231 fn v8__Module__GetIdentityHash(this: *const Module) -> int;
232 fn v8__Module__ScriptId(this: *const Module) -> int;
233 fn v8__Module__InstantiateModule(
234 this: *const Module,
235 context: *const Context,
236 cb: ResolveModuleCallback,
237 source_callback: Option<ResolveSourceCallback>,
238 ) -> MaybeBool;
239 fn v8__Module__Evaluate(
240 this: *const Module,
241 context: *const Context,
242 ) -> *const Value;
243 fn v8__Module__IsGraphAsync(this: *const Module) -> bool;
244 fn v8__Module__IsSourceTextModule(this: *const Module) -> bool;
245 fn v8__Module__IsSyntheticModule(this: *const Module) -> bool;
246 fn v8__Module__CreateSyntheticModule(
247 isolate: *const RealIsolate,
248 module_name: *const String,
249 export_names_len: usize,
250 export_names_raw: *const *const String,
251 evaluation_steps: SyntheticModuleEvaluationSteps,
252 ) -> *const Module;
253 fn v8__Module__SetSyntheticModuleExport(
254 this: *const Module,
255 isolate: *const RealIsolate,
256 export_name: *const String,
257 export_value: *const Value,
258 ) -> MaybeBool;
259 fn v8__Module__GetUnboundModuleScript(
260 this: *const Module,
261 ) -> *const UnboundModuleScript;
262 fn v8__Location__GetLineNumber(this: *const Location) -> int;
263 fn v8__Location__GetColumnNumber(this: *const Location) -> int;
264 fn v8__ModuleRequest__GetSpecifier(
265 this: *const ModuleRequest,
266 ) -> *const String;
267 fn v8__ModuleRequest__GetPhase(
268 this: *const ModuleRequest,
269 ) -> ModuleImportPhase;
270 fn v8__ModuleRequest__GetSourceOffset(this: *const ModuleRequest) -> int;
271 fn v8__ModuleRequest__GetImportAttributes(
272 this: *const ModuleRequest,
273 ) -> *const FixedArray;
274 fn v8__Module__GetStalledTopLevelAwaitMessage(
275 this: *const Module,
276 isolate: *const RealIsolate,
277 out_vec: *mut StalledTopLevelAwaitMessage,
278 vec_len: usize,
279 ) -> usize;
280}
281
282#[repr(C)]
283pub struct StalledTopLevelAwaitMessage {
284 pub module: *const Module,
285 pub message: *const Message,
286}
287
288#[repr(C)]
290#[derive(Debug)]
291pub struct Location([i32; 2]);
292
293impl Location {
294 pub fn get_line_number(&self) -> int {
295 unsafe { v8__Location__GetLineNumber(self) }
296 }
297
298 pub fn get_column_number(&self) -> int {
299 unsafe { v8__Location__GetColumnNumber(self) }
300 }
301}
302
303#[derive(Debug, PartialEq, Eq)]
309#[repr(C)]
310pub enum ModuleStatus {
311 Uninstantiated,
312 Instantiating,
313 Instantiated,
314 Evaluating,
315 Evaluated,
316 Errored,
317}
318
319impl Module {
320 #[inline(always)]
322 pub fn get_status(&self) -> ModuleStatus {
323 unsafe { v8__Module__GetStatus(self) }
324 }
325
326 #[inline(always)]
328 pub fn get_exception<'o>(&self) -> Local<'o, Value> {
329 unsafe { Local::from_raw(v8__Module__GetException(self)) }.unwrap()
332 }
333
334 #[inline(always)]
336 pub fn get_module_requests<'o>(&self) -> Local<'o, FixedArray> {
337 unsafe { Local::from_raw(v8__Module__GetModuleRequests(self)) }.unwrap()
338 }
339
340 #[inline(always)]
343 pub fn source_offset_to_location(&self, offset: int) -> Location {
344 let mut out = MaybeUninit::<Location>::uninit();
345 unsafe {
346 v8__Module__SourceOffsetToLocation(self, offset, out.as_mut_ptr());
347 out.assume_init()
348 }
349 }
350
351 #[inline(always)]
357 pub fn get_identity_hash(&self) -> NonZeroI32 {
358 unsafe { NonZeroI32::new_unchecked(v8__Module__GetIdentityHash(self)) }
359 }
360
361 #[inline(always)]
365 pub fn script_id(&self) -> Option<int> {
366 if !self.is_source_text_module() {
367 return None;
368 }
369 if self.get_status() == ModuleStatus::Errored {
370 return None;
371 }
372 Some(unsafe { v8__Module__ScriptId(self) })
373 }
374
375 #[inline(always)]
379 pub fn get_module_namespace<'o>(&self) -> Local<'o, Value> {
380 unsafe { Local::from_raw(v8__Module__GetModuleNamespace(self)).unwrap() }
383 }
384
385 #[inline(always)]
392 pub fn get_module_namespace_with_phase<'o>(
393 &self,
394 phase: ModuleImportPhase,
395 ) -> Local<'o, Value> {
396 unsafe {
397 Local::from_raw(v8__Module__GetModuleNamespace2(self, phase)).unwrap()
398 }
399 }
400
401 #[must_use]
410 #[inline(always)]
411 pub fn evaluate_for_import_defer<'s>(
412 &self,
413 scope: &PinScope<'s, '_>,
414 ) -> Option<Local<'s, Value>> {
415 unsafe {
416 Local::from_raw(v8__Module__EvaluateForImportDefer(
417 self,
418 &*scope.get_current_context(),
419 ))
420 }
421 }
422
423 #[must_use]
429 #[inline(always)]
430 pub fn instantiate_module<'s, 'i>(
431 &self,
432 scope: &PinScope<'s, 'i>,
433 callback: impl MapFnTo<ResolveModuleCallback<'s>>,
434 ) -> Option<bool> {
435 unsafe {
436 v8__Module__InstantiateModule(
437 self,
438 &*scope.get_current_context(),
439 callback.map_fn_to(),
440 None,
441 )
442 }
443 .into()
444 }
445
446 #[must_use]
452 #[inline(always)]
453 pub fn instantiate_module2<'s, 'i>(
454 &self,
455 scope: &PinScope<'s, 'i>,
456 callback: impl MapFnTo<ResolveModuleCallback<'s>>,
457 source_callback: impl MapFnTo<ResolveSourceCallback<'s>>,
458 ) -> Option<bool> {
459 unsafe {
460 v8__Module__InstantiateModule(
461 self,
462 &*scope.get_current_context(),
463 callback.map_fn_to(),
464 Some(source_callback.map_fn_to()),
465 )
466 }
467 .into()
468 }
469
470 #[must_use]
477 #[inline(always)]
478 pub fn evaluate<'s>(
479 &self,
480 scope: &PinScope<'s, '_>,
481 ) -> Option<Local<'s, Value>> {
482 unsafe {
483 scope
484 .cast_local(|sd| v8__Module__Evaluate(self, sd.get_current_context()))
485 }
486 }
487
488 #[inline(always)]
493 pub fn is_graph_async(&self) -> bool {
494 unsafe { v8__Module__IsGraphAsync(self) }
495 }
496
497 #[inline(always)]
499 pub fn is_source_text_module(&self) -> bool {
500 unsafe { v8__Module__IsSourceTextModule(self) }
501 }
502
503 #[inline(always)]
505 pub fn is_synthetic_module(&self) -> bool {
506 unsafe { v8__Module__IsSyntheticModule(self) }
507 }
508
509 #[inline(always)]
515 pub fn create_synthetic_module<'s, 'i>(
516 scope: &PinScope<'s, 'i>,
517 module_name: Local<String>,
518 export_names: &[Local<String>],
519 evaluation_steps: impl MapFnTo<SyntheticModuleEvaluationSteps<'s>>,
520 ) -> Local<'s, Module> {
521 let export_names = Local::slice_into_raw(export_names);
522 let export_names_len = export_names.len();
523 let export_names = export_names.as_ptr();
524 unsafe {
525 scope
526 .cast_local(|sd| {
527 v8__Module__CreateSyntheticModule(
528 sd.get_isolate_ptr(),
529 &*module_name,
530 export_names_len,
531 export_names,
532 evaluation_steps.map_fn_to(),
533 )
534 })
535 .unwrap()
536 }
537 }
538
539 #[must_use]
545 #[inline(always)]
546 pub fn set_synthetic_module_export<'s>(
547 &self,
548 scope: &mut PinScope<'s, '_>,
549 export_name: Local<'s, String>,
550 export_value: Local<'s, Value>,
551 ) -> Option<bool> {
552 unsafe {
553 v8__Module__SetSyntheticModuleExport(
554 self,
555 scope.get_isolate_ptr(),
556 &*export_name,
557 &*export_value,
558 )
559 }
560 .into()
561 }
562
563 #[inline(always)]
564 pub fn get_unbound_module_script<'s>(
565 &self,
566 scope: &PinScope<'s, '_>,
567 ) -> Local<'s, UnboundModuleScript> {
568 unsafe {
569 scope
570 .cast_local(|_| v8__Module__GetUnboundModuleScript(self))
571 .unwrap()
572 }
573 }
574
575 pub fn get_stalled_top_level_await_message<'s>(
581 &self,
582 scope: &PinScope<'s, '_, ()>,
583 ) -> Vec<(Local<'s, Module>, Local<'s, Message>)> {
584 let mut out_vec: Vec<StalledTopLevelAwaitMessage> = Vec::with_capacity(16);
585 for _i in 0..16 {
586 out_vec.push(StalledTopLevelAwaitMessage {
587 module: std::ptr::null(),
588 message: std::ptr::null(),
589 });
590 }
591
592 let returned_len = unsafe {
593 v8__Module__GetStalledTopLevelAwaitMessage(
594 self,
595 scope.get_isolate_ptr(),
596 out_vec.as_mut_ptr(),
597 out_vec.len(),
598 )
599 };
600
601 let mut ret_vec = Vec::with_capacity(returned_len);
602 for item in out_vec.iter().take(returned_len) {
603 unsafe {
604 ret_vec.push((
605 Local::from_raw(item.module).unwrap(),
606 Local::from_raw(item.message).unwrap(),
607 ));
608 }
609 }
610 ret_vec
611 }
612}
613
614impl ModuleRequest {
615 #[inline(always)]
617 pub fn get_specifier<'o>(&self) -> Local<'o, String> {
618 unsafe { Local::from_raw(v8__ModuleRequest__GetSpecifier(self)) }.unwrap()
619 }
620
621 #[inline(always)]
623 pub fn get_phase(&self) -> ModuleImportPhase {
624 unsafe { v8__ModuleRequest__GetPhase(self) }
625 }
626 #[inline(always)]
629 pub fn get_source_offset(&self) -> int {
630 unsafe { v8__ModuleRequest__GetSourceOffset(self) }
631 }
632
633 #[inline(always)]
646 pub fn get_import_attributes<'o>(&self) -> Local<'o, FixedArray> {
647 unsafe { Local::from_raw(v8__ModuleRequest__GetImportAttributes(self)) }
648 .unwrap()
649 }
650}