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__GetIdentityHash(this: *const Module) -> int;
224 fn v8__Module__ScriptId(this: *const Module) -> int;
225 fn v8__Module__InstantiateModule(
226 this: *const Module,
227 context: *const Context,
228 cb: ResolveModuleCallback,
229 source_callback: Option<ResolveSourceCallback>,
230 ) -> MaybeBool;
231 fn v8__Module__Evaluate(
232 this: *const Module,
233 context: *const Context,
234 ) -> *const Value;
235 fn v8__Module__IsGraphAsync(this: *const Module) -> bool;
236 fn v8__Module__IsSourceTextModule(this: *const Module) -> bool;
237 fn v8__Module__IsSyntheticModule(this: *const Module) -> bool;
238 fn v8__Module__CreateSyntheticModule(
239 isolate: *const RealIsolate,
240 module_name: *const String,
241 export_names_len: usize,
242 export_names_raw: *const *const String,
243 evaluation_steps: SyntheticModuleEvaluationSteps,
244 ) -> *const Module;
245 fn v8__Module__SetSyntheticModuleExport(
246 this: *const Module,
247 isolate: *const RealIsolate,
248 export_name: *const String,
249 export_value: *const Value,
250 ) -> MaybeBool;
251 fn v8__Module__GetUnboundModuleScript(
252 this: *const Module,
253 ) -> *const UnboundModuleScript;
254 fn v8__Location__GetLineNumber(this: *const Location) -> int;
255 fn v8__Location__GetColumnNumber(this: *const Location) -> int;
256 fn v8__ModuleRequest__GetSpecifier(
257 this: *const ModuleRequest,
258 ) -> *const String;
259 fn v8__ModuleRequest__GetPhase(
260 this: *const ModuleRequest,
261 ) -> ModuleImportPhase;
262 fn v8__ModuleRequest__GetSourceOffset(this: *const ModuleRequest) -> int;
263 fn v8__ModuleRequest__GetImportAttributes(
264 this: *const ModuleRequest,
265 ) -> *const FixedArray;
266 fn v8__Module__GetStalledTopLevelAwaitMessage(
267 this: *const Module,
268 isolate: *const RealIsolate,
269 out_vec: *mut StalledTopLevelAwaitMessage,
270 vec_len: usize,
271 ) -> usize;
272}
273
274#[repr(C)]
275pub struct StalledTopLevelAwaitMessage {
276 pub module: *const Module,
277 pub message: *const Message,
278}
279
280#[repr(C)]
282#[derive(Debug)]
283pub struct Location([i32; 2]);
284
285impl Location {
286 pub fn get_line_number(&self) -> int {
287 unsafe { v8__Location__GetLineNumber(self) }
288 }
289
290 pub fn get_column_number(&self) -> int {
291 unsafe { v8__Location__GetColumnNumber(self) }
292 }
293}
294
295#[derive(Debug, PartialEq, Eq)]
301#[repr(C)]
302pub enum ModuleStatus {
303 Uninstantiated,
304 Instantiating,
305 Instantiated,
306 Evaluating,
307 Evaluated,
308 Errored,
309}
310
311impl Module {
312 #[inline(always)]
314 pub fn get_status(&self) -> ModuleStatus {
315 unsafe { v8__Module__GetStatus(self) }
316 }
317
318 #[inline(always)]
320 pub fn get_exception<'o>(&self) -> Local<'o, Value> {
321 unsafe { Local::from_raw(v8__Module__GetException(self)) }.unwrap()
324 }
325
326 #[inline(always)]
328 pub fn get_module_requests<'o>(&self) -> Local<'o, FixedArray> {
329 unsafe { Local::from_raw(v8__Module__GetModuleRequests(self)) }.unwrap()
330 }
331
332 #[inline(always)]
335 pub fn source_offset_to_location(&self, offset: int) -> Location {
336 let mut out = MaybeUninit::<Location>::uninit();
337 unsafe {
338 v8__Module__SourceOffsetToLocation(self, offset, out.as_mut_ptr());
339 out.assume_init()
340 }
341 }
342
343 #[inline(always)]
349 pub fn get_identity_hash(&self) -> NonZeroI32 {
350 unsafe { NonZeroI32::new_unchecked(v8__Module__GetIdentityHash(self)) }
351 }
352
353 #[inline(always)]
357 pub fn script_id(&self) -> Option<int> {
358 if !self.is_source_text_module() {
359 return None;
360 }
361 if self.get_status() == ModuleStatus::Errored {
362 return None;
363 }
364 Some(unsafe { v8__Module__ScriptId(self) })
365 }
366
367 #[inline(always)]
371 pub fn get_module_namespace<'o>(&self) -> Local<'o, Value> {
372 unsafe { Local::from_raw(v8__Module__GetModuleNamespace(self)).unwrap() }
375 }
376
377 #[must_use]
383 #[inline(always)]
384 pub fn instantiate_module<'s, 'i>(
385 &self,
386 scope: &PinScope<'s, 'i>,
387 callback: impl MapFnTo<ResolveModuleCallback<'s>>,
388 ) -> Option<bool> {
389 unsafe {
390 v8__Module__InstantiateModule(
391 self,
392 &*scope.get_current_context(),
393 callback.map_fn_to(),
394 None,
395 )
396 }
397 .into()
398 }
399
400 #[must_use]
406 #[inline(always)]
407 pub fn instantiate_module2<'s, 'i>(
408 &self,
409 scope: &PinScope<'s, 'i>,
410 callback: impl MapFnTo<ResolveModuleCallback<'s>>,
411 source_callback: impl MapFnTo<ResolveSourceCallback<'s>>,
412 ) -> Option<bool> {
413 unsafe {
414 v8__Module__InstantiateModule(
415 self,
416 &*scope.get_current_context(),
417 callback.map_fn_to(),
418 Some(source_callback.map_fn_to()),
419 )
420 }
421 .into()
422 }
423
424 #[must_use]
431 #[inline(always)]
432 pub fn evaluate<'s>(
433 &self,
434 scope: &PinScope<'s, '_>,
435 ) -> Option<Local<'s, Value>> {
436 unsafe {
437 scope
438 .cast_local(|sd| v8__Module__Evaluate(self, sd.get_current_context()))
439 }
440 }
441
442 #[inline(always)]
447 pub fn is_graph_async(&self) -> bool {
448 unsafe { v8__Module__IsGraphAsync(self) }
449 }
450
451 #[inline(always)]
453 pub fn is_source_text_module(&self) -> bool {
454 unsafe { v8__Module__IsSourceTextModule(self) }
455 }
456
457 #[inline(always)]
459 pub fn is_synthetic_module(&self) -> bool {
460 unsafe { v8__Module__IsSyntheticModule(self) }
461 }
462
463 #[inline(always)]
469 pub fn create_synthetic_module<'s, 'i>(
470 scope: &PinScope<'s, 'i>,
471 module_name: Local<String>,
472 export_names: &[Local<String>],
473 evaluation_steps: impl MapFnTo<SyntheticModuleEvaluationSteps<'s>>,
474 ) -> Local<'s, Module> {
475 let export_names = Local::slice_into_raw(export_names);
476 let export_names_len = export_names.len();
477 let export_names = export_names.as_ptr();
478 unsafe {
479 scope
480 .cast_local(|sd| {
481 v8__Module__CreateSyntheticModule(
482 sd.get_isolate_ptr(),
483 &*module_name,
484 export_names_len,
485 export_names,
486 evaluation_steps.map_fn_to(),
487 )
488 })
489 .unwrap()
490 }
491 }
492
493 #[must_use]
499 #[inline(always)]
500 pub fn set_synthetic_module_export<'s>(
501 &self,
502 scope: &mut PinScope<'s, '_>,
503 export_name: Local<'s, String>,
504 export_value: Local<'s, Value>,
505 ) -> Option<bool> {
506 unsafe {
507 v8__Module__SetSyntheticModuleExport(
508 self,
509 scope.get_isolate_ptr(),
510 &*export_name,
511 &*export_value,
512 )
513 }
514 .into()
515 }
516
517 #[inline(always)]
518 pub fn get_unbound_module_script<'s>(
519 &self,
520 scope: &PinScope<'s, '_>,
521 ) -> Local<'s, UnboundModuleScript> {
522 unsafe {
523 scope
524 .cast_local(|_| v8__Module__GetUnboundModuleScript(self))
525 .unwrap()
526 }
527 }
528
529 pub fn get_stalled_top_level_await_message<'s>(
535 &self,
536 scope: &PinScope<'s, '_, ()>,
537 ) -> Vec<(Local<'s, Module>, Local<'s, Message>)> {
538 let mut out_vec: Vec<StalledTopLevelAwaitMessage> = Vec::with_capacity(16);
539 for _i in 0..16 {
540 out_vec.push(StalledTopLevelAwaitMessage {
541 module: std::ptr::null(),
542 message: std::ptr::null(),
543 });
544 }
545
546 let returned_len = unsafe {
547 v8__Module__GetStalledTopLevelAwaitMessage(
548 self,
549 scope.get_isolate_ptr(),
550 out_vec.as_mut_ptr(),
551 out_vec.len(),
552 )
553 };
554
555 let mut ret_vec = Vec::with_capacity(returned_len);
556 for item in out_vec.iter().take(returned_len) {
557 unsafe {
558 ret_vec.push((
559 Local::from_raw(item.module).unwrap(),
560 Local::from_raw(item.message).unwrap(),
561 ));
562 }
563 }
564 ret_vec
565 }
566}
567
568impl ModuleRequest {
569 #[inline(always)]
571 pub fn get_specifier<'o>(&self) -> Local<'o, String> {
572 unsafe { Local::from_raw(v8__ModuleRequest__GetSpecifier(self)) }.unwrap()
573 }
574
575 #[inline(always)]
577 pub fn get_phase(&self) -> ModuleImportPhase {
578 unsafe { v8__ModuleRequest__GetPhase(self) }
579 }
580 #[inline(always)]
583 pub fn get_source_offset(&self) -> int {
584 unsafe { v8__ModuleRequest__GetSourceOffset(self) }
585 }
586
587 #[inline(always)]
600 pub fn get_import_attributes<'o>(&self) -> Local<'o, FixedArray> {
601 unsafe { Local::from_raw(v8__ModuleRequest__GetImportAttributes(self)) }
602 .unwrap()
603 }
604}