1use std::convert::TryFrom;
2use std::marker::PhantomData;
3use std::ptr::null;
4
5use crate::scope::CallbackScope;
6use crate::support::MapFnFrom;
7use crate::support::MapFnTo;
8use crate::support::ToCFn;
9use crate::support::UnitType;
10use crate::support::{int, Opaque};
11use crate::Context;
12use crate::Function;
13use crate::HandleScope;
14use crate::Local;
15use crate::Name;
16use crate::Object;
17use crate::Signature;
18use crate::String;
19use crate::Value;
20
21extern "C" {
22 fn v8__Function__New(
23 context: *const Context,
24 callback: FunctionCallback,
25 data_or_null: *const Value,
26 length: i32,
27 constructor_behavior: ConstructorBehavior,
28 side_effect_type: SideEffectType,
29 ) -> *const Function;
30 fn v8__Function__Call(
31 this: *const Function,
32 context: *const Context,
33 recv: *const Value,
34 argc: int,
35 argv: *const *const Value,
36 ) -> *const Value;
37 fn v8__Function__NewInstance(
38 this: *const Function,
39 context: *const Context,
40 argc: int,
41 argv: *const *const Value,
42 ) -> *const Object;
43 fn v8__Function__GetName(this: *const Function) -> *const String;
44 fn v8__Function__SetName(this: *const Function, name: *const String);
45
46 fn v8__FunctionCallbackInfo__GetReturnValue(
47 info: *const FunctionCallbackInfo,
48 ) -> *mut Value;
49 fn v8__FunctionCallbackInfo__This(
50 this: *const FunctionCallbackInfo,
51 ) -> *const Object;
52 fn v8__FunctionCallbackInfo__Length(this: *const FunctionCallbackInfo)
53 -> int;
54 fn v8__FunctionCallbackInfo__GetArgument(
55 this: *const FunctionCallbackInfo,
56 i: int,
57 ) -> *const Value;
58 fn v8__FunctionCallbackInfo__Data(
59 this: *const FunctionCallbackInfo,
60 ) -> *const Value;
61
62 fn v8__PropertyCallbackInfo__GetReturnValue(
63 this: *const PropertyCallbackInfo,
64 ) -> *mut Value;
65 fn v8__PropertyCallbackInfo__This(
66 this: *const PropertyCallbackInfo,
67 ) -> *const Object;
68
69 fn v8__ReturnValue__Set(this: *mut ReturnValue, value: *const Value);
70 fn v8__ReturnValue__Get(this: *const ReturnValue) -> *const Value;
71}
72
73#[repr(C)]
81pub enum ConstructorBehavior {
82 Throw,
83 Allow,
84}
85
86#[repr(C)]
95pub enum SideEffectType {
96 HasSideEffect,
97 HasNoSideEffect,
98 HasSideEffectToReceiver,
99}
100
101#[repr(C)]
102#[derive(Default)]
103pub(crate) struct CFunction([usize; 2]);
104
105#[repr(C)]
109#[derive(Debug)]
110pub struct ReturnValue<'cb>(*mut Value, PhantomData<&'cb ()>);
111
112impl<'cb> ReturnValue<'cb> {
117 fn from_function_callback_info(info: *const FunctionCallbackInfo) -> Self {
118 let slot = unsafe { v8__FunctionCallbackInfo__GetReturnValue(info) };
119 Self(slot, PhantomData)
120 }
121
122 fn from_property_callback_info(info: *const PropertyCallbackInfo) -> Self {
123 let slot = unsafe { v8__PropertyCallbackInfo__GetReturnValue(info) };
124 Self(slot, PhantomData)
125 }
126
127 pub fn set(&mut self, value: Local<Value>) {
130 unsafe { v8__ReturnValue__Set(&mut *self, &*value) }
131 }
132
133 pub fn get<'s>(&self, scope: &mut HandleScope<'s>) -> Local<'s, Value> {
137 unsafe { scope.cast_local(|_| v8__ReturnValue__Get(self)) }.unwrap()
138 }
139}
140
141#[repr(C)]
146#[derive(Debug)]
147pub struct FunctionCallbackInfo {
148 implicit_args: *mut Opaque,
151 values: *const Value,
152 length: int,
153}
154
155#[repr(C)]
158#[derive(Debug)]
159pub struct PropertyCallbackInfo {
160 args: *mut Opaque,
163}
164
165#[derive(Debug)]
166pub struct FunctionCallbackArguments<'s> {
167 info: *const FunctionCallbackInfo,
168 phantom: PhantomData<&'s ()>,
169}
170
171impl<'s> FunctionCallbackArguments<'s> {
172 pub(crate) fn from_function_callback_info(
173 info: *const FunctionCallbackInfo,
174 ) -> Self {
175 Self {
176 info,
177 phantom: PhantomData,
178 }
179 }
180
181 pub fn this(&self) -> Local<'s, Object> {
183 unsafe {
184 Local::from_raw(v8__FunctionCallbackInfo__This(self.info)).unwrap()
185 }
186 }
187
188 pub fn data(&self) -> Option<Local<'s, Value>> {
190 unsafe { Local::from_raw(v8__FunctionCallbackInfo__Data(self.info)) }
191 }
192
193 pub fn length(&self) -> int {
195 unsafe {
196 let length = (*self.info).length;
197 debug_assert_eq!(length, v8__FunctionCallbackInfo__Length(self.info));
198 length
199 }
200 }
201
202 pub fn get(&self, i: int) -> Local<'s, Value> {
205 unsafe {
206 Local::from_raw(v8__FunctionCallbackInfo__GetArgument(self.info, i))
207 .unwrap()
208 }
209 }
210}
211
212#[derive(Debug)]
213pub struct PropertyCallbackArguments<'s> {
214 info: *const PropertyCallbackInfo,
215 phantom: PhantomData<&'s ()>,
216}
217
218impl<'s> PropertyCallbackArguments<'s> {
219 pub(crate) fn from_property_callback_info(
220 info: *const PropertyCallbackInfo,
221 ) -> Self {
222 Self {
223 info,
224 phantom: PhantomData,
225 }
226 }
227
228 pub fn this(&self) -> Local<'s, Object> {
268 unsafe {
269 Local::from_raw(v8__PropertyCallbackInfo__This(self.info)).unwrap()
270 }
271 }
272}
273
274pub type FunctionCallback = extern "C" fn(*const FunctionCallbackInfo);
275
276impl<F> MapFnFrom<F> for FunctionCallback
277where
278 F: UnitType + Fn(&mut HandleScope, FunctionCallbackArguments, ReturnValue),
279{
280 fn mapping() -> Self {
281 let f = |info: *const FunctionCallbackInfo| {
282 let scope = &mut unsafe { CallbackScope::new(&*info) };
283 let args = FunctionCallbackArguments::from_function_callback_info(info);
284 let rv = ReturnValue::from_function_callback_info(info);
285 (F::get())(scope, args, rv);
286 };
287 f.to_c_fn()
288 }
289}
290
291pub type AccessorNameGetterCallback<'s> =
294 extern "C" fn(Local<'s, Name>, *const PropertyCallbackInfo);
295
296impl<F> MapFnFrom<F> for AccessorNameGetterCallback<'_>
297where
298 F: UnitType
299 + Fn(&mut HandleScope, Local<Name>, PropertyCallbackArguments, ReturnValue),
300{
301 fn mapping() -> Self {
302 let f = |key: Local<Name>, info: *const PropertyCallbackInfo| {
303 let scope = &mut unsafe { CallbackScope::new(&*info) };
304 let args = PropertyCallbackArguments::from_property_callback_info(info);
305 let rv = ReturnValue::from_property_callback_info(info);
306 (F::get())(scope, key, args, rv);
307 };
308 f.to_c_fn()
309 }
310}
311
312pub type AccessorNameSetterCallback<'s> =
313 extern "C" fn(Local<'s, Name>, Local<'s, Value>, *const PropertyCallbackInfo);
314
315impl<F> MapFnFrom<F> for AccessorNameSetterCallback<'_>
316where
317 F: UnitType
318 + Fn(&mut HandleScope, Local<Name>, Local<Value>, PropertyCallbackArguments),
319{
320 fn mapping() -> Self {
321 let f = |key: Local<Name>,
322 value: Local<Value>,
323 info: *const PropertyCallbackInfo| {
324 let scope = &mut unsafe { CallbackScope::new(&*info) };
325 let args = PropertyCallbackArguments::from_property_callback_info(info);
326 (F::get())(scope, key, value, args);
327 };
328 f.to_c_fn()
329 }
330}
331
332pub struct FunctionBuilder<'s, T> {
334 pub(crate) callback: FunctionCallback,
335 pub(crate) data: Option<Local<'s, Value>>,
336 pub(crate) signature: Option<Local<'s, Signature>>,
337 pub(crate) length: i32,
338 pub(crate) constructor_behavior: ConstructorBehavior,
339 pub(crate) side_effect_type: SideEffectType,
340 phantom: PhantomData<T>,
341}
342
343impl<'s, T> FunctionBuilder<'s, T> {
344 pub fn new(callback: impl MapFnTo<FunctionCallback>) -> Self {
346 Self {
347 callback: callback.map_fn_to(),
348 data: None,
349 signature: None,
350 length: 0,
351 constructor_behavior: ConstructorBehavior::Allow,
352 side_effect_type: SideEffectType::HasSideEffect,
353 phantom: PhantomData,
354 }
355 }
356
357 pub fn data(mut self, data: Local<'s, Value>) -> Self {
359 self.data = Some(data);
360 self
361 }
362
363 pub fn length(mut self, length: i32) -> Self {
365 self.length = length;
366 self
367 }
368
369 pub fn constructor_behavior(
371 mut self,
372 constructor_behavior: ConstructorBehavior,
373 ) -> Self {
374 self.constructor_behavior = constructor_behavior;
375 self
376 }
377
378 pub fn side_effect_type(mut self, side_effect_type: SideEffectType) -> Self {
380 self.side_effect_type = side_effect_type;
381 self
382 }
383}
384
385impl<'s> FunctionBuilder<'s, Function> {
386 pub fn build(
388 self,
389 scope: &mut HandleScope<'s>,
390 ) -> Option<Local<'s, Function>> {
391 unsafe {
392 scope.cast_local(|sd| {
393 v8__Function__New(
394 sd.get_current_context(),
395 self.callback,
396 self.data.map_or_else(null, |p| &*p),
397 self.length,
398 self.constructor_behavior,
399 self.side_effect_type,
400 )
401 })
402 }
403 }
404}
405
406impl Function {
407 pub fn builder<'s>(
410 callback: impl MapFnTo<FunctionCallback>,
411 ) -> FunctionBuilder<'s, Self> {
412 FunctionBuilder::new(callback)
413 }
414
415 pub fn new<'s>(
418 scope: &mut HandleScope<'s>,
419 callback: impl MapFnTo<FunctionCallback>,
420 ) -> Option<Local<'s, Function>> {
421 Self::builder(callback).build(scope)
422 }
423
424 pub fn call<'s>(
425 &self,
426 scope: &mut HandleScope<'s>,
427 recv: Local<Value>,
428 args: &[Local<Value>],
429 ) -> Option<Local<'s, Value>> {
430 let args = Local::slice_into_raw(args);
431 let argc = int::try_from(args.len()).unwrap();
432 let argv = args.as_ptr();
433 unsafe {
434 scope.cast_local(|sd| {
435 v8__Function__Call(self, sd.get_current_context(), &*recv, argc, argv)
436 })
437 }
438 }
439
440 pub fn new_instance<'s>(
441 &self,
442 scope: &mut HandleScope<'s>,
443 args: &[Local<Value>],
444 ) -> Option<Local<'s, Object>> {
445 let args = Local::slice_into_raw(args);
446 let argc = int::try_from(args.len()).unwrap();
447 let argv = args.as_ptr();
448 unsafe {
449 scope.cast_local(|sd| {
450 v8__Function__NewInstance(self, sd.get_current_context(), argc, argv)
451 })
452 }
453 }
454
455 pub fn get_name<'s>(&self, scope: &mut HandleScope<'s>) -> Local<'s, String> {
456 unsafe { scope.cast_local(|_| v8__Function__GetName(self)).unwrap() }
457 }
458
459 pub fn set_name(&self, name: Local<String>) {
460 unsafe { v8__Function__SetName(self, &*name) }
461 }
462}