0
0
Fork 0
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:
Ben Noordhuis 2020-01-19 00:38:41 +01:00 committed by Bert Belder
parent 2a7868daa9
commit 7b0269b447
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
5 changed files with 181 additions and 36 deletions

View file

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

View file

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

View file

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

View file

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