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(
}
// Rebox the result.
result->VerifyApiCallResultType();
if (!is_construct || result->IsJSObject()) return handle(*result, isolate);
if (!is_construct || result->IsJSReceiver())
return handle(*result, isolate);
}
return js_receiver;
......
......@@ -11261,47 +11261,78 @@ THREADED_TEST(ConstructorForObject) {
Local<Function> function =
function_template->GetFunction(context.local()).ToLocalChecked();
Local<Object> instance1 = function;
CHECK(instance1->IsObject());
CHECK(instance1->IsFunction());
CHECK(context->Global()
->Set(context.local(), v8_str("obj4"), instance1)
.FromJust());
v8::TryCatch try_catch(isolate);
Local<Value> value;
CHECK(!try_catch.HasCaught());
CHECK(instance1->IsObject());
CHECK(instance1->IsFunction());
{
Local<Value> value = CompileRun("new obj4(28)");
CHECK(!try_catch.HasCaught());
CHECK(value->IsObject());
Local<Value> args[] = {v8_num(28)};
value = instance1->CallAsConstructor(context.local(), 1, args)
.ToLocalChecked();
CHECK(!try_catch.HasCaught());
CHECK(value->IsObject());
}
value = CompileRun("new obj4(28)");
Local<Value> proxy = CompileRun("proxy = new Proxy({},{})");
CHECK(!try_catch.HasCaught());
CHECK(value->IsObject());
CHECK(proxy->IsProxy());
Local<Value> args1[] = {v8_num(28)};
value = instance1->CallAsConstructor(context.local(), 1, args1)
.ToLocalChecked();
CHECK(!try_catch.HasCaught());
CHECK(value->IsObject());
{
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);
instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
Local<Object> instance2 =
instance_template->NewInstance(context.local()).ToLocalChecked();
CHECK(instance2->IsObject());
CHECK(instance2->IsFunction());
CHECK(context->Global()
->Set(context.local(), v8_str("obj5"), instance2)
.FromJust());
CHECK(!try_catch.HasCaught());
CHECK(instance2->IsObject());
CHECK(instance2->IsFunction());
value = CompileRun("new obj5(28)");
CHECK(!try_catch.HasCaught());
CHECK(!value->IsObject());
{
Local<Value> value = CompileRun("new obj5(28)");
CHECK(!try_catch.HasCaught());
CHECK(!value->IsObject());
Local<Value> args[] = {v8_num(28)};
value = instance2->CallAsConstructor(context.local(), 1, args)
.ToLocalChecked();
CHECK(!try_catch.HasCaught());
CHECK(!value->IsObject());
}
Local<Value> args2[] = {v8_num(28)};
value = instance2->CallAsConstructor(context.local(), 1, args2)
.ToLocalChecked();
CHECK(!try_catch.HasCaught());
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