Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,13 @@ void v8__ObjectTemplate__SetImmutableProto(const v8::ObjectTemplate& self) {
return ptr_to_local(&self)->SetImmutableProto();
}

void v8__ObjectTemplate__SetCallAsFunctionHandler(
const v8::ObjectTemplate& self, v8::FunctionCallback callback,
const v8::Value* data_or_null) {
ptr_to_local(&self)->SetCallAsFunctionHandler(callback,
ptr_to_local(data_or_null));
}

const v8::Object* v8__Object__New(v8::Isolate* isolate) {
return local_to_ptr(v8::Object::New(isolate));
}
Expand Down Expand Up @@ -1743,6 +1750,31 @@ const v8::Array* v8__Object__PreviewEntries(const v8::Object& self,
return maybe_local_to_ptr(ptr_to_local(&self)->PreviewEntries(is_key_value));
}

const bool v8__Object__IsCallable(const v8::Object& self) {
return ptr_to_local(&self)->IsCallable();
}

const bool v8__Object__IsConstructor(const v8::Object& self) {
return ptr_to_local(&self)->IsConstructor();
}

const v8::Value* v8__Object__CallAsFunction(const v8::Object& self,
const v8::Context& context,
const v8::Value& recv, int argc,
const v8::Value* const argv[]) {
return maybe_local_to_ptr(ptr_to_local(&self)->CallAsFunction(
ptr_to_local(&context), ptr_to_local(&recv), argc,
const_ptr_array_to_local_array(argv)));
}

const v8::Value* v8__Object__CallAsConstructor(const v8::Object& self,
const v8::Context& context,
int argc,
const v8::Value* const argv[]) {
return maybe_local_to_ptr(ptr_to_local(&self)->CallAsConstructor(
ptr_to_local(&context), argc, const_ptr_array_to_local_array(argv)));
}

const v8::Array* v8__Array__New(v8::Isolate* isolate, int length) {
return local_to_ptr(v8::Array::New(isolate, length));
}
Expand Down
147 changes: 147 additions & 0 deletions src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,21 @@ unsafe extern "C" {
tag: u16,
) -> *mut RustObj;
fn v8__Object__IsApiWrapper(this: *const Object) -> bool;
fn v8__Object__IsCallable(this: *const Object) -> bool;
fn v8___Object__IsConstructor(this: *const Object) -> bool;
fn v8__Object__CallAsFunction(
this: *const Object,
context: *const Context,
recv: *const Value,
argc: int,
argv: *const *const Value,
) -> *const Value;
fn v8__Object__CallAsConstructor(
this: *const Object,
context: *const Context,
argc: int,
argv: *const *const Value,
) -> *const Value;

fn v8__Array__New(isolate: *mut RealIsolate, length: int) -> *const Array;
fn v8__Array__New_with_elements(
Expand Down Expand Up @@ -1031,6 +1046,138 @@ impl Object {
}
out.into()
}

/// When this Object is callable, this method returns `true`.
///
/// Certain exotic objects may be callable despite not being
/// [`Function`](crate::Function)s, such as [`Proxy`](crate::Proxy), or other
/// objects with a `[[Call]]` internal method. Callable objects can be created
/// via
/// [`ObjectTemplate::set_call_as_function_handler`](crate::ObjectTemplate::set_call_as_function_handler).
#[must_use = "this is a pure method"]
#[inline(always)]
pub fn is_callable(&self) -> bool {
unsafe { v8__Object__IsCallable(self) }
}

/// When this Object can be called as a constructor, this method returns
/// `true`.
#[must_use = "this is a pure method"]
#[inline(always)]
pub fn is_constructor(&self) -> bool {
unsafe { v8___Object__IsConstructor(self) }
}

