76c5f5cc8a
In the GN build, libchromiumcontent is no longer a distinct library, but merely a container for a set of scripts and patches. Maintaining those patches in a separate repository is tedious and error-prone, so merge them into the main repo. Once this is merged and GN is the default way to build Electron, the libchromiumcontent repository can be archived.
114 lines
5.1 KiB
Diff
114 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();
|