diff --git a/src/binding.cc b/src/binding.cc index 959cf20a..c81148d3 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -1776,6 +1776,11 @@ const v8::ObjectTemplate* v8__FunctionTemplate__PrototypeTemplate( return local_to_ptr(ptr_to_local(&self)->PrototypeTemplate()); } +const v8::ObjectTemplate* v8__FunctionTemplate__InstanceTemplate( + const v8::FunctionTemplate& self) { + return local_to_ptr(ptr_to_local(&self)->InstanceTemplate()); +} + v8::Isolate* v8__FunctionCallbackInfo__GetIsolate( const v8::FunctionCallbackInfo& self) { return self.GetIsolate(); diff --git a/src/template.rs b/src/template.rs index 49a2307f..dcaffa04 100644 --- a/src/template.rs +++ b/src/template.rs @@ -54,6 +54,9 @@ extern "C" { fn v8__FunctionTemplate__PrototypeTemplate( this: *const FunctionTemplate, ) -> *const ObjectTemplate; + fn v8__FunctionTemplate__InstanceTemplate( + this: *const FunctionTemplate, + ) -> *const ObjectTemplate; fn v8__FunctionTemplate__SetClassName( this: *const FunctionTemplate, name: *const String, @@ -226,6 +229,18 @@ impl FunctionTemplate { .unwrap() } + /// Returns the object template that is used for instances created when this function + /// template is called as a constructor. + pub fn instance_template<'s>( + &self, + scope: &mut HandleScope<'s, ()>, + ) -> Local<'s, ObjectTemplate> { + unsafe { + scope.cast_local(|_sd| v8__FunctionTemplate__InstanceTemplate(self)) + } + .unwrap() + } + /// Causes the function template to inherit from a parent function template. /// This means the function's prototype.__proto__ is set to the parent function's prototype. pub fn inherit(&self, parent: Local) { diff --git a/tests/test_api.rs b/tests/test_api.rs index db8fc9b1..75b42eb6 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -1566,6 +1566,42 @@ fn function_template_prototype() { } } +#[test] +fn instance_template_with_internal_field() { + let _setup_guard = setup(); + let isolate = &mut v8::Isolate::new(Default::default()); + let scope = &mut v8::HandleScope::new(isolate); + let context = v8::Context::new(scope); + let scope = &mut v8::ContextScope::new(scope, context); + + pub fn constructor_callback( + scope: &mut v8::HandleScope, + args: v8::FunctionCallbackArguments, + mut retval: v8::ReturnValue, + ) { + let this = args.this(); + assert!(this.set_internal_field(0, v8::Integer::new(scope, 42).into())); + retval.set(this.into()) + } + + let function_templ = v8::FunctionTemplate::new(scope, constructor_callback); + let instance_templ = function_templ.instance_template(scope); + instance_templ.set_internal_field_count(1); + + let name = v8::String::new(scope, "WithInternalField").unwrap(); + let val = function_templ.get_function(scope).unwrap(); + context.global(scope).set(scope, name.into(), val.into()); + + let new_instance = eval(scope, "new WithInternalField()").unwrap(); + let internal_field = new_instance + .to_object(scope) + .unwrap() + .get_internal_field(scope, 0) + .unwrap(); + + assert_eq!(internal_field.integer_value(scope).unwrap(), 42); +} + #[test] fn object_template_set_accessor() { let _setup_guard = setup();