@@ -536,10 +536,11 @@ static bool FindAllCanWriteHolder(LookupIterator* it) {
536536
537537
538538MaybeHandle<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.
42544271MaybeHandle<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
42754280MaybeHandle<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