mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-27 01:29:19 -05:00
first pass implementation for v8::Module (#120)
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
parent
ac8aec9c8f
commit
3ec3b07638
4 changed files with 155 additions and 13 deletions
|
@ -33,6 +33,9 @@ static_assert(sizeof(v8::ReturnValue<v8::Value>) == sizeof(size_t) * 1,
|
|||
static_assert(sizeof(v8::TryCatch) == sizeof(size_t) * 6,
|
||||
"TryCatch size mismatch");
|
||||
|
||||
static_assert(sizeof(v8::Location) == sizeof(size_t) * 1,
|
||||
"Location size mismatch");
|
||||
|
||||
extern "C" {
|
||||
|
||||
void v8__V8__SetFlagsFromCommandLine(int* argc, char** argv) {
|
||||
|
@ -729,9 +732,48 @@ v8_inspector::StringBuffer* v8_inspector__StringBuffer__create(
|
|||
return v8_inspector::StringBuffer::create(source).release();
|
||||
}
|
||||
|
||||
int v8__Location__GetLineNumber(v8::Location& self) {
|
||||
return self.GetLineNumber();
|
||||
}
|
||||
|
||||
int v8__Location__GetColumnNumber(v8::Location& self) {
|
||||
return self.GetColumnNumber();
|
||||
}
|
||||
|
||||
v8::Module::Status v8__Module__GetStatus(const v8::Module& self) {
|
||||
return self.GetStatus();
|
||||
}
|
||||
|
||||
v8::Value* v8__Module__GetException(const v8::Module& self) {
|
||||
return local_to_ptr(self.GetException());
|
||||
}
|
||||
|
||||
int v8__Module__GetModuleRequestsLength(const v8::Module& self) {
|
||||
return self.GetModuleRequestsLength();
|
||||
}
|
||||
|
||||
v8::String* v8__Module__GetModuleRequest(const v8::Module& self, int i) {
|
||||
return local_to_ptr(self.GetModuleRequest(i));
|
||||
}
|
||||
|
||||
void v8__Module__GetModuleRequestLocation(const v8::Module& self, int i,
|
||||
v8::Location* out) {
|
||||
*out = self.GetModuleRequestLocation(i);
|
||||
}
|
||||
|
||||
int v8__Module__GetIdentityHash(const v8::Module& self) {
|
||||
return self.GetIdentityHash();
|
||||
}
|
||||
|
||||
MaybeBool v8__Module__InstantiateModule(v8::Module& self,
|
||||
v8::Local<v8::Context> context,
|
||||
v8::Module::ResolveCallback callback) {
|
||||
return maybe_to_maybe_bool(self.InstantiateModule(context, callback));
|
||||
}
|
||||
|
||||
v8::Value* v8__Module__Evaluate(v8::Module& self,
|
||||
v8::Local<v8::Context> context) {
|
||||
return maybe_local_to_ptr(self.Evaluate(context));
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
@ -56,6 +56,7 @@ pub use isolate::OwnedIsolate;
|
|||
pub use local::Local;
|
||||
pub use locker::Locker;
|
||||
pub use module::Module;
|
||||
pub use module::ModuleStatus;
|
||||
pub use number::{Integer, Number};
|
||||
pub use object::Object;
|
||||
pub use primitive_array::PrimitiveArray;
|
||||
|
|
|
@ -5,17 +5,48 @@ use crate::Context;
|
|||
use crate::Local;
|
||||
use crate::String;
|
||||
use crate::Value;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
// Ideally the return value would be Option<Local<Module>>... but not FFI-safe
|
||||
type ResolveCallback =
|
||||
extern "C" fn(Local<Context>, Local<String>, Local<Module>) -> *mut Module;
|
||||
|
||||
extern "C" {
|
||||
fn v8__Module__GetStatus(this: *const Module) -> ModuleStatus;
|
||||
fn v8__Module__GetException(this: *const Module) -> *mut Value;
|
||||
fn v8__Module__GetModuleRequestsLength(this: *const Module) -> int;
|
||||
fn v8__Module__GetModuleRequest(this: *const Module, i: usize)
|
||||
-> *mut String;
|
||||
fn v8__Module__GetModuleRequestLocation(
|
||||
this: *const Module,
|
||||
i: usize,
|
||||
out: &mut MaybeUninit<Location>,
|
||||
) -> Location;
|
||||
fn v8__Module__GetIdentityHash(this: *const Module) -> int;
|
||||
fn v8__Module__InstantiateModule(
|
||||
this: *mut Module,
|
||||
context: Local<Context>,
|
||||
callback: ResolveCallback,
|
||||
) -> MaybeBool;
|
||||
fn v8__Module__Evaluate(
|
||||
this: *mut Module,
|
||||
context: *mut Context,
|
||||
) -> *mut Value;
|
||||
fn v8__Location__GetLineNumber(this: &Location) -> int;
|
||||
fn v8__Location__GetColumnNumber(this: &Location) -> int;
|
||||
}
|
||||
|
||||
#[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) }
|
||||
}
|
||||
}
|
||||
|
||||
/// The different states a module can be in.
|
||||
|
@ -25,7 +56,7 @@ extern "C" {
|
|||
/// respectively.
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub enum Status {
|
||||
pub enum ModuleStatus {
|
||||
Uninstantiated,
|
||||
Instantiating,
|
||||
Instantiated,
|
||||
|
@ -40,29 +71,39 @@ pub struct Module(Opaque);
|
|||
/// A compiled JavaScript module.
|
||||
impl Module {
|
||||
/// Returns the module's current status.
|
||||
pub fn get_status(&self) -> Status {
|
||||
unimplemented!();
|
||||
pub fn get_status(&self) -> ModuleStatus {
|
||||
unsafe { v8__Module__GetStatus(self) }
|
||||
}
|
||||
|
||||
/// For a module in kErrored status, this returns the corresponding exception.
|
||||
pub fn get_exception(&self) -> Local<Value> {
|
||||
unimplemented!();
|
||||
unsafe { Local::from_raw(v8__Module__GetException(self)).unwrap() }
|
||||
}
|
||||
|
||||
/// Returns the number of modules requested by this module.
|
||||
pub fn get_module_requests_length(&self) -> int {
|
||||
unimplemented!();
|
||||
unsafe { v8__Module__GetModuleRequestsLength(self) }
|
||||
}
|
||||
|
||||
/// Returns the ith module specifier in this module.
|
||||
/// i must be < self.get_module_requests_length() and >= 0.
|
||||
pub fn get_module_request(&self, _i: usize) -> Local<String> {
|
||||
unimplemented!();
|
||||
pub fn get_module_request(&self, i: usize) -> Local<String> {
|
||||
unsafe { Local::from_raw(v8__Module__GetModuleRequest(self, i)).unwrap() }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
v8__Module__GetModuleRequestLocation(self, i, &mut out);
|
||||
out.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the identity hash for this object.
|
||||
pub fn get_identity_hash(&self) -> int {
|
||||
unimplemented!();
|
||||
unsafe { v8__Module__GetIdentityHash(self) }
|
||||
}
|
||||
|
||||
/// Instantiates the module and its dependencies.
|
||||
|
@ -86,7 +127,10 @@ impl Module {
|
|||
/// kErrored and propagate the thrown exception (which is then also available
|
||||
/// via |GetException|).
|
||||
#[must_use]
|
||||
pub fn evaluate(&self, _context: Local<Context>) -> Option<Local<Value>> {
|
||||
unimplemented!();
|
||||
pub fn evaluate(
|
||||
&mut self,
|
||||
mut context: Local<Context>,
|
||||
) -> Option<Local<Value>> {
|
||||
unsafe { Local::from_raw(v8__Module__Evaluate(&mut *self, &mut *context)) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -715,8 +715,8 @@ fn mock_script_origin<'sc>(
|
|||
scope: &mut HandleScope<'sc>,
|
||||
) -> v8::ScriptOrigin<'sc> {
|
||||
let resource_name = v8_str(scope, "foo.js");
|
||||
let resource_line_offset = v8::Integer::new(scope, 4);
|
||||
let resource_column_offset = v8::Integer::new(scope, 5);
|
||||
let resource_line_offset = v8::Integer::new(scope, 0);
|
||||
let resource_column_offset = v8::Integer::new(scope, 0);
|
||||
let resource_is_shared_cross_origin = v8::new_true(scope);
|
||||
let script_id = v8::Integer::new(scope, 123);
|
||||
let source_map_url = v8_str(scope, "source_map_url");
|
||||
|
@ -769,6 +769,61 @@ fn script_compiler_source() {
|
|||
drop(g);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn module_instantiation_failures1() {
|
||||
let g = setup();
|
||||
let mut params = v8::Isolate::create_params();
|
||||
params.set_array_buffer_allocator(v8::Allocator::new_default_allocator());
|
||||
let mut isolate = v8::Isolate::new(params);
|
||||
isolate.enter();
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
let mut context = v8::Context::new(scope);
|
||||
context.enter();
|
||||
|
||||
let source_text = v8_str(
|
||||
scope,
|
||||
"import './foo.js';\n\
|
||||
export {} from './bar.js';",
|
||||
);
|
||||
let origin = mock_script_origin(scope);
|
||||
let source = v8::script_compiler::Source::new(source_text, &origin);
|
||||
|
||||
let module = v8::script_compiler::compile_module(
|
||||
&isolate,
|
||||
source,
|
||||
v8::script_compiler::CompileOptions::NoCompileOptions,
|
||||
v8::script_compiler::NoCacheReason::NoReason,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(v8::ModuleStatus::Uninstantiated, module.get_status());
|
||||
assert_eq!(2, module.get_module_requests_length());
|
||||
|
||||
assert_eq!(
|
||||
"./foo.js",
|
||||
module.get_module_request(0).to_rust_string_lossy(scope)
|
||||
);
|
||||
let loc = module.get_module_request_location(0);
|
||||
assert_eq!(0, loc.get_line_number());
|
||||
assert_eq!(7, loc.get_column_number());
|
||||
|
||||
assert_eq!(
|
||||
"./bar.js",
|
||||
module.get_module_request(1).to_rust_string_lossy(scope)
|
||||
);
|
||||
let loc = module.get_module_request_location(1);
|
||||
assert_eq!(1, loc.get_line_number());
|
||||
assert_eq!(15, loc.get_column_number());
|
||||
|
||||
// TODO(ry) Instantiation should fail.
|
||||
|
||||
context.exit();
|
||||
});
|
||||
drop(locker);
|
||||
isolate.exit();
|
||||
drop(g);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn primitive_array() {
|
||||
let g = setup();
|
||||
|
|
Loading…
Reference in a new issue