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:
parent
7f3442133e
commit
03953f52bd
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user