Skip to main content

v8/
template.rs

1use crate::ConstructorBehavior;
2use crate::Context;
3use crate::Function;
4use crate::FunctionBuilder;
5use crate::FunctionCallback;
6use crate::IndexedDefinerCallback;
7use crate::IndexedDeleterCallback;
8use crate::IndexedGetterCallback;
9use crate::IndexedQueryCallback;
10use crate::IndexedSetterCallback;
11use crate::Local;
12use crate::NamedDefinerCallback;
13use crate::NamedDeleterCallback;
14use crate::NamedGetterCallback;
15use crate::NamedGetterCallbackForAccessor;
16use crate::NamedQueryCallback;
17use crate::NamedSetterCallback;
18use crate::NamedSetterCallbackForAccessor;
19use crate::Object;
20use crate::PropertyAttribute;
21use crate::PropertyEnumeratorCallback;
22use crate::PropertyHandlerFlags;
23use crate::SideEffectType;
24use crate::Signature;
25use crate::String;
26use crate::Value;
27pub use crate::binding::v8__Intercepted as Intercepted;
28use crate::data::Data;
29use crate::data::FunctionTemplate;
30use crate::data::Name;
31use crate::data::ObjectTemplate;
32use crate::data::Template;
33use crate::fast_api::CFunction;
34use crate::isolate::RealIsolate;
35use crate::scope::PinScope;
36use crate::support::MapFnTo;
37use crate::support::int;
38use std::convert::TryFrom;
39use std::ptr::null;
40
41unsafe extern "C" {
42  fn v8__Template__Set(
43    this: *const Template,
44    key: *const Name,
45    value: *const Data,
46    attr: PropertyAttribute,
47  );
48  fn v8__Template__SetIntrinsicDataProperty(
49    this: *const Template,
50    key: *const Name,
51    intrinsic: Intrinsic,
52    attr: PropertyAttribute,
53  );
54
55  fn v8__Signature__New(
56    isolate: *mut RealIsolate,
57    templ: *const FunctionTemplate,
58  ) -> *const Signature;
59  fn v8__FunctionTemplate__New(
60    isolate: *mut RealIsolate,
61    callback: FunctionCallback,
62    data_or_null: *const Value,
63    signature_or_null: *const Signature,
64    length: i32,
65    constructor_behavior: ConstructorBehavior,
66    side_effect_type: SideEffectType,
67    c_functions: *const CFunction,
68    c_functions_len: usize,
69  ) -> *const FunctionTemplate;
70  fn v8__FunctionTemplate__GetFunction(
71    this: *const FunctionTemplate,
72    context: *const Context,
73  ) -> *const Function;
74  fn v8__FunctionTemplate__PrototypeTemplate(
75    this: *const FunctionTemplate,
76  ) -> *const ObjectTemplate;
77  fn v8__FunctionTemplate__InstanceTemplate(
78    this: *const FunctionTemplate,
79  ) -> *const ObjectTemplate;
80  fn v8__FunctionTemplate__SetClassName(
81    this: *const FunctionTemplate,
82    name: *const String,
83  );
84  fn v8__FunctionTemplate__SetAccessorProperty(
85    this: *const FunctionTemplate,
86    key: *const Name,
87    getter: *const FunctionTemplate,
88    setter: *const FunctionTemplate,
89    attr: PropertyAttribute,
90  );
91  fn v8__FunctionTemplate__Inherit(
92    this: *const FunctionTemplate,
93    parent: *const FunctionTemplate,
94  );
95  fn v8__FunctionTemplate__ReadOnlyPrototype(this: *const FunctionTemplate);
96  fn v8__FunctionTemplate__RemovePrototype(this: *const FunctionTemplate);
97
98  fn v8__ObjectTemplate__New(
99    isolate: *mut RealIsolate,
100    templ: *const FunctionTemplate,
101  ) -> *const ObjectTemplate;
102  fn v8__ObjectTemplate__NewInstance(
103    this: *const ObjectTemplate,
104    context: *const Context,
105  ) -> *const Object;
106  fn v8__ObjectTemplate__InternalFieldCount(this: *const ObjectTemplate)
107  -> int;
108  fn v8__ObjectTemplate__SetInternalFieldCount(
109    this: *const ObjectTemplate,
110    value: int,
111  );
112
113  fn v8__ObjectTemplate__SetNativeDataProperty(
114    this: *const ObjectTemplate,
115    key: *const Name,
116    getter: AccessorNameGetterCallback,
117    setter: Option<AccessorNameSetterCallback>,
118    data_or_null: *const Value,
119    attr: PropertyAttribute,
120  );
121  fn v8__ObjectTemplate__SetAccessorProperty(
122    this: *const ObjectTemplate,
123    key: *const Name,
124    getter: *const FunctionTemplate,
125    setter: *const FunctionTemplate,
126    attr: PropertyAttribute,
127  );
128
129  fn v8__ObjectTemplate__SetNamedPropertyHandler(
130    this: *const ObjectTemplate,
131    getter: Option<NamedPropertyGetterCallback>,
132    setter: Option<NamedPropertySetterCallback>,
133    query: Option<NamedPropertyQueryCallback>,
134    deleter: Option<NamedPropertyDeleterCallback>,
135    enumerator: Option<NamedPropertyEnumeratorCallback>,
136    definer: Option<NamedPropertyDefinerCallback>,
137    descriptor: Option<NamedPropertyDescriptorCallback>,
138    data_or_null: *const Value,
139    flags: PropertyHandlerFlags,
140  );
141
142  fn v8__ObjectTemplate__SetIndexedPropertyHandler(
143    this: *const ObjectTemplate,
144    getter: Option<IndexedPropertyGetterCallback>,
145    setter: Option<IndexedPropertySetterCallback>,
146    query: Option<IndexedPropertyQueryCallback>,
147    deleter: Option<IndexedPropertyDeleterCallback>,
148    enumerator: Option<IndexedPropertyEnumeratorCallback>,
149    definer: Option<IndexedPropertyDefinerCallback>,
150    descriptor: Option<IndexedPropertyDescriptorCallback>,
151    data_or_null: *const Value,
152    flags: PropertyHandlerFlags,
153  );
154
155  fn v8__ObjectTemplate__SetImmutableProto(this: *const ObjectTemplate);
156}
157
158pub type AccessorNameGetterCallback = NamedGetterCallbackForAccessor;
159
160/// Note: [ReturnValue] is ignored for accessors.
161pub type AccessorNameSetterCallback = NamedSetterCallbackForAccessor;
162
163/// Interceptor for get requests on an object.
164///
165/// Use [ReturnValue] to set the return value of the intercepted get request. If
166/// the property does not exist the callback should not set the result and must
167/// not produce side effects.
168///
169/// See also [ObjectTemplate::set_handler].
170pub type NamedPropertyGetterCallback = NamedGetterCallback;
171
172/// Interceptor for set requests on an object.
173///
174/// Use [ReturnValue] to indicate whether the request was intercepted or not. If
175/// the setter successfully intercepts the request, i.e., if the request should
176/// not be further executed, call [ReturnValue::set]. If the setter did not
177/// intercept the request, i.e., if the request should be handled as if no
178/// interceptor is present, do not not call set() and do not produce side
179/// effects.
180///
181/// See also [ObjectTemplate::set_named_property_handler].
182pub type NamedPropertySetterCallback = NamedSetterCallback;
183
184/// Intercepts all requests that query the attributes of the property, e.g.,
185/// getOwnPropertyDescriptor(), propertyIsEnumerable(), and defineProperty().
186///
187/// Use [ReturnValue::set] to set the property attributes. The value is an
188/// integer encoding a [PropertyAttribute]. If the property does not exist the
189/// callback should not set the result and must not produce side effects.
190///
191/// Note: Some functions query the property attributes internally, even though
192/// they do not return the attributes. For example, hasOwnProperty() can trigger
193/// this interceptor depending on the state of the object.
194///
195/// See also [ObjectTemplate::set_named_property_handler].
196pub type NamedPropertyQueryCallback = NamedQueryCallback;
197
198/// Interceptor for delete requests on an object.
199///
200/// Use [ReturnValue] to indicate whether the request was intercepted or not. If
201/// the deleter successfully intercepts the request, i.e., if the request should
202/// not be further executed, call [ReturnValue::set] with a boolean value. The
203/// value is used as the return value of delete. If the deleter does not
204/// intercept the request then it should not set the result and must not produce
205/// side effects.
206///
207/// Note: If you need to mimic the behavior of delete, i.e., throw in strict
208/// mode instead of returning false, use
209/// [PropertyCallbackArguments::should_throw_on_error] to determine if you are
210/// in strict mode.
211///
212/// See also [ObjectTemplate::set_named_property_handler].
213pub type NamedPropertyDeleterCallback = NamedDeleterCallback;
214
215/// Returns an array containing the names of the properties the named property getter intercepts.
216///
217/// Note: The values in the array must be of type v8::Name.
218///
219/// See also [ObjectTemplate::set_named_property_handler].
220pub type NamedPropertyEnumeratorCallback = PropertyEnumeratorCallback;
221
222/// Interceptor for defineProperty requests on an object.
223///
224/// Use [ReturnValue] to indicate whether the request was intercepted or not. If
225/// the definer successfully intercepts the request, i.e., if the request should
226/// not be further executed, call [ReturnValue::set]. If the definer did not
227/// intercept the request, i.e., if the request should be handled as if no
228/// interceptor is present, do not not call set() and do not produce side
229/// effects.
230///
231/// See also [ObjectTemplate::set_named_property_handler].
232pub type NamedPropertyDefinerCallback = NamedDefinerCallback;
233
234/// Interceptor for getOwnPropertyDescriptor requests on an object.
235///
236/// Use [ReturnValue::set] to set the return value of the intercepted request.
237/// The return value must be an object that can be converted to a
238/// [PropertyDescriptor], e.g., a [Value] returned from
239/// `Object.getOwnPropertyDescriptor()`.
240///
241/// Note: If GetOwnPropertyDescriptor is intercepted, it will always return
242/// true, i.e., indicate that the property was found.
243///
244/// See also [ObjectTemplate::set_named_property_handler].
245pub type NamedPropertyDescriptorCallback = NamedGetterCallback;
246
247/// See [GenericNamedPropertyGetterCallback].
248pub type IndexedPropertyGetterCallback = IndexedGetterCallback;
249
250/// See [GenericNamedPropertySetterCallback].
251pub type IndexedPropertySetterCallback = IndexedSetterCallback;
252
253/// See [GenericNamedPropertyQueryCallback].
254pub type IndexedPropertyQueryCallback = IndexedQueryCallback;
255
256/// See [GenericNamedPropertyDeleterCallback].
257pub type IndexedPropertyDeleterCallback = IndexedDeleterCallback;
258
259/// See [GenericNamedPropertyEnumeratorCallback].
260pub type IndexedPropertyEnumeratorCallback = PropertyEnumeratorCallback;
261
262/// See [GenericNamedPropertyDefinerCallback].
263pub type IndexedPropertyDefinerCallback = IndexedDefinerCallback;
264
265/// See [GenericNamedPropertyDescriptorCallback].
266pub type IndexedPropertyDescriptorCallback = IndexedGetterCallback;
267
268pub struct AccessorConfiguration<'s> {
269  pub(crate) getter: AccessorNameGetterCallback,
270  pub(crate) setter: Option<AccessorNameSetterCallback>,
271  pub(crate) data: Option<Local<'s, Value>>,
272  pub(crate) property_attribute: PropertyAttribute,
273}
274
275impl<'s> AccessorConfiguration<'s> {
276  pub fn new(getter: impl MapFnTo<AccessorNameGetterCallback>) -> Self {
277    Self {
278      getter: getter.map_fn_to(),
279      setter: None,
280      data: None,
281      property_attribute: PropertyAttribute::NONE,
282    }
283  }
284
285  pub fn setter(
286    mut self,
287    setter: impl MapFnTo<AccessorNameSetterCallback>,
288  ) -> Self {
289    self.setter = Some(setter.map_fn_to());
290    self
291  }
292
293  pub fn property_attribute(
294    mut self,
295    property_attribute: PropertyAttribute,
296  ) -> Self {
297    self.property_attribute = property_attribute;
298    self
299  }
300
301  /// Set the associated data. The default is no associated data.
302  pub fn data(mut self, data: Local<'s, Value>) -> Self {
303    self.data = Some(data);
304    self
305  }
306}
307
308#[derive(Default)]
309pub struct NamedPropertyHandlerConfiguration<'s> {
310  pub(crate) getter: Option<NamedPropertyGetterCallback>,
311  pub(crate) setter: Option<NamedPropertySetterCallback>,
312  pub(crate) query: Option<NamedPropertyQueryCallback>,
313  pub(crate) deleter: Option<NamedPropertyDeleterCallback>,
314  pub(crate) enumerator: Option<NamedPropertyEnumeratorCallback>,
315  pub(crate) definer: Option<NamedPropertyDefinerCallback>,
316  pub(crate) descriptor: Option<NamedPropertyDescriptorCallback>,
317  pub(crate) data: Option<Local<'s, Value>>,
318  pub(crate) flags: PropertyHandlerFlags,
319}
320
321impl<'s> NamedPropertyHandlerConfiguration<'s> {
322  pub fn new() -> Self {
323    Self {
324      getter: None,
325      setter: None,
326      query: None,
327      deleter: None,
328      enumerator: None,
329      definer: None,
330      descriptor: None,
331      data: None,
332      flags: PropertyHandlerFlags::NONE,
333    }
334  }
335
336  pub fn is_some(&self) -> bool {
337    self.getter.is_some()
338      || self.setter.is_some()
339      || self.query.is_some()
340      || self.deleter.is_some()
341      || self.enumerator.is_some()
342      || self.definer.is_some()
343      || self.descriptor.is_some()
344      || !self.flags.is_none()
345  }
346
347  pub fn getter(
348    mut self,
349    getter: impl MapFnTo<NamedPropertyGetterCallback>,
350  ) -> Self {
351    self.getter = Some(getter.map_fn_to());
352    self
353  }
354
355  pub fn getter_raw(mut self, getter: NamedPropertyGetterCallback) -> Self {
356    self.getter = Some(getter);
357    self
358  }
359
360  pub fn setter(
361    mut self,
362    setter: impl MapFnTo<NamedPropertySetterCallback>,
363  ) -> Self {
364    self.setter = Some(setter.map_fn_to());
365    self
366  }
367
368  pub fn setter_raw(mut self, setter: NamedPropertySetterCallback) -> Self {
369    self.setter = Some(setter);
370    self
371  }
372
373  pub fn query(
374    mut self,
375    query: impl MapFnTo<NamedPropertyQueryCallback>,
376  ) -> Self {
377    self.query = Some(query.map_fn_to());
378    self
379  }
380
381  pub fn query_raw(mut self, query: NamedPropertyQueryCallback) -> Self {
382    self.query = Some(query);
383    self
384  }
385
386  pub fn deleter(
387    mut self,
388    deleter: impl MapFnTo<NamedPropertyDeleterCallback>,
389  ) -> Self {
390    self.deleter = Some(deleter.map_fn_to());
391    self
392  }
393
394  pub fn deleter_raw(mut self, deleter: NamedPropertyDeleterCallback) -> Self {
395    self.deleter = Some(deleter);
396    self
397  }
398
399  pub fn enumerator(
400    mut self,
401    enumerator: impl MapFnTo<NamedPropertyEnumeratorCallback>,
402  ) -> Self {
403    self.enumerator = Some(enumerator.map_fn_to());
404    self
405  }
406
407  pub fn enumerator_raw(
408    mut self,
409    enumerator: NamedPropertyEnumeratorCallback,
410  ) -> Self {
411    self.enumerator = Some(enumerator);
412    self
413  }
414
415  pub fn definer(
416    mut self,
417    definer: impl MapFnTo<NamedPropertyDefinerCallback>,
418  ) -> Self {
419    self.definer = Some(definer.map_fn_to());
420    self
421  }
422
423  pub fn definer_raw(mut self, definer: NamedPropertyDefinerCallback) -> Self {
424    self.definer = Some(definer);
425    self
426  }
427
428  pub fn descriptor(
429    mut self,
430    descriptor: impl MapFnTo<NamedPropertyDescriptorCallback>,
431  ) -> Self {
432    self.descriptor = Some(descriptor.map_fn_to());
433    self
434  }
435
436  pub fn descriptor_raw(
437    mut self,
438    descriptor: NamedPropertyDescriptorCallback,
439  ) -> Self {
440    self.descriptor = Some(descriptor);
441    self
442  }
443
444  /// Set the associated data. The default is no associated data.
445  pub fn data(mut self, data: Local<'s, Value>) -> Self {
446    self.data = Some(data);
447    self
448  }
449
450  /// Set the property handler flags. The default is PropertyHandlerFlags::NONE.
451  pub fn flags(mut self, flags: PropertyHandlerFlags) -> Self {
452    self.flags = flags;
453    self
454  }
455}
456
457#[derive(Default)]
458pub struct IndexedPropertyHandlerConfiguration<'s> {
459  pub(crate) getter: Option<IndexedPropertyGetterCallback>,
460  pub(crate) setter: Option<IndexedPropertySetterCallback>,
461  pub(crate) query: Option<IndexedPropertyQueryCallback>,
462  pub(crate) deleter: Option<IndexedPropertyDeleterCallback>,
463  pub(crate) enumerator: Option<IndexedPropertyEnumeratorCallback>,
464  pub(crate) definer: Option<IndexedPropertyDefinerCallback>,
465  pub(crate) descriptor: Option<IndexedPropertyDescriptorCallback>,
466  pub(crate) data: Option<Local<'s, Value>>,
467  pub(crate) flags: PropertyHandlerFlags,
468}
469
470impl<'s> IndexedPropertyHandlerConfiguration<'s> {
471  pub fn new() -> Self {
472    Self {
473      getter: None,
474      setter: None,
475      query: None,
476      deleter: None,
477      enumerator: None,
478      definer: None,
479      descriptor: None,
480      data: None,
481      flags: PropertyHandlerFlags::NONE,
482    }
483  }
484
485  pub fn is_some(&self) -> bool {
486    self.getter.is_some()
487      || self.setter.is_some()
488      || self.query.is_some()
489      || self.deleter.is_some()
490      || self.enumerator.is_some()
491      || self.definer.is_some()
492      || self.descriptor.is_some()
493      || !self.flags.is_none()
494  }
495
496  pub fn getter(
497    mut self,
498    getter: impl MapFnTo<IndexedPropertyGetterCallback>,
499  ) -> Self {
500    self.getter = Some(getter.map_fn_to());
501    self
502  }
503
504  pub fn getter_raw(mut self, getter: IndexedPropertyGetterCallback) -> Self {
505    self.getter = Some(getter);
506    self
507  }
508
509  pub fn setter(
510    mut self,
511    setter: impl MapFnTo<IndexedPropertySetterCallback>,
512  ) -> Self {
513    self.setter = Some(setter.map_fn_to());
514    self
515  }
516
517  pub fn setter_raw(mut self, setter: IndexedPropertySetterCallback) -> Self {
518    self.setter = Some(setter);
519    self
520  }
521
522  pub fn query(
523    mut self,
524    query: impl MapFnTo<IndexedPropertyQueryCallback>,
525  ) -> Self {
526    self.query = Some(query.map_fn_to());
527    self
528  }
529
530  pub fn query_raw(mut self, query: IndexedPropertyQueryCallback) -> Self {
531    self.query = Some(query);
532    self
533  }
534
535  pub fn deleter(
536    mut self,
537    deleter: impl MapFnTo<IndexedPropertyDeleterCallback>,
538  ) -> Self {
539    self.deleter = Some(deleter.map_fn_to());
540    self
541  }
542
543  pub fn deleter_raw(
544    mut self,
545    deleter: IndexedPropertyDeleterCallback,
546  ) -> Self {
547    self.deleter = Some(deleter);
548    self
549  }
550
551  pub fn enumerator(
552    mut self,
553    enumerator: impl MapFnTo<IndexedPropertyEnumeratorCallback>,
554  ) -> Self {
555    self.enumerator = Some(enumerator.map_fn_to());
556    self
557  }
558
559  pub fn enumerator_raw(
560    mut self,
561    enumerator: IndexedPropertyEnumeratorCallback,
562  ) -> Self {
563    self.enumerator = Some(enumerator);
564    self
565  }
566
567  pub fn definer(
568    mut self,
569    definer: impl MapFnTo<IndexedPropertyDefinerCallback>,
570  ) -> Self {
571    self.definer = Some(definer.map_fn_to());
572    self
573  }
574
575  pub fn definer_raw(
576    mut self,
577    definer: IndexedPropertyDefinerCallback,
578  ) -> Self {
579    self.definer = Some(definer);
580    self
581  }
582
583  pub fn descriptor(
584    mut self,
585    descriptor: impl MapFnTo<IndexedPropertyDescriptorCallback>,
586  ) -> Self {
587    self.descriptor = Some(descriptor.map_fn_to());
588    self
589  }
590
591  pub fn descriptor_raw(
592    mut self,
593    descriptor: IndexedPropertyDescriptorCallback,
594  ) -> Self {
595    self.descriptor = Some(descriptor);
596    self
597  }
598
599  /// Set the associated data. The default is no associated data.
600  pub fn data(mut self, data: Local<'s, Value>) -> Self {
601    self.data = Some(data);
602    self
603  }
604
605  /// Set the property handler flags. The default is PropertyHandlerFlags::NONE.
606  pub fn flags(mut self, flags: PropertyHandlerFlags) -> Self {
607    self.flags = flags;
608    self
609  }
610}
611
612#[derive(Debug, Clone, Copy)]
613#[repr(C)]
614pub enum Intrinsic {
615  ArrayProtoEntries,
616  ArrayProtoForEach,
617  ArrayProtoKeys,
618  ArrayProtoValues,
619  ArrayPrototype,
620  AsyncIteratorPrototype,
621  ErrorPrototype,
622  IteratorPrototype,
623  MapIteratorPrototype,
624  ObjProtoValueOf,
625  SetIteratorPrototype,
626}
627
628impl Template {
629  /// Adds a property to each instance created by this template.
630  #[inline(always)]
631  pub fn set(&self, key: Local<Name>, value: Local<Data>) {
632    self.set_with_attr(key, value, PropertyAttribute::NONE);
633  }
634
635  /// Adds a property to each instance created by this template with
636  /// the specified property attributes.
637  #[inline(always)]
638  pub fn set_with_attr(
639    &self,
640    key: Local<Name>,
641    value: Local<Data>,
642    attr: PropertyAttribute,
643  ) {
644    unsafe { v8__Template__Set(self, &*key, &*value, attr) }
645  }
646
647  /// During template instantiation, sets the value with the
648  /// intrinsic property from the correct context.
649  #[inline(always)]
650  pub fn set_intrinsic_data_property(
651    &self,
652    key: Local<Name>,
653    intrinsic: Intrinsic,
654    attr: PropertyAttribute,
655  ) {
656    unsafe {
657      v8__Template__SetIntrinsicDataProperty(self, &*key, intrinsic, attr);
658    }
659  }
660}
661
662impl<'s> FunctionBuilder<'s, FunctionTemplate> {
663  /// Set the function call signature. The default is no signature.
664  #[inline(always)]
665  pub fn signature(mut self, signature: Local<'s, Signature>) -> Self {
666    self.signature = Some(signature);
667    self
668  }
669
670  /// Creates the function template.
671  #[inline(always)]
672  pub fn build<'i>(
673    self,
674    scope: &PinScope<'s, 'i, ()>,
675  ) -> Local<'s, FunctionTemplate> {
676    unsafe {
677      scope.cast_local(|sd| {
678        v8__FunctionTemplate__New(
679          sd.get_isolate_ptr(),
680          self.callback,
681          self.data.map_or_else(null, |p| &*p),
682          self.signature.map_or_else(null, |p| &*p),
683          self.length,
684          self.constructor_behavior,
685          self.side_effect_type,
686          null(),
687          0,
688        )
689      })
690    }
691    .unwrap()
692  }
693
694  /// It's not required to provide `CFunctionInfo` for the overloads - if they
695  /// are omitted, then they will be automatically created. In some cases it is
696  /// useful to pass them explicitly - eg. when you are snapshotting you'd provide
697  /// the overloads and `CFunctionInfo` that would be placed in the external
698  /// references array.
699  ///
700  /// # Lifetime invariant
701  ///
702  /// `overloads` is `&'static [CFunction]` because, since
703  /// [crrev.com/c/7828135], V8 stores the raw `v8::CFunction` pointers it
704  /// receives via `NewWithCFunctionOverloads` directly inside
705  /// `FunctionTemplateInfo` (rather than copying them into a managed heap
706  /// object). The pointed-to storage must therefore outlive every
707  /// `FunctionTemplate` that references it. A `FunctionTemplate` may live
708  /// until isolate disposal, so in practice this requires the slice (and its
709  /// elements, including the `CFunctionInfo`s they reference) to have
710  /// `'static` storage. Use a `const` slice such as
711  ///
712  /// ```ignore
713  /// const OVERLOADS: &[v8::fast_api::CFunction] = &[FAST_TEST];
714  /// ```
715  ///
716  /// or a `static` item; do **not** synthesize the slice from stack-local
717  /// data.
718  ///
719  /// [crrev.com/c/7828135]: https://chromium-review.googlesource.com/c/v8/v8/+/7828135
720  pub fn build_fast<'i>(
721    self,
722    scope: &PinScope<'s, 'i>,
723    overloads: &'static [CFunction],
724  ) -> Local<'s, FunctionTemplate> {
725    unsafe {
726      scope.cast_local(|sd| {
727        v8__FunctionTemplate__New(
728          sd.get_isolate_ptr(),
729          self.callback,
730          self.data.map_or_else(null, |p| &*p),
731          self.signature.map_or_else(null, |p| &*p),
732          self.length,
733          ConstructorBehavior::Throw,
734          self.side_effect_type,
735          overloads.as_ptr(),
736          overloads.len(),
737        )
738      })
739    }
740    .unwrap()
741  }
742}
743
744/// A Signature specifies which receiver is valid for a function.
745///
746/// A receiver matches a given signature if the receiver (or any of its
747/// hidden prototypes) was created from the signature's FunctionTemplate, or
748/// from a FunctionTemplate that inherits directly or indirectly from the
749/// signature's FunctionTemplate.
750impl Signature {
751  #[inline(always)]
752  pub fn new<'s>(
753    scope: &PinScope<'s, '_, ()>,
754    templ: Local<FunctionTemplate>,
755  ) -> Local<'s, Self> {
756    unsafe {
757      scope.cast_local(|sd| v8__Signature__New(sd.get_isolate_ptr(), &*templ))
758    }
759    .unwrap()
760  }
761}
762
763impl FunctionTemplate {
764  /// Create a FunctionBuilder to configure a FunctionTemplate.
765  /// This is the same as FunctionBuilder::<FunctionTemplate>::new().
766  #[inline(always)]
767  pub fn builder<'s>(
768    callback: impl MapFnTo<FunctionCallback>,
769  ) -> FunctionBuilder<'s, Self> {
770    FunctionBuilder::new(callback)
771  }
772
773  #[inline(always)]
774  pub fn builder_raw<'s>(
775    callback: FunctionCallback,
776  ) -> FunctionBuilder<'s, Self> {
777    FunctionBuilder::new_raw(callback)
778  }
779
780  /// Creates a function template.
781  #[inline(always)]
782  pub fn new<'s>(
783    scope: &PinScope<'s, '_, ()>,
784    callback: impl MapFnTo<FunctionCallback>,
785  ) -> Local<'s, FunctionTemplate> {
786    Self::builder(callback).build(scope)
787  }
788
789  #[inline(always)]
790  pub fn new_raw<'s>(
791    scope: &PinScope<'s, '_, ()>,
792    callback: FunctionCallback,
793  ) -> Local<'s, FunctionTemplate> {
794    Self::builder_raw(callback).build(scope)
795  }
796
797  /// Returns the unique function instance in the current execution context.
798  #[inline(always)]
799  pub fn get_function<'s>(
800    &self,
801    scope: &PinScope<'s, '_>,
802  ) -> Option<Local<'s, Function>> {
803    unsafe {
804      scope.cast_local(|sd| {
805        v8__FunctionTemplate__GetFunction(self, sd.get_current_context())
806      })
807    }
808  }
809
810  /// Set the class name of the FunctionTemplate. This is used for
811  /// printing objects created with the function created from the
812  /// FunctionTemplate as its constructor.
813  #[inline(always)]
814  pub fn set_class_name(&self, name: Local<String>) {
815    unsafe { v8__FunctionTemplate__SetClassName(self, &*name) };
816  }
817
818  /// Returns the ObjectTemplate that is used by this
819  /// FunctionTemplate as a PrototypeTemplate
820  #[inline(always)]
821  pub fn prototype_template<'s>(
822    &self,
823    scope: &PinScope<'s, '_, ()>,
824  ) -> Local<'s, ObjectTemplate> {
825    unsafe {
826      scope.cast_local(|_sd| v8__FunctionTemplate__PrototypeTemplate(self))
827    }
828    .unwrap()
829  }
830
831  /// Returns the object template that is used for instances created when this function
832  /// template is called as a constructor.
833  #[inline(always)]
834  pub fn instance_template<'s>(
835    &self,
836    scope: &PinScope<'s, '_, ()>,
837  ) -> Local<'s, ObjectTemplate> {
838    unsafe {
839      scope.cast_local(|_sd| v8__FunctionTemplate__InstanceTemplate(self))
840    }
841    .unwrap()
842  }
843
844  /// Causes the function template to inherit from a parent function template.
845  /// This means the function's prototype.__proto__ is set to the parent function's prototype.
846  #[inline(always)]
847  pub fn inherit(&self, parent: Local<FunctionTemplate>) {
848    unsafe { v8__FunctionTemplate__Inherit(self, &*parent) };
849  }
850
851  /// Sets the ReadOnly flag in the attributes of the 'prototype' property
852  /// of functions created from this FunctionTemplate to true.
853  #[inline(always)]
854  pub fn read_only_prototype(&self) {
855    unsafe { v8__FunctionTemplate__ReadOnlyPrototype(self) };
856  }
857
858  /// Removes the prototype property from functions created from this FunctionTemplate.
859  #[inline(always)]
860  pub fn remove_prototype(&self) {
861    unsafe { v8__FunctionTemplate__RemovePrototype(self) };
862  }
863
864  /// Sets an [accessor property](https://tc39.es/ecma262/#sec-property-attributes)
865  /// on the function template (i.e. a static accessor on the constructor).
866  ///
867  /// # Panics
868  ///
869  /// Panics if both `getter` and `setter` are `None`.
870  #[inline(always)]
871  pub fn set_accessor_property(
872    &self,
873    key: Local<Name>,
874    getter: Option<Local<FunctionTemplate>>,
875    setter: Option<Local<FunctionTemplate>>,
876    attr: PropertyAttribute,
877  ) {
878    assert!(getter.is_some() || setter.is_some());
879
880    unsafe {
881      let getter = getter.map_or_else(std::ptr::null, |v| &*v);
882      let setter = setter.map_or_else(std::ptr::null, |v| &*v);
883      v8__FunctionTemplate__SetAccessorProperty(
884        self, &*key, getter, setter, attr,
885      );
886    }
887  }
888}
889
890impl ObjectTemplate {
891  /// Creates an object template.
892  #[inline(always)]
893  pub fn new<'s>(scope: &PinScope<'s, '_, ()>) -> Local<'s, ObjectTemplate> {
894    unsafe {
895      scope.cast_local(|sd| {
896        v8__ObjectTemplate__New(sd.get_isolate_ptr(), std::ptr::null())
897      })
898    }
899    .unwrap()
900  }
901
902  /// Creates an object template from a function template.
903  #[inline(always)]
904  pub fn new_from_template<'s>(
905    scope: &PinScope<'s, '_, ()>,
906    templ: Local<FunctionTemplate>,
907  ) -> Local<'s, ObjectTemplate> {
908    unsafe {
909      scope
910        .cast_local(|sd| v8__ObjectTemplate__New(sd.get_isolate_ptr(), &*templ))
911    }
912    .unwrap()
913  }
914
915  /// Creates a new instance of this object template.
916  #[inline(always)]
917  pub fn new_instance<'s>(
918    &self,
919    scope: &PinScope<'s, '_>,
920  ) -> Option<Local<'s, Object>> {
921    unsafe {
922      scope.cast_local(|sd| {
923        v8__ObjectTemplate__NewInstance(self, sd.get_current_context())
924      })
925    }
926  }
927
928  /// Gets the number of internal fields for objects generated from
929  /// this template.
930  #[inline(always)]
931  pub fn internal_field_count(&self) -> usize {
932    let count = unsafe { v8__ObjectTemplate__InternalFieldCount(self) };
933    usize::try_from(count).expect("bad internal field count") // Can't happen.
934  }
935
936  /// Sets the number of internal fields for objects generated from
937  /// this template.
938  #[inline(always)]
939  pub fn set_internal_field_count(&self, value: usize) -> bool {
940    // The C++ API takes an i32 but trying to set a value < 0
941    // results in unpredictable behavior, hence we disallow it.
942    match int::try_from(value) {
943      Err(_) => false,
944      Ok(value) => {
945        unsafe { v8__ObjectTemplate__SetInternalFieldCount(self, value) };
946        true
947      }
948    }
949  }
950
951  #[inline(always)]
952  pub fn set_accessor(
953    &self,
954    key: Local<Name>,
955    getter: impl MapFnTo<AccessorNameGetterCallback>,
956  ) {
957    self
958      .set_accessor_with_configuration(key, AccessorConfiguration::new(getter));
959  }
960
961  #[inline(always)]
962  pub fn set_accessor_with_setter(
963    &self,
964    key: Local<Name>,
965    getter: impl MapFnTo<AccessorNameGetterCallback>,
966    setter: impl MapFnTo<AccessorNameSetterCallback>,
967  ) {
968    self.set_accessor_with_configuration(
969      key,
970      AccessorConfiguration::new(getter).setter(setter),
971    );
972  }
973
974  #[inline(always)]
975  pub fn set_accessor_with_configuration(
976    &self,
977    key: Local<Name>,
978    configuration: AccessorConfiguration,
979  ) {
980    unsafe {
981      v8__ObjectTemplate__SetNativeDataProperty(
982        self,
983        &*key,
984        configuration.getter,
985        configuration.setter,
986        configuration.data.map_or_else(null, |p| &*p),
987        configuration.property_attribute,
988      );
989    }
990  }
991
992  //Re uses the AccessorNameGetterCallback to avoid implementation conflicts since the declaration for
993  //GenericNamedPropertyGetterCallback and  AccessorNameGetterCallback are the same
994  pub fn set_named_property_handler(
995    &self,
996    configuration: NamedPropertyHandlerConfiguration,
997  ) {
998    assert!(configuration.is_some());
999    unsafe {
1000      v8__ObjectTemplate__SetNamedPropertyHandler(
1001        self,
1002        configuration.getter,
1003        configuration.setter,
1004        configuration.query,
1005        configuration.deleter,
1006        configuration.enumerator,
1007        configuration.definer,
1008        configuration.descriptor,
1009        configuration.data.map_or_else(null, |p| &*p),
1010        configuration.flags,
1011      );
1012    }
1013  }
1014
1015  pub fn set_indexed_property_handler(
1016    &self,
1017    configuration: IndexedPropertyHandlerConfiguration,
1018  ) {
1019    assert!(configuration.is_some());
1020    unsafe {
1021      v8__ObjectTemplate__SetIndexedPropertyHandler(
1022        self,
1023        configuration.getter,
1024        configuration.setter,
1025        configuration.query,
1026        configuration.deleter,
1027        configuration.enumerator,
1028        configuration.definer,
1029        configuration.descriptor,
1030        configuration.data.map_or_else(null, |p| &*p),
1031        configuration.flags,
1032      );
1033    }
1034  }
1035
1036  /// Sets an [accessor property](https://tc39.es/ecma262/#sec-property-attributes)
1037  /// on the object template.
1038  ///
1039  /// # Panics
1040  ///
1041  /// Panics if both `getter` and `setter` are `None`.
1042  #[inline(always)]
1043  pub fn set_accessor_property(
1044    &self,
1045    key: Local<Name>,
1046    getter: Option<Local<FunctionTemplate>>,
1047    setter: Option<Local<FunctionTemplate>>,
1048    attr: PropertyAttribute,
1049  ) {
1050    assert!(getter.is_some() || setter.is_some());
1051
1052    unsafe {
1053      let getter = getter.map_or_else(std::ptr::null, |v| &*v);
1054      let setter = setter.map_or_else(std::ptr::null, |v| &*v);
1055      v8__ObjectTemplate__SetAccessorProperty(
1056        self, &*key, getter, setter, attr,
1057      );
1058    }
1059  }
1060
1061  /// Makes the ObjectTemplate for an immutable prototype exotic object,
1062  /// with an immutable proto.
1063  #[inline(always)]
1064  pub fn set_immutable_proto(&self) {
1065    unsafe { v8__ObjectTemplate__SetImmutableProto(self) };
1066  }
1067}