Skip to content

Commit fa3e6c0

Browse files
verwaestCommit bot
authored andcommitted
Introduce DefineOwnPropertyIgnoreAttributes and make it call SetPropertyWithInterceptor.
Otherwise using Object.defineProperty with window.localStorage will not actually store the value into the database but on the object itself. BUG=v8:4137 LOG=n Review URL: https://codereview.chromium.org/1180073002 Cr-Commit-Position: refs/heads/master@{#29002}
1 parent 6a10931 commit fa3e6c0

File tree

6 files changed

+146
-152
lines changed

6 files changed

+146
-152
lines changed

src/api.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3638,7 +3638,8 @@ static i::MaybeHandle<i::Object> DefineObjectProperty(
36383638
name = i::Handle<i::String>::cast(converted);
36393639
}
36403640

3641-
return i::JSObject::DefinePropertyOrElement(js_object, name, value, attrs);
3641+
return i::JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, name,
3642+
value, attrs);
36423643
}
36433644

36443645

src/json-parser.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,8 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
434434
// Commit the intermediate state to the object and stop transitioning.
435435
CommitStateToJsonObject(json_object, map, &properties);
436436

437-
JSObject::DefinePropertyOrElement(json_object, key, value).Check();
437+
JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
438+
.Check();
438439
} while (transitioning && MatchSkipWhiteSpace(','));
439440

440441
// If we transitioned until the very end, transition the map now.
@@ -470,7 +471,8 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
470471
value = ParseJsonValue();
471472
if (value.is_null()) return ReportUnexpectedCharacter();
472473

473-
JSObject::DefinePropertyOrElement(json_object, key, value).Check();
474+
JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
475+
value).Check();
474476
}
475477
}
476478

src/objects-inl.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,22 +1197,6 @@ MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
11971197
}
11981198

11991199

