mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-01-12 00:54:15 -05:00
Add ObjectTemplate and Template::set() (#225)
The ObjectTemplate type already existed but now it can also be instantiated. This commit also adds Template::set() to actually make that useful.
This commit is contained in:
parent
2a7868daa9
commit
7b0269b447
5 changed files with 181 additions and 36 deletions
|
@ -625,6 +625,24 @@ int v8__String__WriteUtf8(const v8::String& self, v8::Isolate* isolate,
|
|||
return self.WriteUtf8(isolate, buffer, length, nchars_ref, options);
|
||||
}
|
||||
|
||||
void v8__Template__Set(v8::Template& self, v8::Local<v8::Name> key,
|
||||
v8::Local<v8::Data> value) {
|
||||
// TODO(bnoordhuis) Allow setting PropertyAttributes.
|
||||
self.Set(key, value);
|
||||
}
|
||||
|
||||
v8::ObjectTemplate* v8__ObjectTemplate__New(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> templ) {
|
||||
return local_to_ptr(v8::ObjectTemplate::New(isolate, templ));
|
||||
}
|
||||
|
||||
v8::Object* v8__ObjectTemplate__NewInstance(
|
||||
v8::ObjectTemplate& self,
|
||||
v8::Local<v8::Context> context) {
|
||||
return maybe_local_to_ptr(self.NewInstance(context));
|
||||
}
|
||||
|
||||
v8::Object* v8__Object__New(v8::Isolate* isolate) {
|
||||
return local_to_ptr(v8::Object::New(isolate));
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@ use crate::support::{int, Opaque};
|
|||
use crate::Context;
|
||||
use crate::Function;
|
||||
use crate::FunctionCallbackScope;
|
||||
use crate::FunctionTemplate;
|
||||
use crate::Isolate;
|
||||
use crate::Local;
|
||||
use crate::Name;
|
||||
use crate::Object;
|
||||
|
@ -32,15 +30,6 @@ extern "C" {
|
|||
argv: *const Local<Value>,
|
||||
) -> *mut Value;
|
||||
|
||||
fn v8__FunctionTemplate__New(
|
||||
isolate: &Isolate,
|
||||
callback: FunctionCallback,
|
||||
) -> *mut FunctionTemplate;
|
||||
fn v8__FunctionTemplate__GetFunction(
|
||||
fn_template: *mut FunctionTemplate,
|
||||
context: *mut Context,
|
||||
) -> *mut Function;
|
||||
|
||||
fn v8__FunctionCallbackInfo__GetReturnValue(
|
||||
info: *const FunctionCallbackInfo,
|
||||
) -> *mut Value;
|
||||
|
@ -282,31 +271,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl FunctionTemplate {
|
||||
/// Creates a function template.
|
||||
pub fn new<'sc>(
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
callback: impl MapFnTo<FunctionCallback>,
|
||||
) -> Local<'sc, FunctionTemplate> {
|
||||
let ptr = unsafe {
|
||||
v8__FunctionTemplate__New(scope.isolate(), callback.map_fn_to())
|
||||
};
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
/// Returns the unique function instance in the current execution context.
|
||||
pub fn get_function<'sc>(
|
||||
&mut self,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut context: Local<Context>,
|
||||
) -> Option<Local<'sc, Function>> {
|
||||
unsafe {
|
||||
scope
|
||||
.to_local(v8__FunctionTemplate__GetFunction(&mut *self, &mut *context))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Function {
|
||||
// TODO: add remaining arguments from C++
|
||||
/// Create a function in the current execution context
|
||||
|
|
|
@ -66,6 +66,7 @@ mod shared_array_buffer;
|
|||
mod snapshot;
|
||||
mod string;
|
||||
mod support;
|
||||
mod template;
|
||||
mod try_catch;
|
||||
mod uint8_array;
|
||||
mod value;
|
||||
|
@ -124,6 +125,7 @@ pub use support::MaybeBool;
|
|||
pub use support::SharedRef;
|
||||
pub use support::UniquePtr;
|
||||
pub use support::UniqueRef;
|
||||
pub use template::*;
|
||||
pub use try_catch::{TryCatch, TryCatchScope};
|
||||
|
||||
// TODO(piscisaureus): Ideally this trait would not be exported.
|
||||
|
|
96
src/template.rs
Normal file
96
src/template.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
use crate::data::Data;
|
||||
use crate::data::FunctionTemplate;
|
||||
use crate::data::Name;
|
||||
use crate::data::ObjectTemplate;
|
||||
use crate::data::Template;
|
||||
use crate::isolate::Isolate;
|
||||
use crate::support::MapFnTo;
|
||||
use crate::Context;
|
||||
use crate::Function;
|
||||
use crate::FunctionCallback;
|
||||
use crate::Local;
|
||||
use crate::Object;
|
||||
use crate::ToLocal;
|
||||
|
||||
extern "C" {
|
||||
fn v8__Template__Set(self_: &Template, key: *const Name, value: *const Data);
|
||||
|
||||
fn v8__FunctionTemplate__New(
|
||||
isolate: &Isolate,
|
||||
callback: FunctionCallback,
|
||||
) -> *mut FunctionTemplate;
|
||||
fn v8__FunctionTemplate__GetFunction(
|
||||
fn_template: *mut FunctionTemplate,
|
||||
context: *mut Context,
|
||||
) -> *mut Function;
|
||||
|
||||
fn v8__ObjectTemplate__New(
|
||||
isolate: *mut Isolate,
|
||||
templ: *const FunctionTemplate,
|
||||
) -> *mut ObjectTemplate;
|
||||
fn v8__ObjectTemplate__NewInstance(
|
||||
self_: &ObjectTemplate,
|
||||
context: *mut Context,
|
||||
) -> *mut Object;
|
||||
}
|
||||
|
||||
impl Template {
|
||||
/// Adds a property to each instance created by this template.
|
||||
pub fn set(&self, key: Local<Name>, value: Local<Data>) {
|
||||
// TODO(bnoordhuis) Allow setting PropertyAttributes.
|
||||
unsafe { v8__Template__Set(self, &*key, &*value) }
|
||||
}
|
||||
}
|
||||
|
||||
impl FunctionTemplate {
|
||||
/// Creates a function template.
|
||||
pub fn new<'sc>(
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
callback: impl MapFnTo<FunctionCallback>,
|
||||
) -> Local<'sc, FunctionTemplate> {
|
||||
let ptr = unsafe {
|
||||
v8__FunctionTemplate__New(scope.isolate(), callback.map_fn_to())
|
||||
};
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
/// Returns the unique function instance in the current execution context.
|
||||
pub fn get_function<'sc>(
|
||||
&mut self,
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
mut context: Local<Context>,
|
||||
) -> Option<Local<'sc, Function>> {
|
||||
unsafe {
|
||||
scope
|
||||
.to_local(v8__FunctionTemplate__GetFunction(&mut *self, &mut *context))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectTemplate {
|
||||
/// Creates an object template.
|
||||
pub fn new<'sc>(scope: &mut impl ToLocal<'sc>) -> Local<'sc, ObjectTemplate> {
|
||||
let ptr =
|
||||
unsafe { v8__ObjectTemplate__New(scope.isolate(), std::ptr::null()) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
/// Creates an object template from a function template.
|
||||
pub fn new_from_template<'sc>(
|
||||
scope: &mut impl ToLocal<'sc>,
|
||||
templ: Local<FunctionTemplate>,
|
||||
) -> Local<'sc, ObjectTemplate> {
|
||||
let ptr = unsafe { v8__ObjectTemplate__New(scope.isolate(), &*templ) };
|
||||
unsafe { scope.to_local(ptr) }.unwrap()
|
||||
}
|
||||
|
||||
/// Creates a new instance of this object template.
|
||||
pub fn new_instance<'a>(
|
||||
&self,
|
||||
scope: &mut impl ToLocal<'a>,
|
||||
mut context: Local<Context>,
|
||||
) -> Option<Local<'a, Object>> {
|
||||
let ptr = unsafe { v8__ObjectTemplate__NewInstance(self, &mut *context) };
|
||||
unsafe { scope.to_local(ptr) }
|
||||
}
|
||||
}
|
|
@ -856,6 +856,63 @@ fn json() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_template() {
|
||||
let _setup_guard = setup();
|
||||
let mut params = v8::Isolate::create_params();
|
||||
params.set_array_buffer_allocator(v8::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let object_templ = v8::ObjectTemplate::new(scope);
|
||||
let function_templ = v8::FunctionTemplate::new(scope, fortytwo_callback);
|
||||
let name = v8_str(scope, "f");
|
||||
object_templ.set(name.into(), function_templ.into());
|
||||
let context = v8::Context::new(scope);
|
||||
let mut cs = v8::ContextScope::new(scope, context);
|
||||
let scope = cs.enter();
|
||||
let object = object_templ.new_instance(scope, context).unwrap();
|
||||
assert!(!object.is_null_or_undefined());
|
||||
let name = v8_str(scope, "g");
|
||||
context
|
||||
.global(scope)
|
||||
.set(context, name.into(), object.into());
|
||||
let actual = eval(scope, context, "g.f()").unwrap();
|
||||
let expected = v8::Integer::new(scope, 42);
|
||||
assert!(expected.strict_equals(actual));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_template_from_function_template() {
|
||||
let _setup_guard = setup();
|
||||
let mut params = v8::Isolate::create_params();
|
||||
params.set_array_buffer_allocator(v8::new_default_allocator());
|
||||
let isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&isolate);
|
||||
{
|
||||
let mut hs = v8::HandleScope::new(&mut locker);
|
||||
let scope = hs.enter();
|
||||
let function_templ = v8::FunctionTemplate::new(scope, fortytwo_callback);
|
||||
let object_templ =
|
||||
v8::ObjectTemplate::new_from_template(scope, function_templ);
|
||||
let context = v8::Context::new(scope);
|
||||
let mut cs = v8::ContextScope::new(scope, context);
|
||||
let scope = cs.enter();
|
||||
let object = object_templ.new_instance(scope, context).unwrap();
|
||||
assert!(!object.is_null_or_undefined());
|
||||
let name = v8_str(scope, "g");
|
||||
context
|
||||
.global(scope)
|
||||
.set(context, name.into(), object.into());
|
||||
let actual = eval(scope, context, "g.constructor.name").unwrap();
|
||||
let expected = v8::String::new(scope, "").unwrap();
|
||||
assert!(expected.strict_equals(actual));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object() {
|
||||
let _setup_guard = setup();
|
||||
|
@ -1122,6 +1179,14 @@ fn fn_callback2(
|
|||
rv.set(s.into());
|
||||
}
|
||||
|
||||
fn fortytwo_callback(
|
||||
scope: v8::FunctionCallbackScope,
|
||||
_: v8::FunctionCallbackArguments,
|
||||
mut rv: v8::ReturnValue,
|
||||
) {
|
||||
rv.set(v8::Integer::new(scope, 42).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function() {
|
||||
let _setup_guard = setup();
|
||||
|
|
Loading…
Reference in a new issue