Skip to content
This repository has been archived by the owner on Apr 3, 2020. It is now read-only.

Commit

Permalink
Convert receiver when calling an Api accessor.
Browse files Browse the repository at this point in the history
BUG=chromium:590071
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#35282}
  • Loading branch information
isheludko authored and Commit bot committed Apr 6, 2016
1 parent 7f34421 commit 03953f5
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 11 deletions.
15 changes: 14 additions & 1 deletion src/builtins.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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);
}
Expand Down
10 changes: 0 additions & 10 deletions src/execution.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
47 changes: 47 additions & 0 deletions test/cctest/test-api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 03953f5

Please sign in to comment.