/// Calls the [`Object`] as a function with the provided `this` argument and
/// arguments.
///
/// For more information, see [`Object::is_callable()`].
#[inline]
pub fn call_as_function<'s>(
&self,
scope: &PinScope<'s, '_>,
recv: Local<'_, Value>,
args: &[Local<'_, Value>],
) -> Option<Local<'s, Value>> {
let args = Local::slice_into_raw(args);
let argc = int::try_from(args.len()).unwrap();
let argv = args.as_ptr();
unsafe {
scope.cast_local(|sd| {
v8__Object__CallAsFunction(
self,
sd.get_current_context(),
&*recv,
argc,
argv,
)
})
}
}

/// Calls the [`Object`] as a function in a given context.
///
/// For more information, see [`Object::is_callable()`].
#[inline]
pub fn call_as_function_with_context<'s>(
&self,
scope: &PinScope<'s, '_, ()>,
context: Local<'_, Context>,
recv: Local<'_, Value>,
args: &[Local<'_, Value>],
) -> Option<Local<'s, Value>> {
let args = Local::slice_into_raw(args);
let argc = int::try_from(args.len()).unwrap();
let argv = args.as_ptr();
unsafe {
let ret = v8__Object__CallAsFunction(
self,
context.as_non_null().as_ptr(),
&*recv,
argc,
argv,
);
if ret.is_null() {
None
} else {
scope.cast_local(|_| ret)
}
}
}

/// Calls the [`Object`] as a constructor with the provided arguments.
/// This is similar to
/// [`Function::new_instance()`](crate::Function::new_instance).
///
/// For more information, see [`Object::is_constructor()`].
#[inline]
pub fn call_as_constructor<'s>(
&self,
scope: &PinScope<'s, '_>,
args: &[Local<'_, Value>],
) -> Option<Local<'s, Value>> {
let args = Local::slice_into_raw(args);
let argc = int::try_from(args.len()).unwrap();
let argv = args.as_ptr();
unsafe {
scope.cast_local(|sd| {
v8__Object__CallAsConstructor(
self,
sd.get_current_context(),
argc,
argv,
)
})
}
}

/// Calls the [`Object`] as a constructor in a given context.
///
/// For more information, see [`Object::is_constructor()`].
#[inline]
pub fn call_as_constructor_with_context<'s>(
&self,
scope: &PinScope<'s, '_, ()>,
context: Local<'_, Context>,
args: &[Local<'_, Value>],
) -> Option<Local<'s, Value>> {
let args = Local::slice_into_raw(args);
let argc = int::try_from(args.len()).unwrap();
let argv = args.as_ptr();
unsafe {
let ret = v8__Object__CallAsConstructor(
self,
context.as_non_null().as_ptr(),
argc,
argv,
);
if ret.is_null() {
None
} else {
scope.cast_local(|_| ret)
}
}
}
}

/// Object integrity levels can be used to restrict what can be done to an
Expand Down
26 changes: 26 additions & 0 deletions src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ unsafe extern "C" {
);

fn v8__ObjectTemplate__SetImmutableProto(this: *const ObjectTemplate);

fn v8__ObjecTemplate__SetCallAsFunctionHandler(
this: *const ObjectTemplate,
callback: FunctionCallback,
data_or_null: *const Value,
);
}

/// Interceptor callbacks use this value to indicate whether the request was
Expand Down Expand Up @@ -1016,4 +1022,24 @@ impl ObjectTemplate {
pub fn set_immutable_proto(&self) {
unsafe { v8__ObjectTemplate__SetImmutableProto(self) };
}

/// Sets the callback to be used when calling instances created from this
/// template as a function.
///
/// If no callback is set, instances behave like normal [`Object`]s that
/// cannot be called like [`Function`]s.
#[inline(always)]
pub fn set_call_as_function_handler(
&self,
callback: impl MapFnTo<FunctionCallback>,
data: Option<Local<'_, Value>>,
) {
unsafe {
v8__ObjecTemplate__SetCallAsFunctionHandler(
self,
callback.map_fn_to(),
data.map_or_else(null, |p| &*p),
);
}
}
}
Loading