[+] v8::Function::Bind(Local<Object> that, Local<Array> bound_args)

This commit is contained in:
Reece Wilson 2022-09-04 17:09:45 +01:00
parent 4882edfeee
commit 07e2139b4f
2 changed files with 49 additions and 0 deletions

View File

@ -51,6 +51,13 @@ class V8_EXPORT Function : public Object {
Local<Context> context, int argc, Local<Value> argv[], Local<Context> context, int argc, Local<Value> argv[],
SideEffectType side_effect_type = SideEffectType::kHasSideEffect) const; SideEffectType side_effect_type = SideEffectType::kHasSideEffect) const;
/**
* Returns a bound function. Roughly equivalent to JS's function.prototype.bind,
* where that and/or bound_args must be specified over variadic (this, ...args)
*/
V8_WARN_UNUSED_RESULT MaybeLocal<Function> Bind(
Local<Object> that, Local<Array> bound_args);
V8_WARN_UNUSED_RESULT MaybeLocal<Value> Call(Local<Context> context, V8_WARN_UNUSED_RESULT MaybeLocal<Value> Call(Local<Context> context,
Local<Value> recv, int argc, Local<Value> recv, int argc,
Local<Value> argv[]); Local<Value> argv[]);

View File

@ -5143,6 +5143,48 @@ MaybeLocal<Object> Function::NewInstanceWithSideEffectType(
RETURN_ESCAPED(result); RETURN_ESCAPED(result);
} }
MaybeLocal<Function> Function::Bind(v8::Local<v8::Object> that,
v8::Local<v8::Array> bound_args) {
i::Handle<i::JSReceiver> self;
i::Handle<i::Object> that_obj;
v8::Isolate* isolate = this->GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
if (that.IsEmpty()) {
Utils::ApiCheck(!bound_args.IsEmpty(),
"Function::Bind",
"A that argument and/or an array of argument values must be specified");
// xref: `TorqueGeneratedJSBoundFunction<D, P>::set_bound_this` (+1 line)
// `bound_this.IsNullOrUndefined`
// specifying undefined is acceptable; replace an empty "that" local with undefined
that_obj = Utils::OpenHandle(*v8::Undefined(isolate));
} else {
that_obj = Utils::OpenHandle(*that);
}
self = Utils::OpenHandle(this);
// derive a base vector of internal object handles by unwrapping an optional v8::Array
base::ScopedVector<i::Handle<i::Object>> argv(bound_args.IsEmpty() ? 0 : bound_args->Length());
if (!bound_args.IsEmpty()) {
for (int i = 0; i < bound_args->Length(); ++i) {
MaybeLocal<Value> arg = bound_args->Get(isolate->GetCurrentContext(), i);
CHECK(!arg.IsEmpty());
argv[i] = Utils::OpenHandle(*arg.ToLocalChecked());
}
}
i::MaybeHandle<i::JSBoundFunction> bound_function =
i_isolate->factory()->NewJSBoundFunction(self, that_obj, argv);
if (bound_function.is_null()) {
return {};
}
return ToApiHandle<Function>(bound_function.ToHandleChecked());
}
MaybeLocal<v8::Value> Function::Call(Local<Context> context, MaybeLocal<v8::Value> Function::Call(Local<Context> context,
v8::Local<v8::Value> recv, int argc, v8::Local<v8::Value> recv, int argc,
v8::Local<v8::Value> argv[]) { v8::Local<v8::Value> argv[]) {