mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-01-12 17:09:28 -05:00
add v8::Object (#55)
This commit is contained in:
parent
41e1f14ab5
commit
b698e2fce3
6 changed files with 136 additions and 3 deletions
1
BUILD.gn
1
BUILD.gn
|
@ -15,6 +15,7 @@ v8_static_library("rusty_v8") {
|
||||||
"src/json.cc",
|
"src/json.cc",
|
||||||
"src/locker.cc",
|
"src/locker.cc",
|
||||||
"src/number.cc",
|
"src/number.cc",
|
||||||
|
"src/object.cc",
|
||||||
"src/platform/mod.cc",
|
"src/platform/mod.cc",
|
||||||
"src/platform/task.cc",
|
"src/platform/task.cc",
|
||||||
"src/primitives.cc",
|
"src/primitives.cc",
|
||||||
|
|
|
@ -19,6 +19,7 @@ mod json;
|
||||||
mod local;
|
mod local;
|
||||||
mod locker;
|
mod locker;
|
||||||
mod number;
|
mod number;
|
||||||
|
mod object;
|
||||||
mod primitives;
|
mod primitives;
|
||||||
mod script;
|
mod script;
|
||||||
mod string;
|
mod string;
|
||||||
|
@ -41,6 +42,7 @@ pub use json::JSON;
|
||||||
pub use local::Local;
|
pub use local::Local;
|
||||||
pub use locker::Locker;
|
pub use locker::Locker;
|
||||||
pub use number::{Integer, Number};
|
pub use number::{Integer, Number};
|
||||||
|
pub use object::Object;
|
||||||
pub use primitives::*;
|
pub use primitives::*;
|
||||||
pub use script::{Script, ScriptOrigin};
|
pub use script::{Script, ScriptOrigin};
|
||||||
pub use string::NewStringType;
|
pub use string::NewStringType;
|
||||||
|
|
14
src/object.cc
Normal file
14
src/object.cc
Normal 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
69
src/object.rs
Normal 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) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,10 @@ pub struct Primitive(Opaque);
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Boolean(Opaque);
|
pub struct Boolean(Opaque);
|
||||||
|
|
||||||
|
/// A superclass for symbols and strings.
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Name(Opaque);
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn v8__Null(isolate: *mut CxxIsolate) -> *mut Primitive;
|
fn v8__Null(isolate: *mut CxxIsolate) -> *mut Primitive;
|
||||||
|
|
||||||
|
@ -57,3 +61,10 @@ impl Deref for Boolean {
|
||||||
unsafe { &*(self as *const _ as *const Primitive) }
|
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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
use rusty_v8 as v8;
|
use rusty_v8 as v8;
|
||||||
|
use rusty_v8::{new_null, Local};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
@ -236,7 +237,10 @@ fn exception() {
|
||||||
let mut msg = v8::Exception::CreateMessage(scope, exception);
|
let mut msg = v8::Exception::CreateMessage(scope, exception);
|
||||||
let msg_string = msg.get();
|
let msg_string = msg.get();
|
||||||
let rust_msg_string = msg_string.to_rust_string_lossy(scope);
|
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());
|
assert!(v8::Exception::GetStackTrace(exception).is_none());
|
||||||
context.exit();
|
context.exit();
|
||||||
});
|
});
|
||||||
|
@ -256,8 +260,7 @@ fn json() {
|
||||||
let mut context = v8::Context::new(s);
|
let mut context = v8::Context::new(s);
|
||||||
context.enter();
|
context.enter();
|
||||||
let json_string =
|
let json_string =
|
||||||
v8::String::new(s, "{\"a\": 1, \"b\": 2}", Default::default())
|
v8::String::new(s, "{\"a\": 1, \"b\": 2}", Default::default()).unwrap();
|
||||||
.unwrap();
|
|
||||||
let maybe_value = v8::JSON::Parse(context, json_string);
|
let maybe_value = v8::JSON::Parse(context, json_string);
|
||||||
assert!(maybe_value.is_some());
|
assert!(maybe_value.is_some());
|
||||||
let value = maybe_value.unwrap();
|
let value = maybe_value.unwrap();
|
||||||
|
@ -269,3 +272,36 @@ fn json() {
|
||||||
context.exit();
|
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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue