diff --git a/src/accessors.cc b/src/accessors.cc index ccae58255a..37404837ad 100644 --- a/src/accessors.cc +++ b/src/accessors.cc @@ -32,6 +32,7 @@ Handle 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 get = v8::FromCData(isolate, getter); diff --git a/src/code-stubs.h b/src/code-stubs.h index 6ed5760b62..d0664a1ff1 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -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); } diff --git a/src/factory.cc b/src/factory.cc index 9cebd3f1b4..1beb00fe66 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -866,6 +866,7 @@ Handle Factory::NewAccessorInfo() { Handle info = Handle::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; } diff --git a/src/objects-inl.h b/src/objects-inl.h index 0492436903..dd2d2df384 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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(flag())); diff --git a/src/objects.cc b/src/objects.cc index aa047b2e8a..00bd2c18bc 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1070,6 +1070,12 @@ MaybeHandle Object::GetPropertyWithAccessor(LookupIterator* it) { v8::ToCData(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 result = args.Call(call_fun, name); @@ -1154,6 +1160,12 @@ Maybe 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()); + } + PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder, should_throw); args.Call(call_fun, name, value); diff --git a/src/objects.h b/src/objects.h index a2cc6d5b30..91d0ab767b 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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 {}; + static const int kIsSloppy = 3; + class AttributesField : public BitField {}; DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo); }; diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc index 90ea08144d..67803eeed6 100644 --- a/test/cctest/test-accessors.cc +++ b/test/cctest/test-accessors.cc @@ -774,3 +774,28 @@ TEST(PrototypeGetterAccessCheck) { CHECK(try_catch.HasCaught()); } } + +static void check_receiver(Local name, + const v8::PropertyCallbackInfo& 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"); +}