| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 5d210bd5718b599c9e55228325b3e8eddbb790b7..0eda4912e63902939c8efd1effdc71953670f307 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -291,7 +291,7 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(Handle<Object> receiver,
|
| if (structure->IsAccessorInfo()) {
|
| Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
|
| if (!info->IsCompatibleReceiver(*receiver)) {
|
| - Handle<Object> args[2] = { name, receiver };
|
| + Handle<Object> args[] = {name, receiver};
|
| THROW_NEW_ERROR(isolate,
|
| NewTypeError("incompatible_method_receiver",
|
| HandleVector(args, arraysize(args))),
|
| @@ -356,7 +356,7 @@ MaybeHandle<Object> Object::SetPropertyWithAccessor(
|
| // api style callbacks
|
| ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure);
|
| if (!info->IsCompatibleReceiver(*receiver)) {
|
| - Handle<Object> args[2] = { name, receiver };
|
| + Handle<Object> args[] = {name, receiver};
|
| THROW_NEW_ERROR(isolate,
|
| NewTypeError("incompatible_method_receiver",
|
| HandleVector(args, arraysize(args))),
|
| @@ -383,10 +383,11 @@ MaybeHandle<Object> Object::SetPropertyWithAccessor(
|
| receiver, Handle<JSReceiver>::cast(setter), value);
|
| } else {
|
| if (is_sloppy(language_mode)) return value;
|
| - Handle<Object> args[2] = { name, holder };
|
| - THROW_NEW_ERROR(
|
| - isolate, NewTypeError("no_setter_in_callback", HandleVector(args, 2)),
|
| - Object);
|
| + Handle<Object> args[] = {name, holder};
|
| + THROW_NEW_ERROR(isolate,
|
| + NewTypeError("no_setter_in_callback",
|
| + HandleVector(args, arraysize(args))),
|
| + Object);
|
| }
|
| }
|
|
|
| @@ -753,13 +754,12 @@ MaybeHandle<Object> Object::SetElementWithReceiver(
|
| Handle<JSObject> target = Handle<JSObject>::cast(receiver);
|
| ElementsAccessor* accessor = target->GetElementsAccessor();
|
| PropertyAttributes attrs = accessor->GetAttributes(target, index);
|
| - if ((attrs & READ_ONLY) != 0) {
|
| - return WriteToReadOnlyElement(isolate, receiver, index, value,
|
| - language_mode);
|
| + if (attrs == ABSENT) {
|
| + return JSObject::SetElement(target, index, value, NONE, language_mode,
|
| + false);
|
| }
|
| - PropertyAttributes new_attrs = attrs != ABSENT ? attrs : NONE;
|
| - return JSObject::SetElement(target, index, value, new_attrs, language_mode,
|
| - false);
|
| + return JSObject::SetElement(target, index, value, attrs, language_mode, false,
|
| + DEFINE_PROPERTY);
|
| }
|
|
|
|
|
| @@ -3047,15 +3047,17 @@ MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
|
| }
|
|
|
|
|
| -MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
|
| - Handle<Object> value,
|
| - LanguageMode language_mode,
|
| - StoreFromKeyed store_mode,
|
| - StorePropertyMode data_store_mode) {
|
| +MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
|
| + Handle<Object> value,
|
| + LanguageMode language_mode,
|
| + StoreFromKeyed store_mode,
|
| + bool* found) {
|
| // Make sure that the top context does not change when doing callbacks or
|
| // interceptor calls.
|
| AssertNoContextChange ncc(it->isolate());
|
|
|
| + *found = true;
|
| +
|
| bool done = false;
|
| for (; it->IsFound(); it->Next()) {
|
| switch (it->state()) {
|
| @@ -3135,32 +3137,102 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
|
| // the property did not exist yet on the global object itself, we have to
|
| // throw a reference error in strict mode.
|
| if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) {
|
| - Handle<Object> args[1] = {it->name()};
|
| - THROW_NEW_ERROR(it->isolate(),
|
| - NewReferenceError("not_defined", HandleVector(args, 1)),
|
| - Object);
|
| + Handle<Object> args[] = {it->name()};
|
| + THROW_NEW_ERROR(
|
| + it->isolate(),
|
| + NewReferenceError("not_defined", HandleVector(args, arraysize(args))),
|
| + Object);
|
| }
|
|
|
| - if (data_store_mode == SUPER_PROPERTY) {
|
| - LookupIterator own_lookup(it->GetReceiver(), it->name(),
|
| - LookupIterator::OWN);
|
| + *found = false;
|
| + return MaybeHandle<Object>();
|
| +}
|
|
|
| - return JSObject::SetProperty(&own_lookup, value, language_mode, store_mode,
|
| - NORMAL_PROPERTY);
|
| - }
|
|
|
| +MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
|
| + Handle<Object> value,
|
| + LanguageMode language_mode,
|
| + StoreFromKeyed store_mode) {
|
| + bool found = false;
|
| + MaybeHandle<Object> result =
|
| + SetPropertyInternal(it, value, language_mode, store_mode, &found);
|
| + if (found) return result;
|
| return AddDataProperty(it, value, NONE, language_mode, store_mode);
|
| }
|
|
|
|
|
| +MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
|
| + Handle<Object> value,
|
| + LanguageMode language_mode,
|
| + StoreFromKeyed store_mode) {
|
| + bool found = false;
|
| + MaybeHandle<Object> result =
|
| + SetPropertyInternal(it, value, language_mode, store_mode, &found);
|
| + if (found) return result;
|
| +
|
| + LookupIterator own_lookup(it->GetReceiver(), it->name(), LookupIterator::OWN);
|
| +
|
| + switch (own_lookup.state()) {
|
| + case LookupIterator::NOT_FOUND:
|
| + return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
|
| + store_mode);
|
| +
|
| + case LookupIterator::DATA: {
|
| + PropertyDetails details = own_lookup.property_details();
|
| + if (details.IsConfigurable() || !details.IsReadOnly()) {
|
| + return JSObject::SetOwnPropertyIgnoreAttributes(
|
| + Handle<JSObject>::cast(it->GetReceiver()), it->name(), value,
|
| + details.attributes());
|
| + }
|
| + return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
|
| + }
|
| +
|
| + case LookupIterator::ACCESSOR: {
|
| + PropertyDetails details = own_lookup.property_details();
|
| + if (details.IsConfigurable()) {
|
| + return JSObject::SetOwnPropertyIgnoreAttributes(
|
| + Handle<JSObject>::cast(it->GetReceiver()), it->name(), value,
|
| + details.attributes());
|
| + }
|
| +
|
| + return RedefineNonconfigurableProperty(it->isolate(), it->name(), value,
|
| + language_mode);
|
| + }
|
| +
|
| + case LookupIterator::TRANSITION:
|
| + UNREACHABLE();
|
| + break;
|
| +
|
| + case LookupIterator::INTERCEPTOR:
|
| + case LookupIterator::JSPROXY:
|
| + case LookupIterator::ACCESS_CHECK: {
|
| + bool found = false;
|
| + MaybeHandle<Object> result = SetPropertyInternal(
|
| + &own_lookup, value, language_mode, store_mode, &found);
|
| + if (found) return result;
|
| + return SetDataProperty(&own_lookup, value);
|
| + }
|
| + }
|
| +
|
| + UNREACHABLE();
|
| + return MaybeHandle<Object>();
|
| +}
|
| +
|
| +
|
| MaybeHandle<Object> Object::WriteToReadOnlyProperty(
|
| LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
|
| - if (is_sloppy(language_mode)) return value;
|
| + return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), it->name(),
|
| + value, language_mode);
|
| +}
|
|
|
| - Handle<Object> args[] = {it->name(), it->GetReceiver()};
|
| - THROW_NEW_ERROR(it->isolate(),
|
| - NewTypeError("strict_read_only_property",
|
| - HandleVector(args, arraysize(args))),
|
| +
|
| +MaybeHandle<Object> Object::WriteToReadOnlyProperty(
|
| + Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
|
| + Handle<Object> value, LanguageMode language_mode) {
|
| + if (is_sloppy(language_mode)) return value;
|
| + Handle<Object> args[] = {name, receiver};
|
| + THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
|
| + HandleVector(args, arraysize(args))),
|
| Object);
|
| }
|
|
|
| @@ -3170,11 +3242,18 @@ MaybeHandle<Object> Object::WriteToReadOnlyElement(Isolate* isolate,
|
| uint32_t index,
|
| Handle<Object> value,
|
| LanguageMode language_mode) {
|
| - if (is_sloppy(language_mode)) return value;
|
| + return WriteToReadOnlyProperty(isolate, receiver,
|
| + isolate->factory()->NewNumberFromUint(index),
|
| + value, language_mode);
|
| +}
|
|
|
| - Handle<Object> args[] = {isolate->factory()->NewNumberFromUint(index),
|
| - receiver};
|
| - THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
|
| +
|
| +MaybeHandle<Object> Object::RedefineNonconfigurableProperty(
|
| + Isolate* isolate, Handle<Object> name, Handle<Object> value,
|
| + LanguageMode language_mode) {
|
| + if (is_sloppy(language_mode)) return value;
|
| + Handle<Object> args[] = {name};
|
| + THROW_NEW_ERROR(isolate, NewTypeError("redefine_disallowed",
|
| HandleVector(args, arraysize(args))),
|
| Object);
|
| }
|
| @@ -3243,7 +3322,7 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
|
| if (it->state() != LookupIterator::TRANSITION) {
|
| if (is_sloppy(language_mode)) return value;
|
|
|
| - Handle<Object> args[1] = {it->name()};
|
| + Handle<Object> args[] = {it->name()};
|
| THROW_NEW_ERROR(it->isolate(),
|
| NewTypeError("object_not_extensible",
|
| HandleVector(args, arraysize(args))),
|
| @@ -3789,11 +3868,8 @@ MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
|
| DCHECK(writable->IsBoolean());
|
| *done = writable->IsFalse();
|
| if (!*done) return isolate->factory()->the_hole_value();
|
| - if (is_sloppy(language_mode)) return value;
|
| - Handle<Object> args[] = { name, receiver };
|
| - THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
|
| - HandleVector(args, arraysize(args))),
|
| - Object);
|
| + return WriteToReadOnlyProperty(isolate, receiver, name, value,
|
| + language_mode);
|
| }
|
|
|
| // We have an AccessorDescriptor.
|
| @@ -5152,9 +5228,10 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
|
| if (is_strict(language_mode)) {
|
| // Deleting a non-configurable property in strict mode.
|
| Handle<Object> name = factory->NewNumberFromUint(index);
|
| - Handle<Object> args[2] = { name, object };
|
| - THROW_NEW_ERROR(isolate, NewTypeError("strict_delete_property",
|
| - HandleVector(args, 2)),
|
| + Handle<Object> args[] = {name, object};
|
| + THROW_NEW_ERROR(isolate,
|
| + NewTypeError("strict_delete_property",
|
| + HandleVector(args, arraysize(args))),
|
| Object);
|
| }
|
| return factory->false_value();
|
| @@ -5285,7 +5362,7 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
|
| if (!it.IsConfigurable()) {
|
| // Fail if the property is not configurable.
|
| if (is_strict(language_mode)) {
|
| - Handle<Object> args[2] = {name, object};
|
| + Handle<Object> args[] = {name, object};
|
| THROW_NEW_ERROR(it.isolate(),
|
| NewTypeError("strict_delete_property",
|
| HandleVector(args, arraysize(args))),
|
| @@ -12660,10 +12737,11 @@ MaybeHandle<Object> JSObject::SetElementWithCallback(
|
| } else {
|
| if (is_sloppy(language_mode)) return value;
|
| Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
|
| - Handle<Object> args[2] = { key, holder };
|
| - THROW_NEW_ERROR(
|
| - isolate, NewTypeError("no_setter_in_callback", HandleVector(args, 2)),
|
| - Object);
|
| + Handle<Object> args[] = {key, holder};
|
| + THROW_NEW_ERROR(isolate,
|
| + NewTypeError("no_setter_in_callback",
|
| + HandleVector(args, arraysize(args))),
|
| + Object);
|
| }
|
| }
|
|
|
| @@ -12850,25 +12928,30 @@ MaybeHandle<Object> JSObject::SetDictionaryElement(
|
| if (details.type() == ACCESSOR_CONSTANT && set_mode == SET_PROPERTY) {
|
| return SetElementWithCallback(object, element, index, value, object,
|
| language_mode);
|
| + } else if (set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
|
| + details.kind() == kAccessor) {
|
| + return RedefineNonconfigurableProperty(
|
| + isolate, isolate->factory()->NewNumberFromUint(index),
|
| + isolate->factory()->undefined_value(), language_mode);
|
| +
|
| + } else if ((set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
|
| + details.IsReadOnly()) ||
|
| + (set_mode == SET_PROPERTY && details.IsReadOnly() &&
|
| + !element->IsTheHole())) {
|
| + // If a value has not been initialized we allow writing to it even if it
|
| + // is read-only (a declared const that has not been initialized).
|
| + return WriteToReadOnlyProperty(
|
| + isolate, object, isolate->factory()->NewNumberFromUint(index),
|
| + isolate->factory()->undefined_value(), language_mode);
|
| } else {
|
| + DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
|
| + element->IsTheHole());
|
| dictionary->UpdateMaxNumberKey(index);
|
| - // If a value has not been initialized we allow writing to it even if it
|
| - // is read-only (a declared const that has not been initialized). If a
|
| - // value is being defined we skip attribute checks completely.
|
| if (set_mode == DEFINE_PROPERTY) {
|
| details = PropertyDetails(attributes, DATA, details.dictionary_index());
|
| dictionary->DetailsAtPut(entry, details);
|
| - } else if (details.IsReadOnly() && !element->IsTheHole()) {
|
| - if (is_sloppy(language_mode)) {
|
| - return isolate->factory()->undefined_value();
|
| - } else {
|
| - Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
|
| - Handle<Object> args[2] = { number, object };
|
| - THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
|
| - HandleVector(args, 2)),
|
| - Object);
|
| - }
|
| }
|
| +
|
| // Elements of the arguments object in slow mode might be slow aliases.
|
| if (is_arguments && element->IsAliasedArgumentsEntry()) {
|
| Handle<AliasedArgumentsEntry> entry =
|
| @@ -12900,9 +12983,10 @@ MaybeHandle<Object> JSObject::SetDictionaryElement(
|
| } else {
|
| Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
|
| Handle<String> name = isolate->factory()->NumberToString(number);
|
| - Handle<Object> args[1] = { name };
|
| - THROW_NEW_ERROR(isolate, NewTypeError("object_not_extensible",
|
| - HandleVector(args, 1)),
|
| + Handle<Object> args[] = {name};
|
| + THROW_NEW_ERROR(isolate,
|
| + NewTypeError("object_not_extensible",
|
| + HandleVector(args, arraysize(args))),
|
| Object);
|
| }
|
| }
|
| @@ -13602,7 +13686,7 @@ bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
|
| MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
|
| Isolate* isolate = array->GetIsolate();
|
| Handle<Name> length = isolate->factory()->length_string();
|
| - Handle<Object> args[2] = { length, array };
|
| + Handle<Object> args[] = {length, array};
|
| THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
|
| HandleVector(args, arraysize(args))),
|
| Object);
|
|
|