0
0
Fork 0
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:
Bert Belder 2019-12-04 14:12:27 +01:00
parent 174ef45a90
commit f106ab5b10
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
13 changed files with 213 additions and 19 deletions

View file

@ -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
View 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
View 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) };
}
}

View file

@ -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) };
}
}

View file

@ -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);

View file

@ -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() }
}
}

View file

@ -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
View 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
View 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)) }
}
}

View file

@ -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) {

View file

@ -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;

View file

@ -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_

View file

@ -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);