Convert receiver when calling an Api accessor.

BUG=chromium:590071
LOG=N

Review URL: https://codereview.chromium.org/1856123005

Cr-Commit-Position: refs/heads/master@{#35282}
This commit is contained in:
ishell 2016-04-06 01:00:13 -07:00 committed by Commit bot
parent 7f3442133e
commit 03953f52bd
3 changed files with 61 additions and 11 deletions

View File

@ -4366,6 +4366,20 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
Handle<Object> receiver,
int argc,
Handle<Object> args[]) {
Isolate* isolate = function->GetIsolate();
// Do proper receiver conversion for non-strict mode api functions.
if (!receiver->IsJSReceiver()) {
DCHECK(function->IsFunctionTemplateInfo() || function->IsJSFunction());
if (function->IsFunctionTemplateInfo() ||
is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
if (receiver->IsUndefined() || receiver->IsNull()) {
receiver = handle(isolate->global_proxy(), isolate);
} else {
ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
Object::ToObject(isolate, receiver), Object);
}
}
}
// Construct BuiltinArguments object: function, arguments reversed, receiver.
const int kBufferSize = 32;
Object* small_argv[kBufferSize];
@ -4382,7 +4396,6 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
argv[0] = *function;
MaybeHandle<Object> result;
{
auto isolate = function->GetIsolate();
RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]);
result = HandleApiCallHelper<false>(isolate, arguments);
}

View File

@ -138,16 +138,6 @@ MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
SaveContext save(isolate);
isolate->set_context(function->context());
// Do proper receiver conversion for non-strict mode api functions.
if (!receiver->IsJSReceiver() &&
is_sloppy(function->shared()->language_mode())) {
if (receiver->IsUndefined() || receiver->IsNull()) {
receiver = handle(function->global_proxy(), isolate);
} else {
ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
Object::ToObject(isolate, receiver), Object);
}
}
DCHECK(function->context()->global_object()->IsJSGlobalObject());
auto value = Builtins::InvokeApiFunction(function, receiver, argc, argv);
bool has_exception = value.is_null();

View File

@ -24658,6 +24658,53 @@ TEST(CompatibleReceiverCheckOnCachedICHandler) {
0);
}
THREADED_TEST(ReceiverConversionForAccessors) {
LocalContext env;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
Local<v8::FunctionTemplate> acc =
v8::FunctionTemplate::New(isolate, Returns42);
CHECK(env->Global()
->Set(env.local(), v8_str("acc"),
acc->GetFunction(env.local()).ToLocalChecked())
.FromJust());
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
templ->SetAccessorProperty(v8_str("acc"), acc, acc);
Local<v8::Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
CHECK(env->Global()->Set(env.local(), v8_str("p"), instance).FromJust());
CHECK(CompileRun("(p.acc == 42)")->BooleanValue(env.local()).FromJust());
CHECK(CompileRun("(p.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
CHECK(!CompileRun("Number.prototype.__proto__ = p;"
"var a = 1;")
.IsEmpty());
CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
CHECK(!CompileRun("Boolean.prototype.__proto__ = p;"
"var a = true;")
.IsEmpty());
CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
CHECK(!CompileRun("String.prototype.__proto__ = p;"
"var a = 'foo';")
.IsEmpty());
CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
CHECK(CompileRun("acc.call(1) == 42")->BooleanValue(env.local()).FromJust());
CHECK(CompileRun("acc.call(true)==42")->BooleanValue(env.local()).FromJust());
CHECK(CompileRun("acc.call('aa')==42")->BooleanValue(env.local()).FromJust());
CHECK(
CompileRun("acc.call(null) == 42")->BooleanValue(env.local()).FromJust());
CHECK(CompileRun("acc.call(undefined) == 42")
->BooleanValue(env.local())
.FromJust());
}
class FutexInterruptionThread : public v8::base::Thread {
public:
explicit FutexInterruptionThread(v8::Isolate* isolate)