115 lines
5.1 KiB
Diff
115 lines
5.1 KiB
Diff
|
9fb02b526f1cd3b859a530a01adb08bc0d089f4f
|
||
|
diff --git a/src/builtins/builtins-api.cc b/src/builtins/builtins-api.cc
|
||
|
index 7e2d3e219e..c26c1a9fd1 100644
|
||
|
--- a/src/builtins/builtins-api.cc
|
||
|
+++ b/src/builtins/builtins-api.cc
|
||
|
@@ -22,17 +22,21 @@ namespace {
|
||
|
// Returns the holder JSObject if the function can legally be called with this
|
||
|
// receiver. Returns nullptr if the call is illegal.
|
||
|
// TODO(dcarney): CallOptimization duplicates this logic, merge.
|
||
|
-JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
|
||
|
- JSObject* receiver) {
|
||
|
+JSReceiver* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
|
||
|
+ JSReceiver* receiver) {
|
||
|
Object* recv_type = info->signature();
|
||
|
// No signature, return holder.
|
||
|
if (!recv_type->IsFunctionTemplateInfo()) return receiver;
|
||
|
+ // A Proxy cannot have been created from the signature template.
|
||
|
+ if (!receiver->IsJSObject()) return nullptr;
|
||
|
+
|
||
|
+ JSObject* js_obj_receiver = JSObject::cast(receiver);
|
||
|
FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
|
||
|
|
||
|
// Check the receiver. Fast path for receivers with no hidden prototypes.
|
||
|
- if (signature->IsTemplateFor(receiver)) return receiver;
|
||
|
- if (!receiver->map()->has_hidden_prototype()) return nullptr;
|
||
|
- for (PrototypeIterator iter(isolate, receiver, kStartAtPrototype,
|
||
|
+ if (signature->IsTemplateFor(js_obj_receiver)) return receiver;
|
||
|
+ if (!js_obj_receiver->map()->has_hidden_prototype()) return nullptr;
|
||
|
+ for (PrototypeIterator iter(isolate, js_obj_receiver, kStartAtPrototype,
|
||
|
PrototypeIterator::END_AT_NON_HIDDEN);
|
||
|
!iter.IsAtEnd(); iter.Advance()) {
|
||
|
JSObject* current = iter.GetCurrent<JSObject>();
|
||
|
@@ -46,8 +50,8 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> HandleApiCallHelper(
|
||
|
Isolate* isolate, Handle<HeapObject> function,
|
||
|
Handle<HeapObject> new_target, Handle<FunctionTemplateInfo> fun_data,
|
||
|
Handle<Object> receiver, BuiltinArguments args) {
|
||
|
- Handle<JSObject> js_receiver;
|
||
|
- JSObject* raw_holder;
|
||
|
+ Handle<JSReceiver> js_receiver;
|
||
|
+ JSReceiver* raw_holder;
|
||
|
if (is_construct) {
|
||
|
DCHECK(args.receiver()->IsTheHole(isolate));
|
||
|
if (fun_data->instance_template()->IsUndefined(isolate)) {
|
||
|
@@ -69,21 +73,18 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> HandleApiCallHelper(
|
||
|
raw_holder = *js_receiver;
|
||
|
} else {
|
||
|
DCHECK(receiver->IsJSReceiver());
|
||
|
-
|
||
|
- if (!receiver->IsJSObject()) {
|
||
|
- // This function cannot be called with the given receiver. Abort!
|
||
|
- THROW_NEW_ERROR(
|
||
|
- isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
|
||
|
- }
|
||
|
-
|
||
|
- js_receiver = Handle<JSObject>::cast(receiver);
|
||
|
+ js_receiver = Handle<JSReceiver>::cast(receiver);
|
||
|
|
||
|
if (!fun_data->accept_any_receiver() &&
|
||
|
- js_receiver->IsAccessCheckNeeded() &&
|
||
|
- !isolate->MayAccess(handle(isolate->context()), js_receiver)) {
|
||
|
- isolate->ReportFailedAccessCheck(js_receiver);
|
||
|
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
||
|
- return isolate->factory()->undefined_value();
|
||
|
+ js_receiver->IsAccessCheckNeeded()) {
|
||
|
+ // Proxies never need access checks.
|
||
|
+ DCHECK(js_receiver->IsJSObject());
|
||
|
+ Handle<JSObject> js_obj_receiver = Handle<JSObject>::cast(js_receiver);
|
||
|
+ if (!isolate->MayAccess(handle(isolate->context()), js_obj_receiver)) {
|
||
|
+ isolate->ReportFailedAccessCheck(js_obj_receiver);
|
||
|
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
||
|
+ return isolate->factory()->undefined_value();
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
raw_holder = GetCompatibleReceiver(isolate, *fun_data, *js_receiver);
|
||
|
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
|
||
|
index 7887cbfa75..0605f439e5 100644
|
||
|
--- a/test/cctest/test-api.cc
|
||
|
+++ b/test/cctest/test-api.cc
|
||
|
@@ -1088,6 +1088,34 @@ THREADED_PROFILED_TEST(FunctionTemplate) {
|
||
|
TestFunctionTemplateAccessor(construct_callback, Return239Callback);
|
||
|
}
|
||
|
|
||
|
+static void FunctionCallbackForProxyTest(
|
||
|
+ const v8::FunctionCallbackInfo<Value>& info) {
|
||
|
+ info.GetReturnValue().Set(info.This());
|
||
|
+}
|
||
|
+
|
||
|
+THREADED_TEST(FunctionTemplateWithProxy) {
|
||
|
+ LocalContext env;
|
||
|
+ v8::Isolate* isolate = env->GetIsolate();
|
||
|
+ v8::HandleScope scope(isolate);
|
||
|
+
|
||
|
+ v8::Local<v8::FunctionTemplate> function_template =
|
||
|
+ v8::FunctionTemplate::New(isolate, FunctionCallbackForProxyTest);
|
||
|
+ v8::Local<v8::Function> function =
|
||
|
+ function_template->GetFunction(env.local()).ToLocalChecked();
|
||
|
+ CHECK((*env)->Global()->Set(env.local(), v8_str("f"), function).FromJust());
|
||
|
+ v8::Local<v8::Value> proxy =
|
||
|
+ CompileRun("var proxy = new Proxy({}, {}); proxy");
|
||
|
+ CHECK(proxy->IsProxy());
|
||
|
+
|
||
|
+ v8::Local<v8::Value> result = CompileRun("f(proxy)");
|
||
|
+ CHECK(result->Equals(env.local(), (*env)->Global()).FromJust());
|
||
|
+
|
||
|
+ result = CompileRun("f.call(proxy)");
|
||
|
+ CHECK(result->Equals(env.local(), proxy).FromJust());
|
||
|
+
|
||
|
+ result = CompileRun("Reflect.apply(f, proxy, [1])");
|
||
|
+ CHECK(result->Equals(env.local(), proxy).FromJust());
|
||
|
+}
|
||
|
|
||
|
static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||
|
ApiTestFuzzer::Fuzz();
|