Commit 9bfb0fef authored by neis's avatar neis Committed by Commit bot

[runtime] Support proxies as return value of API constructors.

When a FunctionTemplate-based function is used as a constructor
and returns a JSProxy, we incorrectly treated that result the same
as a non-object result. Now it is treated like any other object
result, i.e., it becomes the result of the constructor call.

R=verwaest@chromium.org
BUG=v8:6294

Review-Url: https://codereview.chromium.org/2845123002
Cr-Commit-Position: refs/heads/master@{#44970}
parent 0655ee8f
...@@ -118,7 +118,8 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper( ...@@ -118,7 +118,8 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
} }
// Rebox the result. // Rebox the result.
result->VerifyApiCallResultType(); result->VerifyApiCallResultType();
if (!is_construct || result->IsJSObject()) return handle(*result, isolate); if (!is_construct || result->IsJSReceiver())
return handle(*result, isolate);
} }
return js_receiver; return js_receiver;
......
...@@ -11261,48 +11261,79 @@ THREADED_TEST(ConstructorForObject) { ...@@ -11261,48 +11261,79 @@ THREADED_TEST(ConstructorForObject) {
Local<Function> function = Local<Function> function =
function_template->GetFunction(context.local()).ToLocalChecked(); function_template->GetFunction(context.local()).ToLocalChecked();
Local<Object> instance1 = function; Local<Object> instance1 = function;
CHECK(instance1->IsObject());
CHECK(instance1->IsFunction());
CHECK(context->Global() CHECK(context->Global()
->Set(context.local(), v8_str("obj4"), instance1) ->Set(context.local(), v8_str("obj4"), instance1)
.FromJust()); .FromJust());
v8::TryCatch try_catch(isolate); v8::TryCatch try_catch(isolate);
Local<Value> value;
CHECK(!try_catch.HasCaught()); CHECK(!try_catch.HasCaught());
CHECK(instance1->IsObject()); {
CHECK(instance1->IsFunction()); Local<Value> value = CompileRun("new obj4(28)");
value = CompileRun("new obj4(28)");
CHECK(!try_catch.HasCaught()); CHECK(!try_catch.HasCaught());
CHECK(value->IsObject()); CHECK(value->IsObject());
Local<Value> args1[] = {v8_num(28)}; Local<Value> args[] = {v8_num(28)};
value = instance1->CallAsConstructor(context.local(), 1, args1) value = instance1->CallAsConstructor(context.local(), 1, args)
.ToLocalChecked(); .ToLocalChecked();
CHECK(!try_catch.HasCaught()); CHECK(!try_catch.HasCaught());
CHECK(value->IsObject()); CHECK(value->IsObject());
}
Local<Value> proxy = CompileRun("proxy = new Proxy({},{})");
CHECK(!try_catch.HasCaught());
CHECK(proxy->IsProxy());
{
Local<Value> value = CompileRun("new obj4(proxy)");
CHECK(!try_catch.HasCaught());
CHECK(value->IsProxy());
CHECK(value->SameValue(proxy));
Local<Value> args[] = {proxy};
value = instance1->CallAsConstructor(context.local(), 1, args)
.ToLocalChecked();
CHECK(!try_catch.HasCaught());
CHECK(value->SameValue(proxy));
}
Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate); Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
instance_template->SetCallAsFunctionHandler(FakeConstructorCallback); instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
Local<Object> instance2 = Local<Object> instance2 =
instance_template->NewInstance(context.local()).ToLocalChecked(); instance_template->NewInstance(context.local()).ToLocalChecked();
CHECK(instance2->IsObject());
CHECK(instance2->IsFunction());
CHECK(context->Global() CHECK(context->Global()
->Set(context.local(), v8_str("obj5"), instance2) ->Set(context.local(), v8_str("obj5"), instance2)
.FromJust()); .FromJust());
CHECK(!try_catch.HasCaught()); CHECK(!try_catch.HasCaught());
CHECK(instance2->IsObject()); {
CHECK(instance2->IsFunction()); Local<Value> value = CompileRun("new obj5(28)");
value = CompileRun("new obj5(28)");
CHECK(!try_catch.HasCaught()); CHECK(!try_catch.HasCaught());
CHECK(!value->IsObject()); CHECK(!value->IsObject());
Local<Value> args2[] = {v8_num(28)}; Local<Value> args[] = {v8_num(28)};
value = instance2->CallAsConstructor(context.local(), 1, args2) value = instance2->CallAsConstructor(context.local(), 1, args)
.ToLocalChecked(); .ToLocalChecked();
CHECK(!try_catch.HasCaught()); CHECK(!try_catch.HasCaught());
CHECK(!value->IsObject()); CHECK(!value->IsObject());
} }
{
Local<Value> value = CompileRun("new obj5(proxy)");
CHECK(!try_catch.HasCaught());
CHECK(value->IsProxy());
CHECK(value->SameValue(proxy));
Local<Value> args[] = {proxy};
value = instance2->CallAsConstructor(context.local(), 1, args)
.ToLocalChecked();
CHECK(!try_catch.HasCaught());
CHECK(value->SameValue(proxy));
}
}
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment