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