Skip to main content

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