1200-
MaybeHandle<Object> JSObject::DefinePropertyOrElement(
1201-
Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
1202-
PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
1203-
uint32_t index;
1204-
if (name->AsArrayIndex(&index)) {
1205-
return SetOwnElementIgnoreAttributes(object, index, value, attributes,
1206-
handling);
1207-
}
1208-
1209-
// TODO(verwaest): Is this necessary?
1210-
if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
1211-
return SetOwnPropertyIgnoreAttributes(object, name, value, attributes,
1212-
handling);
1213-
}
1214-
1215-
12161200
#define FIELD_ADDR(p, offset) \
12171201
(reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
12181202

src/objects.cc

Lines changed: 128 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -536,10 +536,11 @@ static bool FindAllCanWriteHolder(LookupIterator* it) {
536536

537537

538538
MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
539-
LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
539+
LookupIterator* it, Handle<Object> value) {
540540
Handle<JSObject> checked = it->GetHolder<JSObject>();
541541
if (FindAllCanWriteHolder(it)) {
542-
return SetPropertyWithAccessor(it, value, language_mode);
542+
// The supplied language-mode is ignored by SetPropertyWithAccessor.
543+
return SetPropertyWithAccessor(it, value, SLOPPY);
543544
}
544545

545546
it->isolate()->ReportFailedAccessCheck(checked);
@@ -3044,8 +3045,7 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
30443045
if (it->HasAccess()) break;
30453046
// Check whether it makes sense to reuse the lookup iterator. Here it
30463047
// might still call into setters up the prototype chain.
3047-
return JSObject::SetPropertyWithFailedAccessCheck(it, value,
3048-
language_mode);
3048+
return JSObject::SetPropertyWithFailedAccessCheck(it, value);
30493049

30503050
case LookupIterator::JSPROXY:
30513051
if (it->HolderIsReceiverOrHiddenPrototype()) {
@@ -3165,9 +3165,8 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
31653165
for (; own_lookup.IsFound(); own_lookup.Next()) {
31663166
switch (own_lookup.state()) {
31673167
case LookupIterator::ACCESS_CHECK:
3168-
if (!it->isolate()->MayAccess(own_lookup.GetHolder<JSObject>())) {
3169-
return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
3170-
language_mode);
3168+
if (!own_lookup.HasAccess()) {
3169+
return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value);
31713170
}
31723171
break;
31733172

@@ -3177,17 +3176,17 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
31773176
case LookupIterator::DATA: {
31783177
PropertyDetails details = own_lookup.property_details();
31793178
if (details.IsConfigurable() || !details.IsReadOnly()) {
3180-
return JSObject::ReconfigureAsDataProperty(&own_lookup, value,
3181-
details.attributes());
3179+
return JSObject::DefineOwnPropertyIgnoreAttributes(
3180+
&own_lookup, value, details.attributes());
31823181
}
31833182
return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
31843183
}
31853184

31863185
case LookupIterator::ACCESSOR: {
31873186
PropertyDetails details = own_lookup.property_details();
31883187
if (details.IsConfigurable()) {
3189-
return JSObject::ReconfigureAsDataProperty(&own_lookup, value,
3190-
details.attributes());
3188+
return JSObject::DefineOwnPropertyIgnoreAttributes(
3189+
&own_lookup, value, details.attributes());
31913190
}
31923191

31933192
return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
@@ -4131,166 +4130,172 @@ void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) {
41314130
}
41324131

41334132

4134-
MaybeHandle<Object> JSObject::ReconfigureAsDataProperty(
4133+
// Reconfigures a property to a data property with attributes, even if it is not
4134+
// reconfigurable.
4135+
// Requires a LookupIterator that does not look at the prototype chain beyond
4136+
// hidden prototypes.
4137+
MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
41354138
LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
41364139
ExecutableAccessorInfoHandling handling) {
41374140
Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
41384141
bool is_observed = object->map()->is_observed() &&
41394142
(it->IsElement() ||
41404143
!it->isolate()->IsInternallyUsedPropertyName(it->name()));
41414144

4142-
switch (it->state()) {
4143-
case LookupIterator::INTERCEPTOR:
4144-
case LookupIterator::JSPROXY:
4145-
case LookupIterator::NOT_FOUND:
4146-
case LookupIterator::TRANSITION:
4147-
case LookupIterator::ACCESS_CHECK:
4148-
UNREACHABLE();
4145+
for (; it->IsFound(); it->Next()) {
4146+
switch (it->state()) {
4147+
case LookupIterator::JSPROXY:
4148+
case LookupIterator::NOT_FOUND:
4149+
case LookupIterator::TRANSITION:
4150+
UNREACHABLE();
41494151

4150-
case LookupIterator::INTEGER_INDEXED_EXOTIC:
4151-
return value;
4152+
case LookupIterator::ACCESS_CHECK:
4153+
if (!it->HasAccess()) {
4154+
return SetPropertyWithFailedAccessCheck(it, value);
4155+
}
4156+
break;
41524157

4153-
case LookupIterator::ACCESSOR: {
4154-
PropertyDetails details = it->property_details();
4155-
// Ensure the context isn't changed after calling into accessors.
4156-
AssertNoContextChange ncc(it->isolate());
4158+
// If there's an interceptor, try to store the property with the
4159+
// interceptor.
4160+
// In case of success, the attributes will have been reset to the default
4161+
// attributes of the interceptor, rather than the incoming attributes.
4162+
//
4163+
// TODO(verwaest): JSProxy afterwards verify the attributes that the
4164+
// JSProxy claims it has, and verifies that they are compatible. If not,
4165+
// they throw. Here we should do the same.
4166+
case LookupIterator::INTERCEPTOR:
4167+
if (handling == DONT_FORCE_FIELD) {
4168+
MaybeHandle<Object> maybe_result =
4169+
JSObject::SetPropertyWithInterceptor(it, value);
4170+
if (!maybe_result.is_null()) return maybe_result;
4171+
if (it->isolate()->has_pending_exception()) return maybe_result;
4172+
}
4173+
break;
41574174

4158-
Handle<Object> accessors = it->GetAccessors();
4175+
case LookupIterator::INTEGER_INDEXED_EXOTIC:
4176+
return value;
41594177

4160-
// Special handling for ExecutableAccessorInfo, which behaves like a
4161-
// data property.
4162-
if (accessors->IsExecutableAccessorInfo() &&
4163-
handling == DONT_FORCE_FIELD) {
4164-
Handle<Object> result;
4165-
ASSIGN_RETURN_ON_EXCEPTION(
4166-
it->isolate(), result,
4167-
JSObject::SetPropertyWithAccessor(it, value, STRICT), Object);
4168-
DCHECK(result->SameValue(*value));
4169-
4170-
if (details.attributes() == attributes) return value;
4171-
4172-
// Reconfigure the accessor if attributes mismatch.
4173-
Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4174-
it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4175-
new_data->set_property_attributes(attributes);
4176-
// By clearing the setter we don't have to introduce a lookup to
4177-
// the setter, simply make it unavailable to reflect the
4178-
// attributes.
4179-
if (attributes & READ_ONLY) {
4180-
ExecutableAccessorInfo::ClearSetter(new_data);
4181-
}
4178+
case LookupIterator::ACCESSOR: {
4179+
Handle<Object> accessors = it->GetAccessors();
41824180

4183-
if (it->IsElement()) {
4184-
SetElementCallback(it->GetHolder<JSObject>(), it->index(), new_data,
4185-
attributes);
4181+
// Special handling for ExecutableAccessorInfo, which behaves like a
4182+
// data property.
4183+
if (accessors->IsExecutableAccessorInfo() &&
4184+
handling == DONT_FORCE_FIELD) {
4185+
PropertyDetails details = it->property_details();
4186+
// Ensure the context isn't changed after calling into accessors.
4187+
AssertNoContextChange ncc(it->isolate());
4188+
4189+
Handle<Object> result;
4190+
ASSIGN_RETURN_ON_EXCEPTION(
4191+
it->isolate(), result,
4192+
JSObject::SetPropertyWithAccessor(it, value, STRICT), Object);
4193+
DCHECK(result->SameValue(*value));
4194+
4195+
if (details.attributes() == attributes) return value;
4196+
4197+
// Reconfigure the accessor if attributes mismatch.
4198+
Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4199+
it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4200+
new_data->set_property_attributes(attributes);
4201+
// By clearing the setter we don't have to introduce a lookup to
4202+
// the setter, simply make it unavailable to reflect the
4203+
// attributes.
4204+
if (attributes & READ_ONLY) {
4205+
ExecutableAccessorInfo::ClearSetter(new_data);
4206+
}
4207+
4208+
if (it->IsElement()) {
4209+
SetElementCallback(it->GetHolder<JSObject>(), it->index(), new_data,
4210+
attributes);
4211+
} else {
4212+
SetPropertyCallback(it->GetHolder<JSObject>(), it->name(), new_data,
4213+
attributes);
4214+
}
41864215
} else {
4187-
SetPropertyCallback(it->GetHolder<JSObject>(), it->name(), new_data,
4188-
attributes);
4216+
it->ReconfigureDataProperty(value, attributes);
4217+
it->WriteDataValue(value);
41894218
}
4219+
41904220
if (is_observed) {
41914221
RETURN_ON_EXCEPTION(
41924222
it->isolate(),
41934223
EnqueueChangeRecord(object, "reconfigure", it->GetName(),
41944224
it->factory()->the_hole_value()),
41954225
Object);
41964226
}
4197-
return value;
4198-
}
4199-
4200-
it->ReconfigureDataProperty(value, attributes);
4201-
it->WriteDataValue(value);
4202-
4203-
if (is_observed) {
4204-
RETURN_ON_EXCEPTION(
4205-
it->isolate(),
4206-
EnqueueChangeRecord(object, "reconfigure", it->GetName(),
4207-
it->factory()->the_hole_value()),
4208-
Object);
4209-
}
42104227

4211-
return value;
4212-
}
4213-
4214-
case LookupIterator::DATA: {
4215-
PropertyDetails details = it->property_details();
4216-
Handle<Object> old_value = it->factory()->the_hole_value();
4217-
// Regular property update if the attributes match.
4218-
if (details.attributes() == attributes) {
4219-
return SetDataProperty(it, value);
4228+
return value;
42204229
}
4230+
case LookupIterator::DATA: {
4231+
PropertyDetails details = it->property_details();
4232+
Handle<Object> old_value = it->factory()->the_hole_value();
4233+
// Regular property update if the attributes match.
4234+
if (details.attributes() == attributes) {
4235+
return SetDataProperty(it, value);
4236+
}
42214237

4222-
// Special case: properties of typed arrays cannot be reconfigured to
4223-
// non-writable nor to non-enumerable.
4224-
if (it->IsElement() && (object->HasExternalArrayElements() ||
4225-
object->HasFixedTypedArrayElements())) {
4226-
return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4227-
value, STRICT);
4228-
}
4238+
// Special case: properties of typed arrays cannot be reconfigured to
4239+
// non-writable nor to non-enumerable.
4240+
if (it->IsElement() && (object->HasExternalArrayElements() ||
4241+
object->HasFixedTypedArrayElements())) {
4242+
return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4243+
value, STRICT);
4244+
}
42294245

4230-
// Reconfigure the data property if the attributes mismatch.
4231-
if (is_observed) old_value = it->GetDataValue();
4246+
// Reconfigure the data property if the attributes mismatch.
4247+
if (is_observed) old_value = it->GetDataValue();
42324248

4233-
it->ReconfigureDataProperty(value, attributes);
4234-
it->WriteDataValue(value);
4249+
it->ReconfigureDataProperty(value, attributes);
4250+
it->WriteDataValue(value);
42354251

4236-
if (is_observed) {
4237-
if (old_value->SameValue(*value)) {
4238-
old_value = it->factory()->the_hole_value();
4252+
if (is_observed) {
4253+
if (old_value->SameValue(*value)) {
4254+
old_value = it->factory()->the_hole_value();
4255+
}
4256+
RETURN_ON_EXCEPTION(it->isolate(),
4257+
EnqueueChangeRecord(object, "reconfigure",
4258+
it->GetName(), old_value),
4259+
Object);
42394260
}
4240-
RETURN_ON_EXCEPTION(it->isolate(),
4241-
EnqueueChangeRecord(object, "reconfigure",
4242-
it->GetName(), old_value),
4243-
Object);
4261+
return value;
42444262
}
42454263
}
42464264
}
42474265

4248-
return value;
4266+
return AddDataProperty(it, value, attributes, STRICT,
4267+
CERTAINLY_NOT_STORE_FROM_KEYED);
42494268
}
42504269

42514270

4252-
// Reconfigures a property to a data property with attributes, even if it is not
4253-
// reconfigurable.
42544271
MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
42554272
Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
42564273
PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
42574274
DCHECK(!value->IsTheHole());
4258-
LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4259-
if (it.state() == LookupIterator::ACCESS_CHECK) {
4260-
if (!it.HasAccess()) {
4261-
return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4262-
}
4263-
it.Next();
4264-
}
4265-
4266-
if (it.IsFound()) {
4267-
return ReconfigureAsDataProperty(&it, value, attributes, handling);
4268-
}
4269-
4270-
return AddDataProperty(&it, value, attributes, STRICT,
4271-
CERTAINLY_NOT_STORE_FROM_KEYED);
4275+
LookupIterator it(object, name, LookupIterator::OWN);
4276+
return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
42724277
}
42734278

42744279

42754280
MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
42764281
Handle<JSObject> object, uint32_t index, Handle<Object> value,
42774282
PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
42784283
Isolate* isolate = object->GetIsolate();
4279-
LookupIterator it(isolate, object, index,
4280-
LookupIterator::OWN_SKIP_INTERCEPTOR);
4281-
if (it.state() == LookupIterator::ACCESS_CHECK) {
4282-
if (!it.HasAccess()) {
4283-
return SetPropertyWithFailedAccessCheck(&it, value, STRICT);
4284-
}
4285-
it.Next();
4286-
}
4284+
LookupIterator it(isolate, object, index, LookupIterator::OWN);
4285+
return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4286+
}
42874287

4288-
if (it.IsFound()) {
4289-
return ReconfigureAsDataProperty(&it, value, attributes, handling);
4290-
}
42914288

4292-
return AddDataProperty(&it, value, attributes, STRICT,
4293-
MAY_BE_STORE_FROM_KEYED);
4289+
MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
4290+
Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
4291+
PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4292+
Isolate* isolate = object->GetIsolate();
4293+
uint32_t index;
4294+
LookupIterator it =
4295+
name->AsArrayIndex(&index)
4296+
? LookupIterator(isolate, object, index, LookupIterator::OWN)
4297+
: LookupIterator(object, name, LookupIterator::OWN);
4298+
return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
42944299
}
42954300

42964301

0 commit comments

Comments
 (0)