2020-05-31 12:35:41 -04:00
|
|
|
use std::convert::TryInto;
|
2020-01-14 15:06:41 -05:00
|
|
|
use std::mem::MaybeUninit;
|
|
|
|
use std::ptr::null;
|
|
|
|
|
2019-12-20 08:56:32 -05:00
|
|
|
use crate::support::int;
|
2020-01-14 15:06:41 -05:00
|
|
|
use crate::support::MapFnFrom;
|
|
|
|
use crate::support::MapFnTo;
|
2019-12-20 20:54:14 -05:00
|
|
|
use crate::support::MaybeBool;
|
2020-01-14 15:06:41 -05:00
|
|
|
use crate::support::ToCFn;
|
|
|
|
use crate::support::UnitType;
|
2019-12-20 08:56:32 -05:00
|
|
|
use crate::Context;
|
2020-06-03 01:38:34 -04:00
|
|
|
use crate::HandleScope;
|
2019-12-20 08:56:32 -05:00
|
|
|
use crate::Local;
|
2019-12-30 09:28:39 -05:00
|
|
|
use crate::Module;
|
2019-12-20 20:54:14 -05:00
|
|
|
use crate::String;
|
2019-12-20 08:56:32 -05:00
|
|
|
use crate::Value;
|
|
|
|
|
2019-12-23 20:23:55 -05:00
|
|
|
/// Called during Module::instantiate_module. Provided with arguments:
|
2020-01-14 15:06:41 -05:00
|
|
|
/// (context, specifier, referrer). Return None on error.
|
|
|
|
///
|
|
|
|
/// Note: this callback has an unusual signature due to ABI incompatibilities
|
|
|
|
/// between Rust and C++. However end users can implement the callback as
|
|
|
|
/// follows; it'll be automatically converted.
|
|
|
|
///
|
|
|
|
/// ```rust,ignore
|
|
|
|
/// fn my_resolve_callback<'a>(
|
|
|
|
/// context: v8::Local<'a, v8::Context>,
|
|
|
|
/// specifier: v8::Local<'a, v8::String>,
|
|
|
|
/// referrer: v8::Local<'a, v8::Module>,
|
|
|
|
/// ) -> Option<v8::Local<'a, v8::Module>> {
|
|
|
|
/// // ...
|
|
|
|
/// Some(resolved_module)
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
|
|
|
|
// System V AMD64 ABI: Local<Module> returned in a register.
|
|
|
|
#[cfg(not(target_os = "windows"))]
|
|
|
|
pub type ResolveCallback<'a> = extern "C" fn(
|
|
|
|
Local<'a, Context>,
|
|
|
|
Local<'a, String>,
|
|
|
|
Local<'a, Module>,
|
|
|
|
) -> *const Module;
|
|
|
|
|
|
|
|
// Windows x64 ABI: Local<Module> returned on the stack.
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
pub type ResolveCallback<'a> = extern "C" fn(
|
|
|
|
*mut *const Module,
|
|
|
|
Local<'a, Context>,
|
|
|
|
Local<'a, String>,
|
|
|
|
Local<'a, Module>,
|
|
|
|
) -> *mut *const Module;
|
|
|
|
|
|
|
|
impl<'a, F> MapFnFrom<F> for ResolveCallback<'a>
|
|
|
|
where
|
|
|
|
F: UnitType
|
|
|
|
+ Fn(
|
|
|
|
Local<'a, Context>,
|
|
|
|
Local<'a, String>,
|
|
|
|
Local<'a, Module>,
|
|
|
|
) -> Option<Local<'a, Module>>,
|
|
|
|
{
|
|
|
|
#[cfg(not(target_os = "windows"))]
|
|
|
|
fn mapping() -> Self {
|
|
|
|
let f = |context, specifier, referrer| {
|
|
|
|
(F::get())(context, specifier, 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, referrer| {
|
|
|
|
let r = (F::get())(context, specifier, referrer)
|
|
|
|
.map(|r| -> *const Module { &*r })
|
|
|
|
.unwrap_or(null());
|
|
|
|
unsafe { std::ptr::write(ret_ptr, r) }; // Write result to stack.
|
|
|
|
ret_ptr // Return stack pointer to the return value.
|
|
|
|
};
|
|
|
|
f.to_c_fn()
|
|
|
|
}
|
|
|
|
}
|
2019-12-23 18:09:03 -05:00
|
|
|
|
2019-12-20 20:54:14 -05:00
|
|
|
extern "C" {
|
2019-12-23 07:12:52 -05:00
|
|
|
fn v8__Module__GetStatus(this: *const Module) -> ModuleStatus;
|
2020-04-13 08:43:56 -04:00
|
|
|
fn v8__Module__GetException(this: *const Module) -> *const Value;
|
2019-12-23 07:12:52 -05:00
|
|
|
fn v8__Module__GetModuleRequestsLength(this: *const Module) -> int;
|
2020-04-13 08:43:56 -04:00
|
|
|
fn v8__Module__GetModuleRequest(this: *const Module, i: int)
|
|
|
|
-> *const String;
|
2019-12-23 07:12:52 -05:00
|
|
|
fn v8__Module__GetModuleRequestLocation(
|
|
|
|
this: *const Module,
|
2020-05-31 12:35:41 -04:00
|
|
|
i: int,
|
2020-04-13 08:43:56 -04:00
|
|
|
out: *mut MaybeUninit<Location>,
|
2019-12-23 07:12:52 -05:00
|
|
|
) -> Location;
|
2020-04-13 08:43:56 -04:00
|
|
|
fn v8__Module__GetModuleNamespace(this: *const Module) -> *const Value;
|
2019-12-23 07:12:52 -05:00
|
|
|
fn v8__Module__GetIdentityHash(this: *const Module) -> int;
|
2019-12-20 20:54:14 -05:00
|
|
|
fn v8__Module__InstantiateModule(
|
2020-04-13 08:43:56 -04:00
|
|
|
this: *const Module,
|
|
|
|
context: *const Context,
|
|
|
|
cb: ResolveCallback,
|
2019-12-20 20:54:14 -05:00
|
|
|
) -> MaybeBool;
|
2019-12-23 07:12:52 -05:00
|
|
|
fn v8__Module__Evaluate(
|
2020-04-13 08:43:56 -04:00
|
|
|
this: *const Module,
|
|
|
|
context: *const Context,
|
|
|
|
) -> *const Value;
|
|
|
|
fn v8__Location__GetLineNumber(this: *const Location) -> int;
|
|
|
|
fn v8__Location__GetColumnNumber(this: *const Location) -> int;
|
2019-12-23 07:12:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
/// A location in JavaScript source.
|
|
|
|
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) }
|
|
|
|
}
|
2019-12-20 20:54:14 -05:00
|
|
|
}
|
2019-12-20 08:56:32 -05:00
|
|
|
|
|
|
|
/// The different states a module can be in.
|
|
|
|
///
|
|
|
|
/// This corresponds to the states used in ECMAScript except that "evaluated"
|
|
|
|
/// is split into kEvaluated and kErrored, indicating success and failure,
|
|
|
|
/// respectively.
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
#[repr(C)]
|
2019-12-23 07:12:52 -05:00
|
|
|
pub enum ModuleStatus {
|
2019-12-20 08:56:32 -05:00
|
|
|
Uninstantiated,
|
|
|
|
Instantiating,
|
|
|
|
Instantiated,
|
|
|
|
Evaluating,
|
|
|
|
Evaluated,
|
|
|
|
Errored,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Module {
|
|
|
|
/// Returns the module's current status.
|
2019-12-23 07:12:52 -05:00
|
|
|
pub fn get_status(&self) -> ModuleStatus {
|
|
|
|
unsafe { v8__Module__GetStatus(self) }
|
2019-12-20 08:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// For a module in kErrored status, this returns the corresponding exception.
|
|
|
|
pub fn get_exception(&self) -> Local<Value> {
|
2020-05-31 12:45:00 -04:00
|
|
|
// Note: the returned value is not actually stored in a HandleScope,
|
|
|
|
// therefore we don't need a scope object here.
|
|
|
|
unsafe { Local::from_raw(v8__Module__GetException(self)) }.unwrap()
|
2019-12-20 08:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the number of modules requested by this module.
|
2019-12-30 15:11:50 -05:00
|
|
|
pub fn get_module_requests_length(&self) -> usize {
|
2020-05-31 12:35:41 -04:00
|
|
|
unsafe { v8__Module__GetModuleRequestsLength(self) }
|
|
|
|
.try_into()
|
|
|
|
.unwrap()
|
2019-12-20 08:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the ith module specifier in this module.
|
|
|
|
/// i must be < self.get_module_requests_length() and >= 0.
|
2019-12-23 07:12:52 -05:00
|
|
|
pub fn get_module_request(&self, i: usize) -> Local<String> {
|
2020-05-31 12:45:00 -04:00
|
|
|
// Note: the returned value is not actually stored in a HandleScope,
|
|
|
|
// therefore we don't need a scope object here.
|
2019-12-30 15:11:50 -05:00
|
|
|
unsafe {
|
2020-05-31 12:35:41 -04:00
|
|
|
Local::from_raw(v8__Module__GetModuleRequest(self, i.try_into().unwrap()))
|
2019-12-30 15:11:50 -05:00
|
|
|
}
|
2020-05-31 12:35:41 -04:00
|
|
|
.unwrap()
|
2019-12-23 07:12:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the source location (line number and column number) of the ith
|
|
|
|
/// module specifier's first occurrence in this module.
|
|
|
|
pub fn get_module_request_location(&self, i: usize) -> Location {
|
|
|
|
let mut out = MaybeUninit::<Location>::uninit();
|
|
|
|
unsafe {
|
2020-05-31 12:35:41 -04:00
|
|
|
v8__Module__GetModuleRequestLocation(
|
|
|
|
self,
|
|
|
|
i.try_into().unwrap(),
|
|
|
|
&mut out,
|
|
|
|
);
|
2019-12-23 07:12:52 -05:00
|
|
|
out.assume_init()
|
|
|
|
}
|
2019-12-20 08:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the identity hash for this object.
|
|
|
|
pub fn get_identity_hash(&self) -> int {
|
2019-12-23 07:12:52 -05:00
|
|
|
unsafe { v8__Module__GetIdentityHash(self) }
|
2019-12-20 08:56:32 -05:00
|
|
|
}
|
|
|
|
|
2020-01-17 08:01:19 -05:00
|
|
|
/// Returns the namespace object of this module.
|
|
|
|
///
|
|
|
|
/// The module's status must be at least kInstantiated.
|
2020-05-31 12:35:41 -04:00
|
|
|
pub fn get_module_namespace(&self) -> Local<Value> {
|
2020-05-31 12:45:00 -04:00
|
|
|
// Note: the returned value is not actually stored in a HandleScope,
|
|
|
|
// therefore we don't need a scope object here.
|
2020-01-03 18:12:45 -05:00
|
|
|
unsafe { Local::from_raw(v8__Module__GetModuleNamespace(self)).unwrap() }
|
|
|
|
}
|
|
|
|
|
2019-12-20 08:56:32 -05:00
|
|
|
/// Instantiates the module and its dependencies.
|
|
|
|
///
|
|
|
|
/// Returns an empty Maybe<bool> if an exception occurred during
|
|
|
|
/// instantiation. (In the case where the callback throws an exception, that
|
|
|
|
/// exception is propagated.)
|
|
|
|
#[must_use]
|
2020-01-14 15:06:41 -05:00
|
|
|
pub fn instantiate_module<'a>(
|
2019-12-20 20:54:14 -05:00
|
|
|
&mut self,
|
2020-06-25 20:56:24 -04:00
|
|
|
scope: &mut HandleScope,
|
2020-01-14 15:06:41 -05:00
|
|
|
callback: impl MapFnTo<ResolveCallback<'a>>,
|
2019-12-20 08:56:32 -05:00
|
|
|
) -> Option<bool> {
|
2020-01-14 15:06:41 -05:00
|
|
|
unsafe {
|
2020-06-25 20:56:24 -04:00
|
|
|
v8__Module__InstantiateModule(
|
|
|
|
self,
|
|
|
|
&*scope.get_current_context(),
|
|
|
|
callback.map_fn_to(),
|
|
|
|
)
|
2020-01-14 15:06:41 -05:00
|
|
|
}
|
|
|
|
.into()
|
2019-12-20 08:56:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Evaluates the module and its dependencies.
|
|
|
|
///
|
|
|
|
/// If status is kInstantiated, run the module's code. On success, set status
|
|
|
|
/// to kEvaluated and return the completion value; on failure, set status to
|
|
|
|
/// kErrored and propagate the thrown exception (which is then also available
|
|
|
|
/// via |GetException|).
|
|
|
|
#[must_use]
|
2020-06-03 01:38:34 -04:00
|
|
|
pub fn evaluate<'s>(
|
2020-04-13 08:43:56 -04:00
|
|
|
&self,
|
2020-06-03 01:38:34 -04:00
|
|
|
scope: &mut HandleScope<'s>,
|
|
|
|
) -> Option<Local<'s, Value>> {
|
2020-06-25 20:56:24 -04:00
|
|
|
unsafe {
|
|
|
|
scope
|
|
|
|
.cast_local(|sd| v8__Module__Evaluate(&*self, sd.get_current_context()))
|
|
|
|
}
|
2019-12-20 08:56:32 -05:00
|
|
|
}
|
|
|
|
}
|