mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-23 15:50:11 -05:00
Running a minimal script (#32)
This commit is contained in:
parent
174ef45a90
commit
f106ab5b10
13 changed files with 213 additions and 19 deletions
2
BUILD.gn
2
BUILD.gn
|
@ -5,6 +5,7 @@ v8_static_library("rusty_v8") {
|
|||
sources = [
|
||||
"src/V8.cc",
|
||||
"src/array_buffer.cc",
|
||||
"src/context.cc",
|
||||
"src/handle_scope.cc",
|
||||
"src/inspector/channel.cc",
|
||||
"src/inspector/client.cc",
|
||||
|
@ -14,6 +15,7 @@ v8_static_library("rusty_v8") {
|
|||
"src/number.cc",
|
||||
"src/platform/mod.cc",
|
||||
"src/platform/task.cc",
|
||||
"src/script.cc",
|
||||
"src/string.cc",
|
||||
]
|
||||
deps = [
|
||||
|
|
24
src/context.cc
Normal file
24
src/context.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include <cstdint>
|
||||
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
extern "C" {
|
||||
Context* v8__Context__New(Isolate* isolate) {
|
||||
// TODO: optional arguments.
|
||||
return *Context::New(isolate);
|
||||
}
|
||||
|
||||
void v8__Context__Enter(Context& self) {
|
||||
self.Enter();
|
||||
}
|
||||
|
||||
void v8__Context__Exit(Context& self) {
|
||||
self.Exit();
|
||||
}
|
||||
|
||||
Isolate* v8__Context__GetIsolate(Context& self) {
|
||||
return self.GetIsolate();
|
||||
}
|
||||
}
|
32
src/context.rs
Normal file
32
src/context.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use crate::isolate::CxxIsolate;
|
||||
use crate::isolate::LockedIsolate;
|
||||
use crate::support::Opaque;
|
||||
use crate::HandleScope;
|
||||
use crate::Local;
|
||||
|
||||
extern "C" {
|
||||
fn v8__Context__New(isolate: *mut CxxIsolate) -> *mut Context;
|
||||
fn v8__Context__Enter(this: &mut Context);
|
||||
fn v8__Context__Exit(this: &mut Context);
|
||||
fn v8__Context__GetIsolate(this: &mut Context) -> *mut CxxIsolate;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Context(Opaque);
|
||||
|
||||
impl Context {
|
||||
pub fn new<'sc>(scope: &mut HandleScope<'sc>) -> Local<'sc, Context> {
|
||||
// TODO: optional arguments;
|
||||
unsafe { Local::from_raw(v8__Context__New(scope.cxx_isolate())).unwrap() }
|
||||
}
|
||||
|
||||
pub fn enter(&mut self) {
|
||||
// TODO: enter/exit should be controlled by a scope.
|
||||
unsafe { v8__Context__Enter(self) };
|
||||
}
|
||||
|
||||
pub fn exit(&mut self) {
|
||||
// TODO: enter/exit should be controlled by a scope.
|
||||
unsafe { v8__Context__Exit(self) };
|
||||
}
|
||||
}
|
|
@ -25,10 +25,10 @@ impl<'sc> HandleScope<'sc> {
|
|||
{
|
||||
let mut scope: MaybeUninit<Self> = MaybeUninit::uninit();
|
||||
unsafe { v8__HandleScope__CONSTRUCT(&mut scope, parent.cxx_isolate()) };
|
||||
let mut scope = unsafe { &mut *(&mut scope as *mut _ as *mut HandleScope) };
|
||||
f(&mut scope);
|
||||
let scope = unsafe { &mut *(scope.as_mut_ptr()) };
|
||||
f(scope);
|
||||
|
||||
unsafe { v8__HandleScope__DESTRUCT(&mut scope) };
|
||||
unsafe { v8__HandleScope__DESTRUCT(scope) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,11 +11,13 @@ extern crate bitflags;
|
|||
extern crate lazy_static;
|
||||
extern crate libc;
|
||||
|
||||
mod context;
|
||||
mod handle_scope;
|
||||
mod isolate;
|
||||
mod local;
|
||||
mod locker;
|
||||
mod number;
|
||||
mod script;
|
||||
mod string;
|
||||
mod support;
|
||||
|
||||
|
@ -27,10 +29,15 @@ pub mod platform;
|
|||
#[allow(non_snake_case)]
|
||||
pub mod V8;
|
||||
|
||||
pub use context::Context;
|
||||
pub use handle_scope::HandleScope;
|
||||
pub use isolate::Isolate;
|
||||
pub use local::Local;
|
||||
pub use locker::Locker;
|
||||
pub use number::{Integer, Number};
|
||||
pub use script::{Script, ScriptOrigin};
|
||||
pub use string::NewStringType;
|
||||
pub use string::String;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Value(support::Opaque);
|
||||
|
|
29
src/local.rs
29
src/local.rs
|
@ -1,20 +1,33 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
pub struct Local<'sc, T>(&'sc T);
|
||||
pub struct Local<'sc, T>(NonNull<T>, PhantomData<&'sc ()>);
|
||||
|
||||
impl<'sc, T> Copy for Local<'sc, T> {}
|
||||
|
||||
impl<'sc, T> Clone for Local<'sc, T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc, T> Local<'sc, T> {
|
||||
pub unsafe fn from_raw(ptr: *const T) -> Option<Self> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Self(&*ptr))
|
||||
}
|
||||
pub(crate) unsafe fn from_raw(ptr: *mut T) -> Option<Self> {
|
||||
Some(Self(NonNull::new(ptr)?, PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc, T> Deref for Local<'sc, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
unsafe { self.0.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sc, T> DerefMut for Local<'sc, T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { self.0.as_mut() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ use crate::HandleScope;
|
|||
use crate::Local;
|
||||
|
||||
extern "C" {
|
||||
fn v8__Number__New(isolate: &mut CxxIsolate, value: f64) -> *const Number;
|
||||
fn v8__Number__New(isolate: &mut CxxIsolate, value: f64) -> *mut Number;
|
||||
fn v8__Number__Value(this: &Number) -> f64;
|
||||
fn v8__Integer__New(isolate: &mut CxxIsolate, value: i32) -> *const Integer;
|
||||
fn v8__Integer__New(isolate: &mut CxxIsolate, value: i32) -> *mut Integer;
|
||||
fn v8__Integer__NewFromUnsigned(
|
||||
isolate: &mut CxxIsolate,
|
||||
value: u32,
|
||||
) -> *const Integer;
|
||||
) -> *mut Integer;
|
||||
fn v8__Integer__Value(this: &Integer) -> i64;
|
||||
}
|
||||
|
||||
|
|
20
src/script.cc
Normal file
20
src/script.cc
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include <cstdint>
|
||||
|
||||
#include "support.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
using namespace v8;
|
||||
using namespace support;
|
||||
|
||||
extern "C" {
|
||||
Script* v8__Script__Compile(Context* context,
|
||||
String* source,
|
||||
ScriptOrigin* origin) {
|
||||
return maybe_local_to_ptr(
|
||||
Script::Compile(ptr_to_local(context), ptr_to_local(source), origin));
|
||||
}
|
||||
|
||||
Value* v8__Script__Run(Script& script, Context* context) {
|
||||
return maybe_local_to_ptr(script.Run(ptr_to_local(context)));
|
||||
}
|
||||
}
|
49
src/script.rs
Normal file
49
src/script.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use std::ptr::null;
|
||||
|
||||
use crate::support::Opaque;
|
||||
use crate::Context;
|
||||
use crate::HandleScope;
|
||||
use crate::Local;
|
||||
use crate::String;
|
||||
use crate::Value;
|
||||
|
||||
extern "C" {
|
||||
fn v8__Script__Compile(
|
||||
context: *mut Context,
|
||||
source: *mut String,
|
||||
origin: *const ScriptOrigin,
|
||||
) -> *mut Script;
|
||||
fn v8__Script__Run(this: &mut Script, context: *mut Context) -> *mut Value;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Script(Opaque);
|
||||
#[repr(C)]
|
||||
pub struct ScriptOrigin(Opaque);
|
||||
|
||||
impl Script {
|
||||
pub fn compile<'sc>(
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
mut context: Local<'_, Context>,
|
||||
mut source: Local<'_, String>,
|
||||
origin: Option<&'_ ScriptOrigin>,
|
||||
) -> Option<Local<'sc, Script>> {
|
||||
// TODO: use the type system to enforce that a Context has been entered.
|
||||
// TODO: `context` and `source` probably shouldn't be mut.
|
||||
unsafe {
|
||||
Local::from_raw(v8__Script__Compile(
|
||||
&mut *context,
|
||||
&mut *source,
|
||||
origin.map(|r| r as *const _).unwrap_or(null()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run<'sc>(
|
||||
&mut self,
|
||||
_scope: &mut HandleScope<'sc>,
|
||||
mut context: Local<'_, Context>,
|
||||
) -> Option<Local<Value>> {
|
||||
unsafe { Local::from_raw(v8__Script__Run(self, &mut *context)) }
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ String* v8__String__NewFromUtf8(Isolate* isolate,
|
|||
const char* data,
|
||||
NewStringType type,
|
||||
int length) {
|
||||
return maybe_local_ptr(String::NewFromUtf8(isolate, data, type, length));
|
||||
return maybe_local_to_ptr(String::NewFromUtf8(isolate, data, type, length));
|
||||
}
|
||||
|
||||
int v8__String__Utf8Length(const String& self, Isolate* isolate) {
|
||||
|
|
|
@ -17,7 +17,7 @@ extern "C" {
|
|||
data: *const char,
|
||||
new_type: NewStringType,
|
||||
length: int,
|
||||
) -> *const String;
|
||||
) -> *mut String;
|
||||
|
||||
fn v8__String__Utf8Length(this: &String, isolate: *mut CxxIsolate) -> int;
|
||||
|
||||
|
|
|
@ -35,9 +35,29 @@ void construct_in_place(uninit_t<T>& buf, Args... args) {
|
|||
}
|
||||
} // namespace support
|
||||
|
||||
|
||||
template <class T>
|
||||
inline static T* maybe_local_ptr(v8::MaybeLocal<T> value) {
|
||||
return *value.FromMaybe(v8::Local<T>());
|
||||
inline static T* local_to_ptr(v8::Local<T> local) {
|
||||
return *local;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline static v8::Local<T> ptr_to_local(T* ptr) {
|
||||
static_assert(sizeof(v8::Local<T>) == sizeof(T*), "");
|
||||
auto local = *reinterpret_cast<v8::Local<T>*>(&ptr);
|
||||
assert(*local == ptr);
|
||||
return local;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline static T* maybe_local_to_ptr(v8::MaybeLocal<T> local) {
|
||||
return *local.FromMaybe(v8::Local<T>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline static v8::MaybeLocal<T> ptr_to_maybe_local(T* ptr) {
|
||||
static_assert(sizeof(v8::MaybeLocal<T>) == sizeof(T*), "");
|
||||
return *reinterpret_cast<v8::MaybeLocal<T>*>(&ptr);
|
||||
}
|
||||
|
||||
#endif // SUPPORT_H_
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
extern crate lazy_static;
|
||||
|
||||
use rusty_v8 as v8;
|
||||
use std::default::Default;
|
||||
use std::sync::Mutex;
|
||||
|
||||
lazy_static! {
|
||||
|
@ -25,7 +26,7 @@ impl Drop for TestGuard {
|
|||
}
|
||||
}
|
||||
|
||||
fn setup() -> TestGuard {
|
||||
pub(crate) fn setup() -> TestGuard {
|
||||
let mut g = INIT_LOCK.lock().unwrap();
|
||||
*g += 1;
|
||||
if *g == 1 {
|
||||
|
@ -104,6 +105,32 @@ fn isolate_new() {
|
|||
drop(g);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn script_compile_and_run() {
|
||||
setup();
|
||||
let mut params = v8::Isolate::create_params();
|
||||
params.set_array_buffer_allocator(
|
||||
v8::array_buffer::Allocator::new_default_allocator(),
|
||||
);
|
||||
let mut isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&mut isolate);
|
||||
|
||||
v8::HandleScope::enter(&mut locker, |s| {
|
||||
let mut context = v8::Context::new(s);
|
||||
context.enter();
|
||||
let source =
|
||||
v8::String::new(s, "'Hello ' + 13 + 'th planet'", Default::default())
|
||||
.unwrap();
|
||||
let mut script = v8::Script::compile(s, context, source, None).unwrap();
|
||||
source.to_rust_string_lossy(s);
|
||||
let result = script.run(s, context).unwrap();
|
||||
// TODO: safer casts.
|
||||
let result: v8::Local<v8::String> =
|
||||
unsafe { std::mem::transmute_copy(&result) };
|
||||
assert_eq!(result.to_rust_string_lossy(s), "Hello 13th planet");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_version() {
|
||||
assert!(v8::V8::get_version().len() > 3);
|
||||
|
|
Loading…
Reference in a new issue