Skip to main content

v8/
function.rs

1use std::convert::TryFrom;
2use std::marker::PhantomData;
3use std::ptr::NonNull;
4use std::ptr::null;
5
6use crate::Array;
7use crate::Boolean;
8use crate::CallbackScope;
9use crate::Context;
10use crate::Function;
11use crate::Integer;
12use crate::Isolate;
13use crate::Local;
14use crate::Name;
15use crate::Object;
16use crate::PropertyDescriptor;
17use crate::ScriptOrigin;
18use crate::SealedLocal;
19use crate::Signature;
20use crate::String;
21use crate::UniqueRef;
22use crate::Value;
23use crate::isolate::RealIsolate;
24use crate::scope::PinScope;
25use crate::scope::callback_scope;
26use crate::script_compiler::CachedData;
27use crate::support::MapFnFrom;
28use crate::support::MapFnTo;
29use crate::support::ToCFn;
30use crate::support::UnitType;
31use crate::support::{Opaque, int};
32use crate::template::Intercepted;
33
34unsafe extern "C" {
35  fn v8__Function__New(
36    context: *const Context,
37    callback: FunctionCallback,
38    data_or_null: *const Value,
39    length: i32,
40    constructor_behavior: ConstructorBehavior,
41    side_effect_type: SideEffectType,
42  ) -> *const Function;
43  fn v8__Function__Call(
44    this: *const Function,
45    context: *const Context,
46    recv: *const Value,
47    argc: int,
48    argv: *const *const Value,
49  ) -> *const Value;
50  fn v8__Function__NewInstance(
51    this: *const Function,
52    context: *const Context,
53    argc: int,
54    argv: *const *const Value,
55  ) -> *const Object;
56  fn v8__Function__GetName(this: *const Function) -> *const String;
57  fn v8__Function__SetName(this: *const Function, name: *const String);
58  fn v8__Function__GetScriptColumnNumber(this: *const Function) -> int;
59  fn v8__Function__GetScriptLineNumber(this: *const Function) -> int;
60  fn v8__Function__ScriptId(this: *const Function) -> int;
61  fn v8__Function__GetScriptOrigin(
62    this: *const Function,
63  ) -> *const ScriptOrigin<'static>;
64
65  fn v8__Function__CreateCodeCache(
66    script: *const Function,
67  ) -> *mut CachedData<'static>;
68
69  fn v8__FunctionCallbackInfo__GetIsolate(
70    this: *const FunctionCallbackInfo,
71  ) -> *mut RealIsolate;
72  fn v8__FunctionCallbackInfo__Data(
73    this: *const FunctionCallbackInfo,
74  ) -> *const Value;
75  fn v8__FunctionCallbackInfo__This(
76    this: *const FunctionCallbackInfo,
77  ) -> *const Object;
78  fn v8__FunctionCallbackInfo__NewTarget(
79    this: *const FunctionCallbackInfo,
80  ) -> *const Value;
81  fn v8__FunctionCallbackInfo__IsConstructCall(
82    this: *const FunctionCallbackInfo,
83  ) -> bool;
84  fn v8__FunctionCallbackInfo__Get(
85    this: *const FunctionCallbackInfo,
86    index: int,
87  ) -> *const Value;
88  fn v8__FunctionCallbackInfo__Length(this: *const FunctionCallbackInfo)
89  -> int;
90  fn v8__FunctionCallbackInfo__GetReturnValue(
91    this: *const FunctionCallbackInfo,
92  ) -> usize;
93
94  fn v8__PropertyCallbackInfo__GetIsolate(
95    this: *const RawPropertyCallbackInfo,
96  ) -> *mut RealIsolate;
97  fn v8__PropertyCallbackInfo__Data(
98    this: *const RawPropertyCallbackInfo,
99  ) -> *const Value;
100  fn v8__PropertyCallbackInfo__Holder(
101    this: *const RawPropertyCallbackInfo,
102  ) -> *const Object;
103  fn v8__PropertyCallbackInfo__GetReturnValue(
104    this: *const RawPropertyCallbackInfo,
105  ) -> usize;
106  fn v8__PropertyCallbackInfo__ShouldThrowOnError(
107    this: *const RawPropertyCallbackInfo,
108  ) -> bool;
109
110  fn v8__ReturnValue__Value__Set(
111    this: *mut RawReturnValue,
112    value: *const Value,
113  );
114  fn v8__ReturnValue__Value__Set__Bool(this: *mut RawReturnValue, value: bool);
115  fn v8__ReturnValue__Value__Set__Int32(this: *mut RawReturnValue, value: i32);
116  fn v8__ReturnValue__Value__Set__Uint32(this: *mut RawReturnValue, value: u32);
117  fn v8__ReturnValue__Value__Set__Double(this: *mut RawReturnValue, value: f64);
118  fn v8__ReturnValue__Value__SetNull(this: *mut RawReturnValue);
119  fn v8__ReturnValue__Value__SetUndefined(this: *mut RawReturnValue);
120  fn v8__ReturnValue__Value__SetEmptyString(this: *mut RawReturnValue);
121  fn v8__ReturnValue__Value__Get(this: *const RawReturnValue) -> *const Value;
122}
123
124// Ad-libbed - V8 does not document ConstructorBehavior.
125/// ConstructorBehavior::Allow creates a regular API function.
126///
127/// ConstructorBehavior::Throw creates a "concise" API function, a function
128/// without a ".prototype" property, that is somewhat faster to create and has
129/// a smaller footprint. Functionally equivalent to ConstructorBehavior::Allow
130/// followed by a call to FunctionTemplate::RemovePrototype().
131#[repr(C)]
132pub enum ConstructorBehavior {
133  Throw,
134  Allow,
135}
136
137/// Options for marking whether callbacks may trigger JS-observable side
138/// effects. Side-effect-free callbacks are allowlisted during debug evaluation
139/// with throwOnSideEffect. It applies when calling a Function,
140/// FunctionTemplate, or an Accessor callback. For Interceptors, please see
141/// PropertyHandlerFlags's kHasNoSideEffect.
142/// Callbacks that only cause side effects to the receiver are allowlisted if
143/// invoked on receiver objects that are created within the same debug-evaluate
144/// call, as these objects are temporary and the side effect does not escape.
145#[repr(C)]
146pub enum SideEffectType {
147  HasSideEffect,
148  HasNoSideEffect,
149  HasSideEffectToReceiver,
150}
151
152#[repr(C)]
153#[derive(Debug)]
154struct RawReturnValue(usize);
155
156// Note: the 'cb lifetime is required because the ReturnValue object must not
157// outlive the FunctionCallbackInfo/PropertyCallbackInfo object from which it
158// is derived.
159#[derive(Debug)]
160pub struct ReturnValue<'cb, T = Value>(RawReturnValue, PhantomData<&'cb T>);
161
162impl<'cb, T> ReturnValue<'cb, T> {
163  #[inline(always)]
164  pub fn from_property_callback_info(
165    info: &'cb PropertyCallbackInfo<T>,
166  ) -> Self {
167    Self(
168      unsafe {
169        RawReturnValue(v8__PropertyCallbackInfo__GetReturnValue(&info.0))
170      },
171      PhantomData,
172    )
173  }
174}
175
176impl<'cb> ReturnValue<'cb, Value> {
177  #[inline(always)]
178  pub fn from_function_callback_info(info: &'cb FunctionCallbackInfo) -> Self {
179    Self(
180      unsafe { RawReturnValue(v8__FunctionCallbackInfo__GetReturnValue(info)) },
181      PhantomData,
182    )
183  }
184}
185
186impl ReturnValue<'_, ()> {
187  #[inline(always)]
188  pub fn set_bool(&mut self, value: bool) {
189    unsafe { v8__ReturnValue__Value__Set__Bool(&mut self.0, value) }
190  }
191}
192
193impl<T> ReturnValue<'_, T>
194where
195  for<'s> Local<'s, T>: Into<Local<'s, Value>>,
196{
197  #[inline(always)]
198  pub fn set(&mut self, value: Local<T>) {
199    unsafe { v8__ReturnValue__Value__Set(&mut self.0, &*value.into()) }
200  }
201
202  #[inline(always)]
203  pub fn set_bool(&mut self, value: bool) {
204    unsafe { v8__ReturnValue__Value__Set__Bool(&mut self.0, value) }
205  }
206
207  #[inline(always)]
208  pub fn set_int32(&mut self, value: i32) {
209    unsafe { v8__ReturnValue__Value__Set__Int32(&mut self.0, value) }
210  }
211
212  #[inline(always)]
213  pub fn set_uint32(&mut self, value: u32) {
214    unsafe { v8__ReturnValue__Value__Set__Uint32(&mut self.0, value) }
215  }
216
217  #[inline(always)]
218  pub fn set_double(&mut self, value: f64) {
219    unsafe { v8__ReturnValue__Value__Set__Double(&mut self.0, value) }
220  }
221
222  #[inline(always)]
223  pub fn set_null(&mut self) {
224    unsafe { v8__ReturnValue__Value__SetNull(&mut self.0) }
225  }
226
227  #[inline(always)]
228  pub fn set_undefined(&mut self) {
229    unsafe { v8__ReturnValue__Value__SetUndefined(&mut self.0) }
230  }
231
232  #[inline(always)]
233  pub fn set_empty_string(&mut self) {
234    unsafe { v8__ReturnValue__Value__SetEmptyString(&mut self.0) }
235  }
236
237  /// Getter. Creates a new Local<> so it comes with a certain performance
238  /// hit. If the ReturnValue was not yet set, this will return the undefined
239  /// value.
240  #[inline(always)]
241  pub fn get<'s>(&self, scope: &PinScope<'s, '_>) -> Local<'s, Value> {
242    unsafe { scope.cast_local(|_| v8__ReturnValue__Value__Get(&self.0)) }
243      .unwrap()
244  }
245}
246
247/// The argument information given to function call callbacks.  This
248/// class provides access to information about the context of the call,
249/// including the receiver, the number and values of arguments, and
250/// the holder of the function.
251#[repr(C)]
252#[derive(Debug)]
253pub struct FunctionCallbackInfo(*mut Opaque);
254
255impl FunctionCallbackInfo {
256  #[inline(always)]
257  pub(crate) fn get_isolate_ptr(&self) -> *mut RealIsolate {
258    unsafe { v8__FunctionCallbackInfo__GetIsolate(self) }
259  }
260
261  #[inline(always)]
262  pub(crate) fn new_target(&self) -> Local<'_, Value> {
263    unsafe {
264      let ptr = v8__FunctionCallbackInfo__NewTarget(self);
265      let nn = NonNull::new_unchecked(ptr as *mut _);
266      Local::from_non_null(nn)
267    }
268  }
269
270  #[inline(always)]
271  pub(crate) fn this(&self) -> Local<'_, Object> {
272    unsafe {
273      let ptr = v8__FunctionCallbackInfo__This(self);
274      let nn = NonNull::new_unchecked(ptr as *mut _);
275      Local::from_non_null(nn)
276    }
277  }
278
279  #[inline]
280  pub fn is_construct_call(&self) -> bool {
281    unsafe { v8__FunctionCallbackInfo__IsConstructCall(self) }
282  }
283
284  #[inline(always)]
285  pub(crate) fn data(&self) -> Local<'_, Value> {
286    unsafe {
287      let ptr = v8__FunctionCallbackInfo__Data(self);
288      let nn = NonNull::new_unchecked(ptr as *mut Value);
289      Local::from_non_null(nn)
290    }
291  }
292
293  #[inline(always)]
294  pub(crate) fn length(&self) -> int {
295    unsafe { v8__FunctionCallbackInfo__Length(self) }
296  }
297
298  #[inline(always)]
299  pub(crate) fn get(&self, index: int) -> Local<'_, Value> {
300    unsafe {
301      let ptr = v8__FunctionCallbackInfo__Get(self, index);
302      let nn = NonNull::new_unchecked(ptr as *mut Value);
303      Local::from_non_null(nn)
304    }
305  }
306}
307
308#[repr(C)]
309#[derive(Debug)]
310struct RawPropertyCallbackInfo(*mut Opaque);
311
312/// The information passed to a property callback about the context
313/// of the property access.
314#[repr(C)]
315#[derive(Debug)]
316pub struct PropertyCallbackInfo<T>(RawPropertyCallbackInfo, PhantomData<T>);
317
318impl<T> PropertyCallbackInfo<T> {
319  #[inline(always)]
320  pub(crate) fn get_isolate_ptr(&self) -> *mut RealIsolate {
321    unsafe { v8__PropertyCallbackInfo__GetIsolate(&self.0) }
322  }
323}
324
325#[derive(Debug)]
326pub struct FunctionCallbackArguments<'s>(&'s FunctionCallbackInfo);
327
328impl<'s> FunctionCallbackArguments<'s> {
329  #[inline(always)]
330  pub fn from_function_callback_info(info: &'s FunctionCallbackInfo) -> Self {
331    Self(info)
332  }
333
334  /// SAFETY: caller must guarantee that no other references to the isolate are
335  /// accessible. Specifically, if an open CallbackScope or HandleScope exists
336  /// in the current function, `FunctionCallbackArguments::get_isolate()` should
337  /// not be called.
338  #[inline(always)]
339  pub unsafe fn get_isolate(&mut self) -> &mut Isolate {
340    unsafe { &mut *(self.0.get_isolate_ptr() as *mut crate::isolate::Isolate) }
341  }
342
343  /// For construct calls, this returns the "new.target" value.
344  #[inline(always)]
345  pub fn new_target(&self) -> Local<'s, Value> {
346    self.0.new_target()
347  }
348
349  /// Returns true if this is a construct call, i.e., if the function was
350  /// called with the `new` operator.
351  #[inline]
352  pub fn is_construct_call(&self) -> bool {
353    self.0.is_construct_call()
354  }
355
356  /// Returns the receiver. This corresponds to the "this" value.
357  #[inline(always)]
358  pub fn this(&self) -> Local<'s, Object> {
359    self.0.this()
360  }
361
362  /// Returns the data argument specified when creating the callback.
363  #[inline(always)]
364  pub fn data(&self) -> Local<'s, Value> {
365    self.0.data()
366  }
367
368  /// The number of available arguments.
369  #[inline(always)]
370  pub fn length(&self) -> int {
371    self.0.length()
372  }
373
374  /// Accessor for the available arguments. Returns `undefined` if the index is
375  /// out of bounds.
376  #[inline(always)]
377  pub fn get(&self, i: int) -> Local<'s, Value> {
378    self.0.get(i)
379  }
380}
381
382#[derive(Debug)]
383pub struct PropertyCallbackArguments<'s>(&'s RawPropertyCallbackInfo);
384
385impl<'s> PropertyCallbackArguments<'s> {
386  #[inline(always)]
387  pub(crate) fn from_property_callback_info<T>(
388    info: &'s PropertyCallbackInfo<T>,
389  ) -> Self {
390    Self(&info.0)
391  }
392
393  /// Returns the object in the prototype chain of the receiver that has the
394  /// interceptor. Suppose you have `x` and its prototype is `y`, and `y`
395  /// has an interceptor. Then `info.This()` is `x` and `info.Holder()` is `y`.
396  /// In case the property is installed on the global object the Holder()
397  /// would return the global proxy.
398  #[inline(always)]
399  pub fn holder(&self) -> Local<'s, Object> {
400    unsafe {
401      Local::from_raw(v8__PropertyCallbackInfo__Holder(self.0))
402        .unwrap_unchecked()
403    }
404  }
405
406  /// Returns the data set in the configuration, i.e., in
407  /// `NamedPropertyHandlerConfiguration` or
408  /// `IndexedPropertyHandlerConfiguration.`
409  #[inline(always)]
410  pub fn data(&self) -> Local<'s, Value> {
411    unsafe {
412      Local::from_raw(v8__PropertyCallbackInfo__Data(self.0)).unwrap_unchecked()
413    }
414  }
415
416  /// Returns `true` if the intercepted function should throw if an error
417  /// occurs. Usually, `true` corresponds to `'use strict'`.
418  ///
419  /// Always `false` when intercepting `Reflect.set()` independent of the
420  /// language mode.
421  #[inline(always)]
422  pub fn should_throw_on_error(&self) -> bool {
423    unsafe { v8__PropertyCallbackInfo__ShouldThrowOnError(self.0) }
424  }
425}
426
427pub type FunctionCallback = unsafe extern "C" fn(*const FunctionCallbackInfo);
428
429impl<F> MapFnFrom<F> for FunctionCallback
430where
431  F: UnitType
432    + for<'s, 'i> Fn(
433      &mut PinScope<'s, 'i>,
434      FunctionCallbackArguments<'s>,
435      ReturnValue<'s, Value>,
436    ),
437{
438  fn mapping() -> Self {
439    let f = |info: *const FunctionCallbackInfo| {
440      let info = unsafe { &*info };
441      let scope = std::pin::pin!(unsafe { CallbackScope::new(info) });
442      let mut scope = scope.init();
443      let args = FunctionCallbackArguments::from_function_callback_info(info);
444      let rv = ReturnValue::from_function_callback_info(info);
445      (F::get())(&mut scope, args, rv);
446    };
447    f.to_c_fn()
448  }
449}
450
451pub(crate) type NamedGetterCallbackForAccessor =
452  unsafe extern "C" fn(SealedLocal<Name>, *const PropertyCallbackInfo<Value>);
453
454impl<F> MapFnFrom<F> for NamedGetterCallbackForAccessor
455where
456  F: UnitType
457    + for<'s, 'i> Fn(
458      &mut PinScope<'s, 'i>,
459      Local<'s, Name>,
460      PropertyCallbackArguments<'s>,
461      ReturnValue<Value>,
462    ),
463{
464  fn mapping() -> Self {
465    let f = |key: SealedLocal<Name>,
466             info: *const PropertyCallbackInfo<Value>| {
467      let info = unsafe { &*info };
468      callback_scope!(unsafe scope, info);
469      let key = unsafe { scope.unseal(key) };
470      let args = PropertyCallbackArguments::from_property_callback_info(info);
471      let rv = ReturnValue::from_property_callback_info(info);
472      (F::get())(scope, key, args, rv);
473    };
474    f.to_c_fn()
475  }
476}
477
478pub(crate) type NamedGetterCallback = unsafe extern "C" fn(
479  SealedLocal<Name>,
480  *const PropertyCallbackInfo<Value>,
481) -> Intercepted;
482
483impl<F> MapFnFrom<F> for NamedGetterCallback
484where
485  F: UnitType
486    + for<'s, 'i> Fn(
487      &mut PinScope<'s, 'i>,
488      Local<'s, Name>,
489      PropertyCallbackArguments<'s>,
490      ReturnValue<Value>,
491    ) -> Intercepted,
492{
493  fn mapping() -> Self {
494    let f = |key: SealedLocal<Name>,
495             info: *const PropertyCallbackInfo<Value>| {
496      let info = unsafe { &*info };
497      callback_scope!(unsafe scope, info);
498      let key = unsafe { scope.unseal(key) };
499      let args = PropertyCallbackArguments::from_property_callback_info(info);
500      let rv = ReturnValue::from_property_callback_info(info);
501      (F::get())(scope, key, args, rv)
502    };
503    f.to_c_fn()
504  }
505}
506
507pub(crate) type NamedQueryCallback = unsafe extern "C" fn(
508  SealedLocal<Name>,
509  *const PropertyCallbackInfo<Integer>,
510) -> Intercepted;
511
512impl<F> MapFnFrom<F> for NamedQueryCallback
513where
514  F: UnitType
515    + for<'s, 'i> Fn(
516      &mut PinScope<'s, 'i>,
517      Local<'s, Name>,
518      PropertyCallbackArguments<'s>,
519      ReturnValue<Integer>,
520    ) -> Intercepted,
521{
522  fn mapping() -> Self {
523    let f = |key: SealedLocal<Name>,
524             info: *const PropertyCallbackInfo<Integer>| {
525      let info = unsafe { &*info };
526      callback_scope!(unsafe scope, info);
527      let key = unsafe { scope.unseal(key) };
528      let args = PropertyCallbackArguments::from_property_callback_info(info);
529      let rv = ReturnValue::from_property_callback_info(info);
530      (F::get())(scope, key, args, rv)
531    };
532    f.to_c_fn()
533  }
534}
535
536pub(crate) type NamedSetterCallbackForAccessor = unsafe extern "C" fn(
537  SealedLocal<Name>,
538  SealedLocal<Value>,
539  *const PropertyCallbackInfo<()>,
540);
541
542impl<F> MapFnFrom<F> for NamedSetterCallbackForAccessor
543where
544  F: UnitType
545    + for<'s, 'i> Fn(
546      &mut PinScope<'s, 'i>,
547      Local<'s, Name>,
548      Local<'s, Value>,
549      PropertyCallbackArguments<'s>,
550      ReturnValue<()>,
551    ),
552{
553  fn mapping() -> Self {
554    let f = |key: SealedLocal<Name>,
555             value: SealedLocal<Value>,
556             info: *const PropertyCallbackInfo<()>| {
557      let info = unsafe { &*info };
558      callback_scope!(unsafe scope, info);
559      let key = unsafe { scope.unseal(key) };
560      let value = unsafe { scope.unseal(value) };
561      let args = PropertyCallbackArguments::from_property_callback_info(info);
562      let rv = ReturnValue::from_property_callback_info(info);
563      (F::get())(scope, key, value, args, rv);
564    };
565    f.to_c_fn()
566  }
567}
568
569pub(crate) type NamedSetterCallback = unsafe extern "C" fn(
570  SealedLocal<Name>,
571  SealedLocal<Value>,
572  *const PropertyCallbackInfo<()>,
573) -> Intercepted;
574
575impl<F> MapFnFrom<F> for NamedSetterCallback
576where
577  F: UnitType
578    + for<'s, 'i> Fn(
579      &mut PinScope<'s, 'i>,
580      Local<'s, Name>,
581      Local<'s, Value>,
582      PropertyCallbackArguments<'s>,
583      ReturnValue<()>,
584    ) -> Intercepted,
585{
586  fn mapping() -> Self {
587    let f = |key: SealedLocal<Name>,
588             value: SealedLocal<Value>,
589             info: *const PropertyCallbackInfo<()>| {
590      let info = unsafe { &*info };
591      callback_scope!(unsafe scope, info);
592      let key = unsafe { scope.unseal(key) };
593      let value = unsafe { scope.unseal(value) };
594      let args = PropertyCallbackArguments::from_property_callback_info(info);
595      let rv = ReturnValue::from_property_callback_info(info);
596      (F::get())(scope, key, value, args, rv)
597    };
598    f.to_c_fn()
599  }
600}
601
602// Should return an Array in Return Value
603pub(crate) type PropertyEnumeratorCallback =
604  unsafe extern "C" fn(*const PropertyCallbackInfo<Array>);
605
606impl<F> MapFnFrom<F> for PropertyEnumeratorCallback
607where
608  F: UnitType
609    + for<'s, 'i> Fn(
610      &mut PinScope<'s, 'i>,
611      PropertyCallbackArguments<'s>,
612      ReturnValue<Array>,
613    ),
614{
615  fn mapping() -> Self {
616    let f = |info: *const PropertyCallbackInfo<Array>| {
617      let info = unsafe { &*info };
618      callback_scope!(unsafe scope, info);
619      let args = PropertyCallbackArguments::from_property_callback_info(info);
620      let rv = ReturnValue::from_property_callback_info(info);
621      (F::get())(scope, args, rv);
622    };
623    f.to_c_fn()
624  }
625}
626
627pub(crate) type NamedDefinerCallback = unsafe extern "C" fn(
628  SealedLocal<Name>,
629  *const PropertyDescriptor,
630  *const PropertyCallbackInfo<()>,
631) -> Intercepted;
632
633impl<F> MapFnFrom<F> for NamedDefinerCallback
634where
635  F: UnitType
636    + for<'s, 'i> Fn(
637      &mut PinScope<'s, 'i>,
638      Local<'s, Name>,
639      &PropertyDescriptor,
640      PropertyCallbackArguments<'s>,
641      ReturnValue<()>,
642    ) -> Intercepted,
643{
644  fn mapping() -> Self {
645    let f = |key: SealedLocal<Name>,
646             desc: *const PropertyDescriptor,
647             info: *const PropertyCallbackInfo<()>| {
648      let info = unsafe { &*info };
649      callback_scope!(unsafe scope, info);
650      let key = unsafe { scope.unseal(key) };
651      let args = PropertyCallbackArguments::from_property_callback_info(info);
652      let desc = unsafe { &*desc };
653      let rv = ReturnValue::from_property_callback_info(info);
654      (F::get())(scope, key, desc, args, rv)
655    };
656    f.to_c_fn()
657  }
658}
659
660pub(crate) type NamedDeleterCallback = unsafe extern "C" fn(
661  SealedLocal<Name>,
662  *const PropertyCallbackInfo<Boolean>,
663) -> Intercepted;
664
665impl<F> MapFnFrom<F> for NamedDeleterCallback
666where
667  F: UnitType
668    + for<'s, 'i> Fn(
669      &mut PinScope<'s, 'i>,
670      Local<'s, Name>,
671      PropertyCallbackArguments<'s>,
672      ReturnValue<Boolean>,
673    ) -> Intercepted,
674{
675  fn mapping() -> Self {
676    let f = |key: SealedLocal<Name>,
677             info: *const PropertyCallbackInfo<Boolean>| {
678      let info = unsafe { &*info };
679      callback_scope!(unsafe scope, info);
680      let key = unsafe { scope.unseal(key) };
681      let args = PropertyCallbackArguments::from_property_callback_info(info);
682      let rv = ReturnValue::from_property_callback_info(info);
683      (F::get())(scope, key, args, rv)
684    };
685    f.to_c_fn()
686  }
687}
688
689pub(crate) type IndexedGetterCallback =
690  unsafe extern "C" fn(u32, *const PropertyCallbackInfo<Value>) -> Intercepted;
691
692impl<F> MapFnFrom<F> for IndexedGetterCallback
693where
694  F: UnitType
695    + for<'s, 'i> Fn(
696      &mut PinScope<'s, 'i>,
697      u32,
698      PropertyCallbackArguments<'s>,
699      ReturnValue<Value>,
700    ) -> Intercepted,
701{
702  fn mapping() -> Self {
703    let f = |index: u32, info: *const PropertyCallbackInfo<Value>| {
704      let info = unsafe { &*info };
705      callback_scope!(unsafe scope, info);
706      let args = PropertyCallbackArguments::from_property_callback_info(info);
707      let rv = ReturnValue::from_property_callback_info(info);
708      (F::get())(scope, index, args, rv)
709    };
710    f.to_c_fn()
711  }
712}
713
714pub(crate) type IndexedQueryCallback = unsafe extern "C" fn(
715  u32,
716  *const PropertyCallbackInfo<Integer>,
717) -> Intercepted;
718
719impl<F> MapFnFrom<F> for IndexedQueryCallback
720where
721  F: UnitType
722    + for<'s, 'i> Fn(
723      &mut PinScope<'s, 'i>,
724      u32,
725      PropertyCallbackArguments<'s>,
726      ReturnValue<Integer>,
727    ) -> Intercepted,
728{
729  fn mapping() -> Self {
730    let f = |key: u32, info: *const PropertyCallbackInfo<Integer>| {
731      let info = unsafe { &*info };
732      callback_scope!(unsafe scope, info);
733      let args = PropertyCallbackArguments::from_property_callback_info(info);
734      let rv = ReturnValue::from_property_callback_info(info);
735      (F::get())(scope, key, args, rv)
736    };
737    f.to_c_fn()
738  }
739}
740
741pub(crate) type IndexedSetterCallback = unsafe extern "C" fn(
742  u32,
743  SealedLocal<Value>,
744  *const PropertyCallbackInfo<()>,
745) -> Intercepted;
746
747impl<F> MapFnFrom<F> for IndexedSetterCallback
748where
749  F: UnitType
750    + for<'s, 'i> Fn(
751      &mut PinScope<'s, 'i>,
752      u32,
753      Local<'s, Value>,
754      PropertyCallbackArguments<'s>,
755      ReturnValue<()>,
756    ) -> Intercepted,
757{
758  fn mapping() -> Self {
759    let f = |index: u32,
760             value: SealedLocal<Value>,
761             info: *const PropertyCallbackInfo<()>| {
762      let info = unsafe { &*info };
763      callback_scope!(unsafe scope, info);
764      let value = unsafe { scope.unseal(value) };
765      let args = PropertyCallbackArguments::from_property_callback_info(info);
766      let rv = ReturnValue::from_property_callback_info(info);
767      (F::get())(scope, index, value, args, rv)
768    };
769    f.to_c_fn()
770  }
771}
772
773pub(crate) type IndexedDefinerCallback = unsafe extern "C" fn(
774  u32,
775  *const PropertyDescriptor,
776  *const PropertyCallbackInfo<()>,
777) -> Intercepted;
778
779impl<F> MapFnFrom<F> for IndexedDefinerCallback
780where
781  F: UnitType
782    + for<'s, 'i> Fn(
783      &mut PinScope<'s, 'i>,
784      u32,
785      &PropertyDescriptor,
786      PropertyCallbackArguments<'s>,
787      ReturnValue<()>,
788    ) -> Intercepted,
789{
790  fn mapping() -> Self {
791    let f = |index: u32,
792             desc: *const PropertyDescriptor,
793             info: *const PropertyCallbackInfo<()>| {
794      let info = unsafe { &*info };
795      callback_scope!(unsafe scope, info);
796      let args = PropertyCallbackArguments::from_property_callback_info(info);
797      let rv = ReturnValue::from_property_callback_info(info);
798      let desc = unsafe { &*desc };
799      (F::get())(scope, index, desc, args, rv)
800    };
801    f.to_c_fn()
802  }
803}
804
805pub(crate) type IndexedDeleterCallback = unsafe extern "C" fn(
806  u32,
807  *const PropertyCallbackInfo<Boolean>,
808) -> Intercepted;
809
810impl<F> MapFnFrom<F> for IndexedDeleterCallback
811where
812  F: UnitType
813    + for<'s, 'i> Fn(
814      &mut PinScope<'s, 'i>,
815      u32,
816      PropertyCallbackArguments<'s>,
817      ReturnValue<Boolean>,
818    ) -> Intercepted,
819{
820  fn mapping() -> Self {
821    let f = |index: u32, info: *const PropertyCallbackInfo<Boolean>| {
822      let info = unsafe { &*info };
823      callback_scope!(unsafe scope, info);
824      let args = PropertyCallbackArguments::from_property_callback_info(info);
825      let rv = ReturnValue::from_property_callback_info(info);
826      (F::get())(scope, index, args, rv)
827    };
828    f.to_c_fn()
829  }
830}
831
832/// A builder to construct the properties of a Function or FunctionTemplate.
833pub struct FunctionBuilder<'s, T> {
834  pub(crate) callback: FunctionCallback,
835  pub(crate) data: Option<Local<'s, Value>>,
836  pub(crate) signature: Option<Local<'s, Signature>>,
837  pub(crate) length: i32,
838  pub(crate) constructor_behavior: ConstructorBehavior,
839  pub(crate) side_effect_type: SideEffectType,
840  phantom: PhantomData<T>,
841}
842
843impl<'s, T> FunctionBuilder<'s, T> {
844  /// Create a new FunctionBuilder.
845  #[inline(always)]
846  pub fn new(callback: impl MapFnTo<FunctionCallback>) -> Self {
847    Self::new_raw(callback.map_fn_to())
848  }
849
850  #[inline(always)]
851  pub fn new_raw(callback: FunctionCallback) -> Self {
852    Self {
853      callback,
854      data: None,
855      signature: None,
856      length: 0,
857      constructor_behavior: ConstructorBehavior::Allow,
858      side_effect_type: SideEffectType::HasSideEffect,
859      phantom: PhantomData,
860    }
861  }
862
863  /// Set the associated data. The default is no associated data.
864  #[inline(always)]
865  pub fn data(mut self, data: Local<'s, Value>) -> Self {
866    self.data = Some(data);
867    self
868  }
869
870  /// Set the function length. The default is 0.
871  #[inline(always)]
872  pub fn length(mut self, length: i32) -> Self {
873    self.length = length;
874    self
875  }
876
877  /// Set the constructor behavior. The default is ConstructorBehavior::Allow.
878  #[inline(always)]
879  pub fn constructor_behavior(
880    mut self,
881    constructor_behavior: ConstructorBehavior,
882  ) -> Self {
883    self.constructor_behavior = constructor_behavior;
884    self
885  }
886
887  /// Set the side effect type. The default is SideEffectType::HasSideEffect.
888  #[inline(always)]
889  pub fn side_effect_type(mut self, side_effect_type: SideEffectType) -> Self {
890    self.side_effect_type = side_effect_type;
891    self
892  }
893}
894
895impl<'s> FunctionBuilder<'s, Function> {
896  /// Create the function in the current execution context.
897  #[inline(always)]
898  pub fn build<'i>(
899    self,
900    scope: &PinScope<'s, 'i>,
901  ) -> Option<Local<'s, Function>> {
902    unsafe {
903      scope.cast_local(|sd| {
904        v8__Function__New(
905          sd.get_current_context(),
906          self.callback,
907          self.data.map_or_else(null, |p| &*p),
908          self.length,
909          self.constructor_behavior,
910          self.side_effect_type,
911        )
912      })
913    }
914  }
915}
916
917impl Function {
918  /// Create a FunctionBuilder to configure a Function.
919  /// This is the same as FunctionBuilder::<Function>::new().
920  #[inline(always)]
921  pub fn builder<'s>(
922    callback: impl MapFnTo<FunctionCallback>,
923  ) -> FunctionBuilder<'s, Self> {
924    FunctionBuilder::new(callback)
925  }
926
927  #[inline(always)]
928  pub fn builder_raw<'s>(
929    callback: FunctionCallback,
930  ) -> FunctionBuilder<'s, Self> {
931    FunctionBuilder::new_raw(callback)
932  }
933
934  /// Create a function in the current execution context
935  /// for a given FunctionCallback.
936  #[inline(always)]
937  pub fn new<'s>(
938    scope: &mut PinScope<'s, '_>,
939    callback: impl MapFnTo<FunctionCallback>,
940  ) -> Option<Local<'s, Function>> {
941    Self::builder(callback).build(scope)
942  }
943
944  #[inline(always)]
945  pub fn new_raw<'s>(
946    scope: &mut PinScope<'s, '_>,
947    callback: FunctionCallback,
948  ) -> Option<Local<'s, Function>> {
949    Self::builder_raw(callback).build(scope)
950  }
951
952  /// Call a function in a context scope.
953  #[inline]
954  pub fn call<'s>(
955    &self,
956    scope: &PinScope<'s, '_>,
957    recv: Local<Value>,
958    args: &[Local<Value>],
959  ) -> Option<Local<'s, Value>> {
960    let args = Local::slice_into_raw(args);
961    let argc = int::try_from(args.len()).unwrap();
962    let argv = args.as_ptr();
963    unsafe {
964      scope.cast_local(|sd| {
965        v8__Function__Call(self, sd.get_current_context(), &*recv, argc, argv)
966      })
967    }
968  }
969
970  /// Call a function in a given context.
971  #[inline]
972  pub fn call_with_context<'s>(
973    &self,
974    scope: &PinScope<'s, '_, ()>,
975    context: Local<Context>,
976    recv: Local<Value>,
977    args: &[Local<Value>],
978  ) -> Option<Local<'s, Value>> {
979    let args = Local::slice_into_raw(args);
980    let argc = int::try_from(args.len()).unwrap();
981    let argv = args.as_ptr();
982    unsafe {
983      let ret = v8__Function__Call(
984        self,
985        context.as_non_null().as_ptr(),
986        &*recv,
987        argc,
988        argv,
989      );
990      if ret.is_null() {
991        None
992      } else {
993        scope.cast_local(|_| ret)
994      }
995    }
996  }
997
998  #[inline(always)]
999  pub fn new_instance<'s>(
1000    &self,
1001    scope: &PinScope<'s, '_>,
1002    args: &[Local<Value>],
1003  ) -> Option<Local<'s, Object>> {
1004    let args = Local::slice_into_raw(args);
1005    let argc = int::try_from(args.len()).unwrap();
1006    let argv = args.as_ptr();
1007    unsafe {
1008      scope.cast_local(|sd| {
1009        v8__Function__NewInstance(self, sd.get_current_context(), argc, argv)
1010      })
1011    }
1012  }
1013
1014  #[inline(always)]
1015  pub fn get_name<'s>(&self, scope: &PinScope<'s, '_>) -> Local<'s, String> {
1016    unsafe { scope.cast_local(|_| v8__Function__GetName(self)).unwrap() }
1017  }
1018
1019  #[inline(always)]
1020  pub fn set_name(&self, name: Local<String>) {
1021    unsafe { v8__Function__SetName(self, &*name) }
1022  }
1023
1024  /// Get the (zero-indexed) column number of the function's definition, if available.
1025  #[inline(always)]
1026  pub fn get_script_column_number(&self) -> Option<u32> {
1027    let ret = unsafe { v8__Function__GetScriptColumnNumber(self) };
1028    (ret >= 0).then_some(ret as u32)
1029  }
1030
1031  /// Get the (zero-indexed) line number of the function's definition, if available.
1032  #[inline(always)]
1033  pub fn get_script_line_number(&self) -> Option<u32> {
1034    let ret = unsafe { v8__Function__GetScriptLineNumber(self) };
1035    (ret >= 0).then_some(ret as u32)
1036  }
1037
1038  #[inline(always)]
1039  pub fn get_script_origin(&self) -> &ScriptOrigin<'_> {
1040    unsafe {
1041      let ptr = v8__Function__GetScriptOrigin(self);
1042      &*ptr
1043    }
1044  }
1045
1046  /// Returns scriptId.
1047  #[inline(always)]
1048  pub fn script_id(&self) -> i32 {
1049    unsafe { v8__Function__ScriptId(self) }
1050  }
1051
1052  /// Creates and returns code cache for the specified unbound_script.
1053  /// This will return nullptr if the script cannot be serialized. The
1054  /// CachedData returned by this function should be owned by the caller.
1055  #[inline(always)]
1056  pub fn create_code_cache(&self) -> Option<UniqueRef<CachedData<'static>>> {
1057    let code_cache =
1058      unsafe { UniqueRef::try_from_raw(v8__Function__CreateCodeCache(self)) };
1059    if let Some(code_cache) = &code_cache {
1060      debug_assert_eq!(
1061        code_cache.buffer_policy(),
1062        crate::script_compiler::BufferPolicy::BufferOwned
1063      );
1064    }
1065    code_cache
1066  }
1067}