Skip to main content

v8/
function.rs

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