Convert primitive receivers for API property callbacks
They're always in sloppy mode, so always do the conversion BUG=chromium:609134 R=bmeurer@chromium.org,verwaest@chromium.org LOG=n Review-Url: https://codereview.chromium.org/1960663002 Cr-Commit-Position: refs/heads/master@{#36084}
This commit is contained in:
parent
c2c2d8e69c
commit
127d6781d9
@ -32,6 +32,7 @@ Handle<AccessorInfo> Accessors::MakeAccessor(
|
||||
info->set_all_can_read(false);
|
||||
info->set_all_can_write(false);
|
||||
info->set_is_special_data_property(true);
|
||||
info->set_is_sloppy(false);
|
||||
name = factory->InternalizeName(name);
|
||||
info->set_name(*name);
|
||||
Handle<Object> get = v8::FromCData(isolate, getter);
|
||||
|
@ -1496,6 +1496,9 @@ class LoadApiGetterStub : public TurboFanCodeStub {
|
||||
public:
|
||||
LoadApiGetterStub(Isolate* isolate, bool receiver_is_holder, int index)
|
||||
: TurboFanCodeStub(isolate) {
|
||||
// If that's not true, we need to ensure that the receiver is actually a
|
||||
// JSReceiver. http://crbug.com/609134
|
||||
DCHECK(receiver_is_holder);
|
||||
minor_key_ = IndexBits::encode(index) |
|
||||
ReceiverIsHolderBits::encode(receiver_is_holder);
|
||||
}
|
||||
|
@ -866,6 +866,7 @@ Handle<AccessorInfo> Factory::NewAccessorInfo() {
|
||||
Handle<AccessorInfo> info =
|
||||
Handle<AccessorInfo>::cast(NewStruct(ACCESSOR_INFO_TYPE));
|
||||
info->set_flag(0); // Must clear the flag, it was initialized as undefined.
|
||||
info->set_is_sloppy(true);
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -7218,6 +7218,11 @@ void AccessorInfo::set_is_special_data_property(bool value) {
|
||||
set_flag(BooleanBit::set(flag(), kSpecialDataProperty, value));
|
||||
}
|
||||
|
||||
bool AccessorInfo::is_sloppy() { return BooleanBit::get(flag(), kIsSloppy); }
|
||||
|
||||
void AccessorInfo::set_is_sloppy(bool value) {
|
||||
set_flag(BooleanBit::set(flag(), kIsSloppy, value));
|
||||
}
|
||||
|
||||
PropertyAttributes AccessorInfo::property_attributes() {
|
||||
return AttributesField::decode(static_cast<uint32_t>(flag()));
|
||||
|
@ -1070,6 +1070,12 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
|
||||
v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
|
||||
if (call_fun == nullptr) return isolate->factory()->undefined_value();
|
||||
|
||||
if (info->is_sloppy() && !receiver->IsJSReceiver()) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
|
||||
Object::ConvertReceiver(isolate, receiver),
|
||||
Object);
|
||||
}
|
||||
|
||||
PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
|
||||
Object::DONT_THROW);
|
||||
Handle<Object> result = args.Call(call_fun, name);
|
||||
@ -1154,6 +1160,12 @@ Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
|
||||
// have a setter.
|
||||
if (call_fun == nullptr) return Just(true);
|
||||
|
||||
if (info->is_sloppy() && !receiver->IsJSReceiver()) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, receiver, Object::ConvertReceiver(isolate, receiver),
|
||||
Nothing<bool>());
|
||||
}
|
||||
|
||||
PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
|
||||
should_throw);
|
||||
args.Call(call_fun, name, value);
|
||||
|
@ -10202,6 +10202,9 @@ class AccessorInfo: public Struct {
|
||||
inline bool is_special_data_property();
|
||||
inline void set_is_special_data_property(bool value);
|
||||
|
||||
inline bool is_sloppy();
|
||||
inline void set_is_sloppy(bool value);
|
||||
|
||||
inline PropertyAttributes property_attributes();
|
||||
inline void set_property_attributes(PropertyAttributes attributes);
|
||||
|
||||
@ -10239,7 +10242,8 @@ class AccessorInfo: public Struct {
|
||||
static const int kAllCanReadBit = 0;
|
||||
static const int kAllCanWriteBit = 1;
|
||||
static const int kSpecialDataProperty = 2;
|
||||
class AttributesField : public BitField<PropertyAttributes, 3, 3> {};
|
||||
static const int kIsSloppy = 3;
|
||||
class AttributesField : public BitField<PropertyAttributes, 4, 3> {};
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
|
||||
};
|
||||
|
@ -774,3 +774,28 @@ TEST(PrototypeGetterAccessCheck) {
|
||||
CHECK(try_catch.HasCaught());
|
||||
}
|
||||
}
|
||||
|
||||
static void check_receiver(Local<String> name,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
CHECK(info.This()->IsObject());
|
||||
}
|
||||
|
||||
TEST(Regress609134) {
|
||||
v8::internal::FLAG_allow_natives_syntax = true;
|
||||
LocalContext env;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
auto fun_templ = v8::FunctionTemplate::New(isolate);
|
||||
fun_templ->InstanceTemplate()->SetNativeDataProperty(v8_str("foo"),
|
||||
check_receiver);
|
||||
|
||||
CHECK(env->Global()
|
||||
->Set(env.local(), v8_str("Fun"),
|
||||
fun_templ->GetFunction(env.local()).ToLocalChecked())
|
||||
.FromJust());
|
||||
|
||||
CompileRun(
|
||||
"var f = new Fun();"
|
||||
"Number.prototype.__proto__ = f;"
|
||||
"[42][0].foo");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user