use std::convert::TryInto;
use std::hash::Hash;
use std::hash::Hasher;
use std::mem::MaybeUninit;
use std::ptr::null;
use crate::support::int;
use crate::support::MapFnFrom;
use crate::support::MapFnTo;
use crate::support::MaybeBool;
use crate::support::ToCFn;
use crate::support::UnitType;
use crate::Context;
use crate::FixedArray;
use crate::HandleScope;
use crate::Isolate;
use crate::Local;
use crate::Module;
use crate::ModuleRequest;
use crate::String;
use crate::UnboundModuleScript;
use crate::Value;
#[cfg(not(target_os = "windows"))]
pub type ResolveModuleCallback<'a> = extern "C" fn(
Local<'a, Context>,
Local<'a, String>,
Local<'a, FixedArray>,
Local<'a, Module>,
) -> *const Module;
#[cfg(target_os = "windows")]
pub type ResolveModuleCallback<'a> = extern "C" fn(
*mut *const Module,
Local<'a, Context>,
Local<'a, String>,
Local<'a, FixedArray>,
Local<'a, Module>,
) -> *mut *const Module;
impl<'a, F> MapFnFrom<F> for ResolveModuleCallback<'a>
where
F: UnitType
+ Fn(
Local<'a, Context>,
Local<'a, String>,
Local<'a, FixedArray>,
Local<'a, Module>,
) -> Option<Local<'a, Module>>,
{
#[cfg(not(target_os = "windows"))]
fn mapping() -> Self {
let f = |context, specifier, import_assertions, referrer| {
(F::get())(context, specifier, import_assertions, referrer)
.map(|r| -> *const Module { &*r })
.unwrap_or(null())
};
f.to_c_fn()
}
#[cfg(target_os = "windows")]
fn mapping() -> Self {
let f = |ret_ptr, context, specifier, import_assertions, referrer| {
let r = (F::get())(context, specifier, import_assertions, referrer)
.map(|r| -> *const Module { &*r })
.unwrap_or(null());
unsafe { std::ptr::write(ret_ptr, r) };
ret_ptr
};
f.to_c_fn()
}
}
#[cfg(not(target_os = "windows"))]
pub type SyntheticModuleEvaluationSteps<'a> =
extern "C" fn(Local<'a, Context>, Local<'a, Module>) -> *const Value;
#[cfg(target_os = "windows")]
pub type SyntheticModuleEvaluationSteps<'a> =
extern "C" fn(
*mut *const Value,
Local<'a, Context>,
Local<'a, Module>,
) -> *mut *const Value;
impl<'a, F> MapFnFrom<F> for SyntheticModuleEvaluationSteps<'a>
where
F: UnitType
+ Fn(Local<'a, Context>, Local<'a, Module>) -> Option<Local<'a, Value>>,
{
#[cfg(not(target_os = "windows"))]
fn mapping() -> Self {
let f = |context, module| {
(F::get())(context, module)
.map(|r| -> *const Value { &*r })
.unwrap_or(null())
};
f.to_c_fn()
}
#[cfg(target_os = "windows")]
fn mapping() -> Self {
let f = |ret_ptr, context, module| {
let r = (F::get())(context, module)
.map(|r| -> *const Value { &*r })
.unwrap_or(null());
unsafe { std::ptr::write(ret_ptr, r) };
ret_ptr
};
f.to_c_fn()
}
}
extern "C" {
fn v8__Module__GetStatus(this: *const Module) -> ModuleStatus;
fn v8__Module__GetException(this: *const Module) -> *const Value;
fn v8__Module__GetModuleRequestsLength(this: *const Module) -> int;
fn v8__Module__GetModuleRequest(this: *const Module, i: int)
-> *const String;
fn v8__Module__GetModuleRequests(this: *const Module) -> *const FixedArray;
fn v8__Module__GetModuleRequestLocation(
this: *const Module,
i: int,
out: *mut MaybeUninit<Location>,
) -> Location;
fn v8__Module__SourceOffsetToLocation(
this: *const Module,
offset: int,
out: *mut MaybeUninit<Location>,
) -> Location;
fn v8__Module__GetModuleNamespace(this: *const Module) -> *const Value;
fn v8__Module__GetIdentityHash(this: *const Module) -> int;
fn v8__Module__ScriptId(this: *const Module) -> int;
fn v8__Module__InstantiateModule(
this: *const Module,
context: *const Context,
cb: ResolveModuleCallback,
) -> MaybeBool;
fn v8__Module__Evaluate(
this: *const Module,
context: *const Context,
) -> *const Value;
fn v8__Module__IsSourceTextModule(this: *const Module) -> bool;
fn v8__Module__IsSyntheticModule(this: *const Module) -> bool;
fn v8__Module__CreateSyntheticModule(
isolate: *const Isolate,
module_name: *const String,
export_names_len: usize,
export_names_raw: *const *const String,
evaluation_steps: SyntheticModuleEvaluationSteps,
) -> *const Module;
fn v8__Module__SetSyntheticModuleExport(
this: *const Module,
isolate: *const Isolate,
export_name: *const String,
export_value: *const Value,
) -> MaybeBool;
fn v8__Module__GetUnboundModuleScript(
this: *const Module,
) -> *const UnboundModuleScript;
fn v8__Location__GetLineNumber(this: *const Location) -> int;
fn v8__Location__GetColumnNumber(this: *const Location) -> int;
fn v8__ModuleRequest__GetSpecifier(
this: *const ModuleRequest,
) -> *const String;
fn v8__ModuleRequest__GetSourceOffset(this: *const ModuleRequest) -> int;
fn v8__ModuleRequest__GetImportAssertions(
this: *const ModuleRequest,
) -> *const FixedArray;
}
#[repr(C)]
#[derive(Debug)]
pub struct Location([usize; 1]);
impl Location {
pub fn get_line_number(&self) -> int {
unsafe { v8__Location__GetLineNumber(self) }
}
pub fn get_column_number(&self) -> int {
unsafe { v8__Location__GetColumnNumber(self) }
}
}
#[derive(Debug, PartialEq)]
#[repr(C)]
pub enum ModuleStatus {
Uninstantiated,
Instantiating,
Instantiated,
Evaluating,
Evaluated,
Errored,
}
impl Module {
pub fn get_status(&self) -> ModuleStatus {
unsafe { v8__Module__GetStatus(self) }
}
pub fn get_exception(&self) -> Local<Value> {
unsafe { Local::from_raw(v8__Module__GetException(self)) }.unwrap()
}
#[deprecated(
since = "0.18.2",
note = "Use Module::get_module_requests() and FixedArray::length()."
)]
pub fn get_module_requests_length(&self) -> usize {
unsafe { v8__Module__GetModuleRequestsLength(self) }
.try_into()
.unwrap()
}
#[deprecated(
since = "0.18.2",
note = "Use Module::get_module_requests() and ModuleRequest::get_specifier()."
)]
pub fn get_module_request(&self, i: usize) -> Local<String> {
unsafe {
Local::from_raw(v8__Module__GetModuleRequest(self, i.try_into().unwrap()))
}
.unwrap()
}
pub fn get_module_requests(&self) -> Local<FixedArray> {
unsafe { Local::from_raw(v8__Module__GetModuleRequests(self)) }.unwrap()
}
#[deprecated(
since = "0.18.2",
note = "Use Module::get_module_requests(), ModuleRequest::get_source_offset() and
Module::source_offset_to_location()."
)]
pub fn get_module_request_location(&self, i: usize) -> Location {
let mut out = MaybeUninit::<Location>::uninit();
unsafe {
v8__Module__GetModuleRequestLocation(
self,
i.try_into().unwrap(),
&mut out,
);
out.assume_init()
}
}
pub fn source_offset_to_location(&self, offset: int) -> Location {
let mut out = MaybeUninit::<Location>::uninit();
unsafe {
v8__Module__SourceOffsetToLocation(self, offset, &mut out);
out.assume_init()
}
}
#[doc(hidden)]
pub fn get_identity_hash(&self) -> int {
unsafe { v8__Module__GetIdentityHash(self) }
}
pub fn script_id(&self) -> Option<int> {
if !self.is_source_text_module() {
return None;
}
if self.get_status() == ModuleStatus::Errored {
return None;
}
Some(unsafe { v8__Module__ScriptId(self) })
}
pub fn get_module_namespace(&self) -> Local<Value> {
unsafe { Local::from_raw(v8__Module__GetModuleNamespace(self)).unwrap() }
}
#[must_use]
pub fn instantiate_module<'a>(
&self,
scope: &mut HandleScope,
callback: impl MapFnTo<ResolveModuleCallback<'a>>,
) -> Option<bool> {
unsafe {
v8__Module__InstantiateModule(
self,
&*scope.get_current_context(),
callback.map_fn_to(),
)
}
.into()
}
#[must_use]
pub fn evaluate<'s>(
&self,
scope: &mut HandleScope<'s>,
) -> Option<Local<'s, Value>> {
unsafe {
scope
.cast_local(|sd| v8__Module__Evaluate(&*self, sd.get_current_context()))
}
}
pub fn is_source_text_module(&self) -> bool {
unsafe { v8__Module__IsSourceTextModule(&*self) }
}
pub fn is_synthetic_module(&self) -> bool {
unsafe { v8__Module__IsSyntheticModule(&*self) }
}
pub fn create_synthetic_module<'s, 'a>(
scope: &mut HandleScope<'s>,
module_name: Local<String>,
export_names: &[Local<String>],
evaluation_steps: impl MapFnTo<SyntheticModuleEvaluationSteps<'a>>,
) -> Local<'s, Module> {
let export_names = Local::slice_into_raw(export_names);
let export_names_len = export_names.len();
let export_names = export_names.as_ptr();
unsafe {
scope
.cast_local(|sd| {
v8__Module__CreateSyntheticModule(
sd.get_isolate_ptr(),
&*module_name,
export_names_len,
export_names,
evaluation_steps.map_fn_to(),
)
})
.unwrap()
}
}
#[must_use]
pub fn set_synthetic_module_export(
&self,
scope: &mut HandleScope,
export_name: Local<String>,
export_value: Local<Value>,
) -> Option<bool> {
unsafe {
v8__Module__SetSyntheticModuleExport(
&*self,
scope.get_isolate_ptr(),
&*export_name,
&*export_value,
)
}
.into()
}
pub fn get_unbound_module_script<'s>(
&self,
scope: &mut HandleScope<'s>,
) -> Local<'s, UnboundModuleScript> {
unsafe {
scope
.cast_local(|_| v8__Module__GetUnboundModuleScript(self))
.unwrap()
}
}
}
impl Hash for Module {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_i32(self.get_identity_hash());
}
}
impl ModuleRequest {
pub fn get_specifier(&self) -> Local<String> {
unsafe { Local::from_raw(v8__ModuleRequest__GetSpecifier(self)) }.unwrap()
}
pub fn get_source_offset(&self) -> int {
unsafe { v8__ModuleRequest__GetSourceOffset(self) }
}
pub fn get_import_assertions(&self) -> Local<FixedArray> {
unsafe { Local::from_raw(v8__ModuleRequest__GetImportAssertions(self)) }
.unwrap()
}
}