1use std::mem::MaybeUninit;
2use std::num::NonZeroI32;
3use std::ptr::null;
4
5use crate::Context;
6use crate::FixedArray;
7use crate::HandleScope;
8use crate::Isolate;
9use crate::Local;
10use crate::Message;
11use crate::Module;
12use crate::ModuleRequest;
13use crate::Object;
14use crate::String;
15use crate::UnboundModuleScript;
16use crate::Value;
17use crate::support::MapFnFrom;
18use crate::support::MapFnTo;
19use crate::support::MaybeBool;
20use crate::support::ToCFn;
21use crate::support::UnitType;
22use crate::support::int;
23
24#[cfg(not(target_os = "windows"))]
43#[repr(C)]
44pub struct ResolveModuleCallbackRet(*const Module);
46
47#[cfg(not(target_os = "windows"))]
48pub type ResolveModuleCallback<'a> =
49 unsafe extern "C" fn(
50 Local<'a, Context>,
51 Local<'a, String>,
52 Local<'a, FixedArray>,
53 Local<'a, Module>,
54 ) -> ResolveModuleCallbackRet;
55
56#[cfg(target_os = "windows")]
58pub type ResolveModuleCallback<'a> = unsafe extern "C" fn(
59 *mut *const Module,
60 Local<'a, Context>,
61 Local<'a, String>,
62 Local<'a, FixedArray>,
63 Local<'a, Module>,
64)
65 -> *mut *const Module;
66
67impl<'a, F> MapFnFrom<F> for ResolveModuleCallback<'a>
68where
69 F: UnitType
70 + Fn(
71 Local<'a, Context>,
72 Local<'a, String>,
73 Local<'a, FixedArray>,
74 Local<'a, Module>,
75 ) -> Option<Local<'a, Module>>,
76{
77 #[cfg(not(target_os = "windows"))]
78 fn mapping() -> Self {
79 let f = |context, specifier, import_attributes, referrer| {
80 ResolveModuleCallbackRet(
81 (F::get())(context, specifier, import_attributes, referrer)
82 .map(|r| -> *const Module { &*r })
83 .unwrap_or(null()),
84 )
85 };
86 f.to_c_fn()
87 }
88
89 #[cfg(target_os = "windows")]
90 fn mapping() -> Self {
91 let f = |ret_ptr, context, specifier, import_attributes, referrer| {
92 let r = (F::get())(context, specifier, import_attributes, referrer)
93 .map(|r| -> *const Module { &*r })
94 .unwrap_or(null());
95 unsafe { std::ptr::write(ret_ptr, r) }; ret_ptr };
98 f.to_c_fn()
99 }
100}
101
102#[cfg(not(target_os = "windows"))]
104#[repr(C)]
105pub struct SyntheticModuleEvaluationStepsRet(*const Value);
106
107#[cfg(not(target_os = "windows"))]
108pub type SyntheticModuleEvaluationSteps<'a> =
109 unsafe extern "C" fn(
110 Local<'a, Context>,
111 Local<'a, Module>,
112 ) -> SyntheticModuleEvaluationStepsRet;
113
114#[cfg(target_os = "windows")]
116pub type SyntheticModuleEvaluationSteps<'a> =
117 unsafe extern "C" fn(
118 *mut *const Value,
119 Local<'a, Context>,
120 Local<'a, Module>,
121 ) -> *mut *const Value;
122
123impl<'a, F> MapFnFrom<F> for SyntheticModuleEvaluationSteps<'a>
124where
125 F: UnitType
126 + Fn(Local<'a, Context>, Local<'a, Module>) -> Option<Local<'a, Value>>,
127{
128 #[cfg(not(target_os = "windows"))]
129 fn mapping() -> Self {
130 let f = |context, module| {
131 SyntheticModuleEvaluationStepsRet(
132 (F::get())(context, module).map_or(null(), |r| -> *const Value { &*r }),
133 )
134 };
135 f.to_c_fn()
136 }
137
138 #[cfg(target_os = "windows")]
139 fn mapping() -> Self {
140 let f = |ret_ptr, context, module| {
141 let r = (F::get())(context, module)
142 .map(|r| -> *const Value { &*r })
143 .unwrap_or(null());
144 unsafe { std::ptr::write(ret_ptr, r) }; ret_ptr };
147 f.to_c_fn()
148 }
149}
150
151#[cfg(not(target_os = "windows"))]
153#[repr(C)]
154pub struct ResolveSourceCallbackRet(*const Object);
155
156#[cfg(not(target_os = "windows"))]
157pub type ResolveSourceCallback<'a> =
158 unsafe extern "C" fn(
159 Local<'a, Context>,
160 Local<'a, String>,
161 Local<'a, FixedArray>,
162 Local<'a, Module>,
163 ) -> ResolveSourceCallbackRet;
164
165#[cfg(target_os = "windows")]
167pub type ResolveSourceCallback<'a> = unsafe extern "C" fn(
168 *mut *const Object,
169 Local<'a, Context>,
170 Local<'a, String>,
171 Local<'a, FixedArray>,
172 Local<'a, Module>,
173)
174 -> *mut *const Object;
175
176impl<'a, F> MapFnFrom<F> for ResolveSourceCallback<'a>
177where
178 F: UnitType
179 + Fn(
180 Local<'a, Context>,
181 Local<'a, String>,
182 Local<'a, FixedArray>,
183 Local<'a, Module>,
184 ) -> Option<Local<'a, Object>>,
185{
186 #[cfg(not(target_os = "windows"))]
187 fn mapping() -> Self {
188 let f = |context, specifier, import_attributes, referrer| {
189 ResolveSourceCallbackRet(
190 (F::get())(context, specifier, import_attributes, referrer)
191 .map(|r| -> *const Object { &*r })
192 .unwrap_or(null()),
193 )
194 };
195 f.to_c_fn()
196 }
197
198 #[cfg(target_os = "windows")]
199 fn mapping() -> Self {
200 let f = |ret_ptr, context, specifier, import_attributes, referrer| {
201 let r = (F::get())(context, specifier, import_attributes, referrer)
202 .map(|r| -> *const Object { &*r })
203 .unwrap_or(null());
204 unsafe { std::ptr::write(ret_ptr, r) }; ret_ptr };
207 f.to_c_fn()
208 }
209}
210
211unsafe extern "C" {
212 fn v8__Module__GetStatus(this: *const Module) -> ModuleStatus;
213 fn v8__Module__GetException(this: *const Module) -> *const Value;
214 fn v8__Module__GetModuleRequests(this: *const Module) -> *const FixedArray;
215 fn v8__Module__SourceOffsetToLocation(
216 this: *const Module,
217 offset: int,
218 out: *mut Location,
219 );
220 fn v8__Module__GetModuleNamespace(this: *const Module) -> *const Value;
221 fn v8__Module__GetIdentityHash(this: *const Module) -> int;
222 fn v8__Module__ScriptId(this: *const Module) -> int;
223 fn v8__Module__InstantiateModule(
224 this: *const Module,
225 context: *const Context,
226 cb: ResolveModuleCallback,
227 source_callback: Option<ResolveSourceCallback>,
228 ) -> MaybeBool;
229 fn v8__Module__Evaluate(
230 this: *const Module,
231 context: *const Context,
232 ) -> *const Value;
233 fn v8__Module__IsGraphAsync(this: *const Module) -> bool;
234 fn v8__Module__IsSourceTextModule(this: *const Module) -> bool;
235 fn v8__Module__IsSyntheticModule(this: *const Module) -> bool;
236 fn v8__Module__CreateSyntheticModule(
237 isolate: *const Isolate,
238 module_name: *const String,
239 export_names_len: usize,
240 export_names_raw: *const *const String,
241 evaluation_steps: SyntheticModuleEvaluationSteps,
242 ) -> *const Module;
243 fn v8__Module__SetSyntheticModuleExport(
244 this: *const Module,
245 isolate: *const Isolate,
246 export_name: *const String,
247 export_value: *const Value,
248 ) -> MaybeBool;
249 fn v8__Module__GetUnboundModuleScript(
250 this: *const Module,
251 ) -> *const UnboundModuleScript;
252 fn v8__Location__GetLineNumber(this: *const Location) -> int;
253 fn v8__Location__GetColumnNumber(this: *const Location) -> int;
254 fn v8__ModuleRequest__GetSpecifier(
255 this: *const ModuleRequest,
256 ) -> *const String;
257 fn v8__ModuleRequest__GetSourceOffset(this: *const ModuleRequest) -> int;
258 fn v8__ModuleRequest__GetImportAttributes(
259 this: *const ModuleRequest,
260 ) -> *const FixedArray;
261 fn v8__Module__GetStalledTopLevelAwaitMessage(
262 this: *const Module,
263 isolate: *const Isolate,
264 out_vec: *mut StalledTopLevelAwaitMessage,
265 vec_len: usize,
266 ) -> usize;
267}
268
269#[repr(C)]
270pub struct StalledTopLevelAwaitMessage {
271 pub module: *const Module,
272 pub message: *const Message,
273}
274
275#[repr(C)]
277#[derive(Debug)]
278pub struct Location([i32; 2]);
279
280impl Location {
281 pub fn get_line_number(&self) -> int {
282 unsafe { v8__Location__GetLineNumber(self) }
283 }
284
285 pub fn get_column_number(&self) -> int {
286 unsafe { v8__Location__GetColumnNumber(self) }
287 }
288}
289
290#[derive(Debug, PartialEq, Eq)]
296#[repr(C)]
297pub enum ModuleStatus {
298 Uninstantiated,
299 Instantiating,
300 Instantiated,
301 Evaluating,
302 Evaluated,
303 Errored,
304}
305
306impl Module {
307 #[inline(always)]
309 pub fn get_status(&self) -> ModuleStatus {
310 unsafe { v8__Module__GetStatus(self) }
311 }
312
313 #[inline(always)]
315 pub fn get_exception(&self) -> Local<Value> {
316 unsafe { Local::from_raw(v8__Module__GetException(self)) }.unwrap()
319 }
320
321 #[inline(always)]
323 pub fn get_module_requests(&self) -> Local<FixedArray> {
324 unsafe { Local::from_raw(v8__Module__GetModuleRequests(self)) }.unwrap()
325 }
326
327 #[inline(always)]
330 pub fn source_offset_to_location(&self, offset: int) -> Location {
331 let mut out = MaybeUninit::<Location>::uninit();
332 unsafe {
333 v8__Module__SourceOffsetToLocation(self, offset, out.as_mut_ptr());
334 out.assume_init()
335 }
336 }
337
338 #[inline(always)]
344 pub fn get_identity_hash(&self) -> NonZeroI32 {
345 unsafe { NonZeroI32::new_unchecked(v8__Module__GetIdentityHash(self)) }
346 }
347
348 #[inline(always)]
352 pub fn script_id(&self) -> Option<int> {
353 if !self.is_source_text_module() {
354 return None;
355 }
356 if self.get_status() == ModuleStatus::Errored {
357 return None;
358 }
359 Some(unsafe { v8__Module__ScriptId(self) })
360 }
361
362 #[inline(always)]
366 pub fn get_module_namespace(&self) -> Local<Value> {
367 unsafe { Local::from_raw(v8__Module__GetModuleNamespace(self)).unwrap() }
370 }
371
372 #[must_use]
378 #[inline(always)]
379 pub fn instantiate_module<'a>(
380 &self,
381 scope: &mut HandleScope,
382 callback: impl MapFnTo<ResolveModuleCallback<'a>>,
383 ) -> Option<bool> {
384 unsafe {
385 v8__Module__InstantiateModule(
386 self,
387 &*scope.get_current_context(),
388 callback.map_fn_to(),
389 None,
390 )
391 }
392 .into()
393 }
394
395 #[must_use]
401 #[inline(always)]
402 pub fn instantiate_module2<'a>(
403 &self,
404 scope: &mut HandleScope,
405 callback: impl MapFnTo<ResolveModuleCallback<'a>>,
406 source_callback: impl MapFnTo<ResolveSourceCallback<'a>>,
407 ) -> Option<bool> {
408 unsafe {
409 v8__Module__InstantiateModule(
410 self,
411 &*scope.get_current_context(),
412 callback.map_fn_to(),
413 Some(source_callback.map_fn_to()),
414 )
415 }
416 .into()
417 }
418
419 #[must_use]
426 #[inline(always)]
427 pub fn evaluate<'s>(
428 &self,
429 scope: &mut HandleScope<'s>,
430 ) -> Option<Local<'s, Value>> {
431 unsafe {
432 scope
433 .cast_local(|sd| v8__Module__Evaluate(self, sd.get_current_context()))
434 }
435 }
436
437 #[inline(always)]
442 pub fn is_graph_async(&self) -> bool {
443 unsafe { v8__Module__IsGraphAsync(self) }
444 }
445
446 #[inline(always)]
448 pub fn is_source_text_module(&self) -> bool {
449 unsafe { v8__Module__IsSourceTextModule(self) }
450 }
451
452 #[inline(always)]
454 pub fn is_synthetic_module(&self) -> bool {
455 unsafe { v8__Module__IsSyntheticModule(self) }
456 }
457
458 #[inline(always)]
464 pub fn create_synthetic_module<'s, 'a>(
465 scope: &mut HandleScope<'s>,
466 module_name: Local<String>,
467 export_names: &[Local<String>],
468 evaluation_steps: impl MapFnTo<SyntheticModuleEvaluationSteps<'a>>,
469 ) -> Local<'s, Module> {
470 let export_names = Local::slice_into_raw(export_names);
471 let export_names_len = export_names.len();
472 let export_names = export_names.as_ptr();
473 unsafe {
474 scope
475 .cast_local(|sd| {
476 v8__Module__CreateSyntheticModule(
477 sd.get_isolate_ptr(),
478 &*module_name,
479 export_names_len,
480 export_names,
481 evaluation_steps.map_fn_to(),
482 )
483 })
484 .unwrap()
485 }
486 }
487
488 #[must_use]
494 #[inline(always)]
495 pub fn set_synthetic_module_export(
496 &self,
497 scope: &mut HandleScope,
498 export_name: Local<String>,
499 export_value: Local<Value>,
500 ) -> Option<bool> {
501 unsafe {
502 v8__Module__SetSyntheticModuleExport(
503 self,
504 scope.get_isolate_ptr(),
505 &*export_name,
506 &*export_value,
507 )
508 }
509 .into()
510 }
511
512 #[inline(always)]
513 pub fn get_unbound_module_script<'s>(
514 &self,
515 scope: &mut HandleScope<'s>,
516 ) -> Local<'s, UnboundModuleScript> {
517 unsafe {
518 scope
519 .cast_local(|_| v8__Module__GetUnboundModuleScript(self))
520 .unwrap()
521 }
522 }
523
524 pub fn get_stalled_top_level_await_message(
530 &self,
531 scope: &mut HandleScope,
532 ) -> Vec<(Local<Module>, Local<Message>)> {
533 let mut out_vec: Vec<StalledTopLevelAwaitMessage> = Vec::with_capacity(16);
534 for _i in 0..16 {
535 out_vec.push(StalledTopLevelAwaitMessage {
536 module: std::ptr::null(),
537 message: std::ptr::null(),
538 });
539 }
540
541 let returned_len = unsafe {
542 v8__Module__GetStalledTopLevelAwaitMessage(
543 self,
544 scope.get_isolate_ptr(),
545 out_vec.as_mut_ptr(),
546 out_vec.len(),
547 )
548 };
549
550 let mut ret_vec = Vec::with_capacity(returned_len);
551 for item in out_vec.iter().take(returned_len) {
552 unsafe {
553 ret_vec.push((
554 Local::from_raw(item.module).unwrap(),
555 Local::from_raw(item.message).unwrap(),
556 ));
557 }
558 }
559 ret_vec
560 }
561}
562
563impl ModuleRequest {
564 #[inline(always)]
566 pub fn get_specifier(&self) -> Local<String> {
567 unsafe { Local::from_raw(v8__ModuleRequest__GetSpecifier(self)) }.unwrap()
568 }
569
570 #[inline(always)]
573 pub fn get_source_offset(&self) -> int {
574 unsafe { v8__ModuleRequest__GetSourceOffset(self) }
575 }
576
577 #[inline(always)]
590 pub fn get_import_attributes(&self) -> Local<FixedArray> {
591 unsafe { Local::from_raw(v8__ModuleRequest__GetImportAttributes(self)) }
592 .unwrap()
593 }
594}