add v8::Object (#55)

This commit is contained in:
Bartek Iwańczuk 2019-12-10 01:14:07 +01:00 committed by Ry Dahl
parent 41e1f14ab5
commit b698e2fce3
6 changed files with 136 additions and 3 deletions

View File

@ -15,6 +15,7 @@ v8_static_library("rusty_v8") {
"src/json.cc",
"src/locker.cc",
"src/number.cc",
"src/object.cc",
"src/platform/mod.cc",
"src/platform/task.cc",
"src/primitives.cc",

View File

@ -19,6 +19,7 @@ mod json;
mod local;
mod locker;
mod number;
mod object;
mod primitives;
mod script;
mod string;
@ -41,6 +42,7 @@ pub use json::JSON;
pub use local::Local;
pub use locker::Locker;
pub use number::{Integer, Number};
pub use object::Object;
pub use primitives::*;
pub use script::{Script, ScriptOrigin};
pub use string::NewStringType;

14
src/object.cc Normal file
View File

@ -0,0 +1,14 @@
#include "support.h"
#include "v8/include/v8.h"
using namespace support;
extern "C" {
v8::Object *v8__Object__New(v8::Isolate *isolate,
v8::Local<v8::Value> prototype_or_null,
v8::Local<v8::Name>* names,
v8::Local<v8::Value>* values,
size_t length) {
return local_to_ptr(v8::Object::New(isolate, prototype_or_null, names, values, length));
}
}

69
src/object.rs Normal file
View File

@ -0,0 +1,69 @@
use std::ops::Deref;
use crate::isolate::CxxIsolate;
use crate::isolate::LockedIsolate;
use crate::support::Opaque;
use crate::HandleScope;
use crate::Local;
use crate::Name;
use crate::Value;
/// A JavaScript object (ECMA-262, 4.3.3)
#[repr(C)]
pub struct Object(Opaque);
extern "C" {
fn v8__Object__New(
isolate: *mut CxxIsolate,
prototype_or_null: *mut Value,
names: *mut *mut Name,
values: *mut *mut Value,
length: usize,
) -> *mut Object;
}
impl Object {
/// Creates a JavaScript object with the given properties, and
/// a the given prototype_or_null (which can be any JavaScript
/// value, and if it's null, the newly created object won't have
/// a prototype at all). This is similar to Object.create().
/// All properties will be created as enumerable, configurable
/// and writable properties.
pub fn new<'sc>(
scope: &mut HandleScope<'sc>,
mut prototype_or_null: Local<'sc, Value>,
names: Vec<Local<'sc, Name>>,
values: Vec<Local<'sc, Value>>,
length: usize,
) -> Local<'sc, Object> {
let mut names_: Vec<*mut Name> = vec![];
for mut name in names {
let n = &mut *name;
names_.push(n);
}
let mut values_: Vec<*mut Value> = vec![];
for mut value in values {
let n = &mut *value;
values_.push(n);
}
unsafe {
Local::from_raw(v8__Object__New(
scope.cxx_isolate(),
&mut *prototype_or_null,
names_.as_mut_ptr(),
values_.as_mut_ptr(),
length,
))
.unwrap()
}
}
}
impl Deref for Object {
type Target = Value;
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const _ as *const Value) }
}
}

View File

@ -16,6 +16,10 @@ pub struct Primitive(Opaque);
#[repr(C)]
pub struct Boolean(Opaque);
/// A superclass for symbols and strings.
#[repr(C)]
pub struct Name(Opaque);
extern "C" {
fn v8__Null(isolate: *mut CxxIsolate) -> *mut Primitive;
@ -57,3 +61,10 @@ impl Deref for Boolean {
unsafe { &*(self as *const _ as *const Primitive) }
}
}
impl Deref for Name {
type Target = Primitive;
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const _ as *const Primitive) }
}
}

View File

@ -3,6 +3,7 @@
extern crate lazy_static;
use rusty_v8 as v8;
use rusty_v8::{new_null, Local};
use std::default::Default;
use std::sync::Mutex;
@ -236,7 +237,10 @@ fn exception() {
let mut msg = v8::Exception::CreateMessage(scope, exception);
let msg_string = msg.get();
let rust_msg_string = msg_string.to_rust_string_lossy(scope);
assert_eq!("Uncaught Error: This is a test error".to_string(), rust_msg_string);
assert_eq!(
"Uncaught Error: This is a test error".to_string(),
rust_msg_string
);
assert!(v8::Exception::GetStackTrace(exception).is_none());
context.exit();
});
@ -256,8 +260,7 @@ fn json() {
let mut context = v8::Context::new(s);
context.enter();
let json_string =
v8::String::new(s, "{\"a\": 1, \"b\": 2}", Default::default())
.unwrap();
v8::String::new(s, "{\"a\": 1, \"b\": 2}", Default::default()).unwrap();
let maybe_value = v8::JSON::Parse(context, json_string);
assert!(maybe_value.is_some());
let value = maybe_value.unwrap();
@ -269,3 +272,36 @@ fn json() {
context.exit();
});
}
// TODO Safer casts https://github.com/denoland/rusty_v8/issues/51
fn cast<U, T>(local: v8::Local<T>) -> v8::Local<U> {
let cast_local: v8::Local<U> = unsafe { std::mem::transmute_copy(&local) };
cast_local
}
#[test]
fn object() {
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, |scope| {
let mut context = v8::Context::new(scope);
context.enter();
let null: v8::Local<v8::Value> = cast(new_null(scope));
let s1 = v8::String::new(scope, "a", v8::NewStringType::Normal).unwrap();
let s2 = v8::String::new(scope, "b", v8::NewStringType::Normal).unwrap();
let name1: Local<v8::Name> = cast(s1);
let name2: Local<v8::Name> = cast(s2);
let names = vec![name1, name2];
let v1: v8::Local<v8::Value> = cast(v8::Number::new(scope, 1.0));
let v2: v8::Local<v8::Value> = cast(v8::Number::new(scope, 2.0));
let values = vec![v1, v2];
let object = v8::Object::new(scope, null, names, values, 2);
assert!(!object.is_null_or_undefined());
context.exit();
});
}