From 2bbc9053b570cefed483b74b4f932eb6b8345d6f Mon Sep 17 00:00:00 2001 From: Kedas Date: Mon, 10 Jun 2024 10:40:14 -0700 Subject: [PATCH] Add `v8::Template::set_intrinsic_data_property` (#1496) * feat: add `v8::Template::set_intrinsic_data_property` * fix: use assert_eq instead of assert * fix: cargo fmt --- src/binding.cc | 8 ++++++++ src/template.rs | 37 ++++++++++++++++++++++++++++++++++++ tests/test_api.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/src/binding.cc b/src/binding.cc index 9461dc11..88ff98ac 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -1200,6 +1200,14 @@ void v8__Template__Set(const v8::Template& self, const v8::Name& key, ptr_to_local(&self)->Set(ptr_to_local(&key), ptr_to_local(&value), attr); } +void v8__Template__SetIntrinsicDataProperty( + const v8::Template& self, const v8::Name& key, + v8::Intrinsic intrinsic, + v8::PropertyAttribute attr) { + ptr_to_local(&self)->SetIntrinsicDataProperty(ptr_to_local(&key), + intrinsic, attr); +} + const v8::ObjectTemplate* v8__ObjectTemplate__New( v8::Isolate* isolate, const v8::FunctionTemplate& templ) { return local_to_ptr(v8::ObjectTemplate::New(isolate, ptr_to_local(&templ))); diff --git a/src/template.rs b/src/template.rs index c28a5873..27fd8a15 100644 --- a/src/template.rs +++ b/src/template.rs @@ -43,6 +43,13 @@ extern "C" { value: *const Data, attr: PropertyAttribute, ); + fn v8__Template__SetIntrinsicDataProperty( + this: *const Template, + key: *const Name, + intrinsic: Intrinsic, + attr: PropertyAttribute, + ); + fn v8__Signature__New( isolate: *mut Isolate, templ: *const FunctionTemplate, @@ -614,6 +621,22 @@ impl<'s> IndexedPropertyHandlerConfiguration<'s> { } } +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub enum Intrinsic { + ArrayProtoEntries, + ArrayProtoForEach, + ArrayProtoKeys, + ArrayProtoValues, + ArrayPrototype, + AsyncIteratorPrototype, + ErrorPrototype, + IteratorPrototype, + MapIteratorPrototype, + ObjProtoValueOf, + SetIteratorPrototype, +} + impl Template { /// Adds a property to each instance created by this template. #[inline(always)] @@ -632,6 +655,20 @@ impl Template { ) { unsafe { v8__Template__Set(self, &*key, &*value, attr) } } + + /// During template instantiation, sets the value with the + /// intrinsic property from the correct context. + #[inline(always)] + pub fn set_intrinsic_data_property( + &self, + key: Local, + intrinsic: Intrinsic, + attr: PropertyAttribute, + ) { + unsafe { + v8__Template__SetIntrinsicDataProperty(self, &*key, intrinsic, attr) + } + } } impl<'s> FunctionBuilder<'s, FunctionTemplate> { diff --git a/tests/test_api.rs b/tests/test_api.rs index e26b238e..31992598 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -1862,6 +1862,54 @@ fn function_template_prototype() { } } +#[test] +fn function_template_intrinsic_data_property() { + let _setup_guard = setup::parallel_test(); + let isolate = &mut v8::Isolate::new(Default::default()); + { + let scope = &mut v8::HandleScope::new(isolate); + + let function_templ = v8::FunctionTemplate::new(scope, fortytwo_callback); + + let prop_name = v8::String::new(scope, "prototype").unwrap(); + + let intrinsic_error_prototype_interface_template = + v8::FunctionTemplate::builder(fortytwo_callback) + .constructor_behavior(v8::ConstructorBehavior::Throw) + .build(scope); + + intrinsic_error_prototype_interface_template.set_intrinsic_data_property( + prop_name.into(), + v8::Intrinsic::ErrorPrototype, + v8::PropertyAttribute::NONE, + ); + function_templ.inherit(intrinsic_error_prototype_interface_template); + + let context = v8::Context::new(scope); + let scope = &mut v8::ContextScope::new(scope, context); + + let function = function_templ.get_function(scope).unwrap(); + let object1 = function.new_instance(scope, &[]).unwrap(); + + let error_prototype = { + let message = v8::String::empty(scope); + v8::Exception::error(scope, message) + .to_object(scope) + .unwrap() + .get_prototype(scope) + .unwrap() + }; + + let object1_prototype = object1.get_prototype(scope).unwrap(); + let object1_prototype_parent = object1_prototype + .to_object(scope) + .and_then(|o| o.get_prototype(scope)) + .unwrap(); + + assert_eq!(object1_prototype_parent, error_prototype); + } +} + #[test] fn instance_template_with_internal_field() { let _setup_guard = setup::parallel_test();