i::Handle<i::Object> obj = i::SetElement(
self,
index,
- value_obj);
+ value_obj,
+ i::kNonStrictMode);
has_pending_exception = obj.is_null();
EXCEPTION_BAILOUT_CHECK(false);
return true;
for (int i = 0; i < array->length(); i++) {
Handle<Object> o(array->get(i));
if (CheckBreakPoint(o)) {
- SetElement(break_points_hit, break_points_hit_count++, o);
+ SetElement(break_points_hit,
+ break_points_hit_count++,
+ o,
+ kNonStrictMode);
}
}
} else {
if (CheckBreakPoint(break_point_objects)) {
SetElement(break_points_hit,
break_points_hit_count++,
- break_point_objects);
+ break_point_objects,
+ kNonStrictMode);
}
}
Handle<Object> value,
PropertyAttributes attributes) {
CALL_HEAP_FUNCTION(
- Runtime::ForceSetObjectProperty(object, key, value, attributes), Object);
+ Runtime::ForceSetObjectProperty(
+ object, key, value, attributes),
+ Object);
}
Handle<Object> SetElement(Handle<JSObject> object,
uint32_t index,
- Handle<Object> value) {
+ Handle<Object> value,
+ StrictModeFlag strict_mode) {
if (object->HasPixelElements() || object->HasExternalArrayElements()) {
if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
bool has_exception;
value = number;
}
}
- CALL_HEAP_FUNCTION(object->SetElement(index, *value), Object);
+ CALL_HEAP_FUNCTION(object->SetElement(index, *value, strict_mode), Object);
}
Handle<Object> SetOwnElement(Handle<JSObject> object,
uint32_t index,
- Handle<Object> value) {
+ Handle<Object> value,
+ StrictModeFlag strict_mode) {
ASSERT(!object->HasPixelElements());
ASSERT(!object->HasExternalArrayElements());
- CALL_HEAP_FUNCTION(object->SetElement(index, *value, false), Object);
+ CALL_HEAP_FUNCTION(object->SetElement(index, *value, strict_mode, false),
+ Object);
}
Handle<Object> SetElement(Handle<JSObject> object,
uint32_t index,
- Handle<Object> value);
+ Handle<Object> value,
+ StrictModeFlag strict_mode);
Handle<Object> SetOwnElement(Handle<JSObject> object,
uint32_t index,
- Handle<Object> value);
+ Handle<Object> value,
+ StrictModeFlag strict_mode);
Handle<Object> GetProperty(Handle<JSObject> obj,
const char* name);
uint32_t index;
if (name->AsArrayIndex(&index)) {
HandleScope scope;
- Handle<Object> result = SetElement(receiver, index, value);
+ Handle<Object> result = SetElement(receiver, index, value, strict_mode);
if (result.is_null()) return Failure::Exception();
return *value;
}
uint32_t index;
if (name->AsArrayIndex(&index)) {
HandleScope scope;
- Handle<Object> result = SetElement(receiver, index, value);
+ Handle<Object> result = SetElement(receiver, index, value, strict_mode);
if (result.is_null()) return Failure::Exception();
return *value;
}
}
void WriteChunk(int char_pos1, int char_pos2, int char_len1, int char_len2) {
- SetElement(array_, current_size_, Handle<Object>(Smi::FromInt(char_pos1)));
- SetElement(array_, current_size_ + 1,
- Handle<Object>(Smi::FromInt(char_pos1 + char_len1)));
- SetElement(array_, current_size_ + 2,
- Handle<Object>(Smi::FromInt(char_pos2 + char_len2)));
+ SetElement(array_,
+ current_size_,
+ Handle<Object>(Smi::FromInt(char_pos1)),
+ kNonStrictMode);
+ SetElement(array_,
+ current_size_ + 1,
+ Handle<Object>(Smi::FromInt(char_pos1 + char_len1)),
+ kNonStrictMode);
+ SetElement(array_,
+ current_size_ + 2,
+ Handle<Object>(Smi::FromInt(char_pos2 + char_len2)),
+ kNonStrictMode);
current_size_ += 3;
}
protected:
void SetField(int field_position, Handle<Object> value) {
- SetElement(array_, field_position, value);
+ SetElement(array_, field_position, value, kNonStrictMode);
}
void SetSmiValueField(int field_position, int value) {
- SetElement(array_, field_position, Handle<Smi>(Smi::FromInt(value)));
+ SetElement(array_,
+ field_position,
+ Handle<Smi>(Smi::FromInt(value)),
+ kNonStrictMode);
}
Object* GetField(int field_position) {
return array_->GetElementNoExceptionThrown(field_position);
fun->end_position(), fun->num_parameters(),
current_parent_index_);
current_parent_index_ = len_;
- SetElement(result_, len_, info.GetJSArray());
+ SetElement(result_, len_, info.GetJSArray(), kNonStrictMode);
len_++;
}
list[k] = list[l];
}
for (int i = 0; i < j; i++) {
- SetElement(scope_info_list, scope_info_length, list[i]->name());
+ SetElement(scope_info_list, scope_info_length,
+ list[i]->name(), kNonStrictMode);
scope_info_length++;
SetElement(scope_info_list, scope_info_length,
- Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index())));
+ Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index())),
+ kNonStrictMode);
scope_info_length++;
}
SetElement(scope_info_list, scope_info_length,
- Handle<Object>(Heap::null_value()));
+ Handle<Object>(Heap::null_value()), kNonStrictMode);
scope_info_length++;
outer_scope = outer_scope->outer_scope();
Handle<String> name_handle(String::cast(info->name()));
info_wrapper.SetProperties(name_handle, info->start_position(),
info->end_position(), info);
- SetElement(array, i, info_wrapper.GetJSArray());
+ SetElement(array, i, info_wrapper.GetJSArray(), kNonStrictMode);
}
}
SharedFunctionInfo::cast(wrapper->value()));
if (function->shared() == *shared || IsInlined(*function, *shared)) {
- SetElement(result, i, Handle<Smi>(Smi::FromInt(status)));
+ SetElement(result, i, Handle<Smi>(Smi::FromInt(status)), kNonStrictMode);
return true;
}
}
Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
Handle<Object> replaced(
Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK));
- SetElement(result, i, replaced);
+ SetElement(result, i, replaced, kNonStrictMode);
}
}
return NULL;
// Fill the default values.
for (int i = 0; i < len; i++) {
SetElement(result, i,
- Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)));
+ Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)),
+ kNonStrictMode);
}
// Add error message as an array extra element.
Vector<const char> vector_message(error_message, StrLength(error_message));
Handle<String> str = Factory::NewStringFromAscii(vector_message);
- SetElement(result, len, str);
+ SetElement(result, len, str, kNonStrictMode);
}
return result;
}
Handle<Object> args[2] = { key, holder };
return Top::Throw(*Factory::NewTypeError("strict_read_only_property",
HandleVector(args, 2)));
-
} else {
return value;
}
MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
Object* value,
+ StrictModeFlag strict_mode,
bool check_prototype) {
// Make sure that the top context does not change when doing
// callbacks or interceptor calls.
MaybeObject* raw_result =
this_handle->SetElementWithoutInterceptor(index,
*value_handle,
+ strict_mode,
check_prototype);
RETURN_IF_SCHEDULED_EXCEPTION();
return raw_result;
// elements.
MaybeObject* JSObject::SetFastElement(uint32_t index,
Object* value,
+ StrictModeFlag strict_mode,
bool check_prototype) {
ASSERT(HasFastElements());
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
ASSERT(HasDictionaryElements());
- return SetElement(index, value, check_prototype);
+ return SetElement(index, value, strict_mode, check_prototype);
}
MaybeObject* JSObject::SetElement(uint32_t index,
Object* value,
+ StrictModeFlag strict_mode,
bool check_prototype) {
// Check access rights if needed.
if (IsAccessCheckNeeded() &&
Object* proto = GetPrototype();
if (proto->IsNull()) return value;
ASSERT(proto->IsJSGlobalObject());
- return JSObject::cast(proto)->SetElement(index, value, check_prototype);
+ return JSObject::cast(proto)->SetElement(index,
+ value,
+ strict_mode,
+ check_prototype);
}
// Check for lookup interceptor
if (HasIndexedInterceptor()) {
- return SetElementWithInterceptor(index, value, check_prototype);
+ return SetElementWithInterceptor(index,
+ value,
+ strict_mode,
+ check_prototype);
}
- return SetElementWithoutInterceptor(index, value, check_prototype);
+ return SetElementWithoutInterceptor(index,
+ value,
+ strict_mode,
+ check_prototype);
}
MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
Object* value,
+ StrictModeFlag strict_mode,
bool check_prototype) {
switch (GetElementsKind()) {
case FAST_ELEMENTS:
// Fast case.
- return SetFastElement(index, value, check_prototype);
+ return SetFastElement(index, value, strict_mode, check_prototype);
case PIXEL_ELEMENTS: {
PixelArray* pixels = PixelArray::cast(elements());
return pixels->SetValue(index, value);
return SetElementWithCallback(element, index, value, this);
} else {
dictionary->UpdateMaxNumberKey(index);
- dictionary->ValueAtPut(entry, value);
+ // If put fails instrict mode, throw exception.
+ if (!dictionary->ValueAtPut(entry, value) &&
+ strict_mode == kStrictMode) {
+ Handle<Object> number(Factory::NewNumberFromUint(index));
+ Handle<Object> holder(this);
+ Handle<Object> args[2] = { number, holder };
+ return Top::Throw(
+ *Factory::NewTypeError("strict_read_only_property",
+ HandleVector(args, 2)));
+ }
}
} else {
// Index not already used. Look for an accessor in the prototype chain.
if (check_prototype) {
bool found;
MaybeObject* result =
+ // Strict mode not needed. No-setter case already handled.
SetElementWithCallbackSetterInPrototypes(index, value, &found);
if (found) return result;
}
MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
Object* value,
+ StrictModeFlag strict_mode,
bool check_prototype = true);
// Set the index'th array element.
// A Failure object is returned if GC is needed.
MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
Object* value,
+ StrictModeFlag strict_mode,
bool check_prototype = true);
// Returns the index'th element.
uint32_t index,
Object* value,
JSObject* holder);
- MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(uint32_t index,
- Object* value,
- bool check_prototype);
+ MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(
+ uint32_t index,
+ Object* value,
+ StrictModeFlag strict_mode,
+ bool check_prototype);
MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
uint32_t index,
Object* value,
+ StrictModeFlag strict_mode,
bool check_prototype);
MaybeObject* GetElementPostInterceptor(Object* receiver, uint32_t index);
}
// Set the value for entry.
- void ValueAtPut(int entry, Object* value) {
+ // Returns false if the put wasn't performed due to property being read only.
+ // Returns true on successful put.
+ bool ValueAtPut(int entry, Object* value) {
// Check that this value can actually be written.
PropertyDetails details = DetailsAt(entry);
// If a value has not been initilized we allow writing to it even if
// it is read only (a declared const that has not been initialized).
- if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) return;
- this->set(HashTable<Shape, Key>::EntryToIndex(entry)+1, value);
+ if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) {
+ return false;
+ }
+ this->set(HashTable<Shape, Key>::EntryToIndex(entry) + 1, value);
+ return true;
}
// Returns the property details for the property at entry.
if (value.is_null()) return Handle<Object>::null();
uint32_t index;
if (key->AsArrayIndex(&index)) {
- SetOwnElement(json_object, index, value);
+ SetOwnElement(json_object, index, value, kNonStrictMode);
} else if (key->Equals(Heap::Proto_symbol())) {
// We can't remove the __proto__ accessor since it's hardcoded
// in several places. Instead go along and add the value as
if (key->IsSymbol()) {
if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
// Array index as string (uint32).
- result = SetOwnElement(boilerplate, element_index, value);
+ result = SetOwnElement(boilerplate,
+ element_index,
+ value,
+ kNonStrictMode);
} else {
Handle<String> name(String::cast(*key));
ASSERT(!name->AsArrayIndex(&element_index));
}
} else if (key->ToArrayIndex(&element_index)) {
// Array index (uint32).
- result = SetOwnElement(boilerplate, element_index, value);
+ result = SetOwnElement(boilerplate,
+ element_index,
+ value,
+ kNonStrictMode);
} else {
// Non-uint32 number.
ASSERT(key->IsNumber());
} else {
// The holder is an arguments object.
Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
- Handle<Object> result = SetElement(arguments, index, initial_value);
+ Handle<Object> result = SetElement(arguments, index, initial_value,
+ kNonStrictMode);
if (result.is_null()) return Failure::Exception();
}
} else {
// The holder is an arguments object.
ASSERT((attributes & READ_ONLY) == 0);
Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
- RETURN_IF_EMPTY_HANDLE(SetElement(arguments, index, value));
+ RETURN_IF_EMPTY_HANDLE(SetElement(arguments, index, value, kNonStrictMode));
}
return *value;
}
return *value;
}
- // TODO(1220): Implement SetElement strict mode.
- Handle<Object> result = SetElement(js_object, index, value);
+ Handle<Object> result = SetElement(js_object, index, value, strict_mode);
if (result.is_null()) return Failure::Exception();
return *value;
}
if (key->IsString()) {
Handle<Object> result;
if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
- result = SetElement(js_object, index, value);
+ result = SetElement(js_object, index, value, strict_mode);
} else {
Handle<String> key_string = Handle<String>::cast(key);
key_string->TryFlatten();
Handle<String> name = Handle<String>::cast(converted);
if (name->AsArrayIndex(&index)) {
- // TODO(1220): Implement SetElement strict mode.
- return js_object->SetElement(index, *value);
+ return js_object->SetElement(index, *value, strict_mode);
} else {
return js_object->SetProperty(*name, *value, attr, strict_mode);
}
return *value;
}
- return js_object->SetElement(index, *value);
+ return js_object->SetElement(index, *value, kNonStrictMode);
}
if (key->IsString()) {
if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
- return js_object->SetElement(index, *value);
+ return js_object->SetElement(index, *value, kNonStrictMode);
} else {
Handle<String> key_string = Handle<String>::cast(key);
key_string->TryFlatten();
Handle<String> name = Handle<String>::cast(converted);
if (name->AsArrayIndex(&index)) {
- return js_object->SetElement(index, *value);
+ return js_object->SetElement(index, *value, kNonStrictMode);
} else {
return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
}
if ((attributes & READ_ONLY) == 0) {
// Context is a fixed array and set cannot fail.
Context::cast(*holder)->set(index, *value);
+ } else if (strict_mode == kStrictMode) {
+ // Setting read only property in strict mode.
+ Handle<Object> error =
+ Factory::NewTypeError("strict_cannot_assign",
+ HandleVector(&name, 1));
+ return Top::Throw(*error);
}
} else {
ASSERT((attributes & READ_ONLY) == 0);
Handle<Object> result =
- SetElement(Handle<JSObject>::cast(holder), index, value);
+ SetElement(Handle<JSObject>::cast(holder), index, value, strict_mode);
if (result.is_null()) {
ASSERT(Top::has_pending_exception());
return Failure::Exception();
if (elements->get(i) == element) return Heap::false_value();
}
Object* obj;
- { MaybeObject* maybe_obj = array->SetFastElement(length, element);
+ // Strict not needed. Used for cycle detection in Array join implementation.
+ { MaybeObject* maybe_obj = array->SetFastElement(length, element,
+ kNonStrictMode);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
return Heap::true_value();
Handle<Object> tmp2 = GetElement(jsobject, index2);
RETURN_IF_EMPTY_HANDLE(tmp2);
- RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index1, tmp2));
- RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index2, tmp1));
+ RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index1, tmp2, kStrictMode));
+ RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index2, tmp1, kStrictMode));
return Heap::undefined_value();
}
// position by making sure that we have position information
// recorded for all binary ICs.
if (GetElement(map_, position)->IsUndefined()) {
- SetElement(map_, position, target);
+ SetElement(map_, position, target, kNonStrictMode);
}
} else if (state == MONOMORPHIC) {
if (target->kind() != Code::CALL_IC ||
target->check_type() == RECEIVER_MAP_CHECK) {
Handle<Map> map = Handle<Map>(target->FindFirstMap());
if (*map == NULL) {
- SetElement(map_, position, target);
+ SetElement(map_, position, target, kNonStrictMode);
} else {
- SetElement(map_, position, map);
+ SetElement(map_, position, map, kNonStrictMode);
}
} else {
ASSERT(target->kind() == Code::CALL_IC);
CheckType check = target->check_type();
ASSERT(check != RECEIVER_MAP_CHECK);
- SetElement(map_, position, Handle<Object>(Smi::FromInt(check)));
+ SetElement(map_, position,
+ Handle<Object>(Smi::FromInt(check)), kNonStrictMode);
ASSERT(Smi::cast(*GetElement(map_, position))->value() == check);
}
} else if (state == MEGAMORPHIC) {
- SetElement(map_, position, target);
+ SetElement(map_, position, target, kNonStrictMode);
}
}
}
CHECK_EQ(28, result->Int32Value());
i::Handle<i::Smi> value(i::Smi::FromInt(2));
- i::SetElement(jsobj, 1, value);
+ i::SetElement(jsobj, 1, value, i::kNonStrictMode);
CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
*value.location() = i::Smi::FromInt(256);
- i::SetElement(jsobj, 1, value);
+ i::SetElement(jsobj, 1, value, i::kNonStrictMode);
CHECK_EQ(255,
i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
*value.location() = i::Smi::FromInt(-1);
- i::SetElement(jsobj, 1, value);
+ i::SetElement(jsobj, 1, value, i::kNonStrictMode);
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {"
CHECK(array->HasFastElements()); // Must be in fast mode.
// array[length] = name.
- ok = array->SetElement(0, *name)->ToObjectChecked();
+ ok = array->SetElement(0, *name, kNonStrictMode)->ToObjectChecked();
CHECK_EQ(Smi::FromInt(1), array->length());
CHECK_EQ(array->GetElement(0), *name);
CHECK(array->HasDictionaryElements()); // Must be in slow mode.
// array[length] = name.
- ok = array->SetElement(int_length, *name)->ToObjectChecked();
+ ok = array->SetElement(int_length, *name, kNonStrictMode)->ToObjectChecked();
uint32_t new_int_length = 0;
CHECK(array->length()->ToArrayIndex(&new_int_length));
CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
obj->SetProperty(
*second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
- Object* ok = obj->SetElement(0, *first)->ToObjectChecked();
+ Object* ok = obj->SetElement(0, *first, kNonStrictMode)->ToObjectChecked();
- ok = obj->SetElement(1, *second)->ToObjectChecked();
+ ok = obj->SetElement(1, *second, kNonStrictMode)->ToObjectChecked();
// Make the clone.
Handle<JSObject> clone = Copy(obj);
clone->SetProperty(
*second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
- ok = clone->SetElement(0, *second)->ToObjectChecked();
- ok = clone->SetElement(1, *first)->ToObjectChecked();
+ ok = clone->SetElement(0, *second, kNonStrictMode)->ToObjectChecked();
+ ok = clone->SetElement(1, *first, kNonStrictMode)->ToObjectChecked();
CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
assertEquals(o[100000], 31);
}
})();
+
+
+(function TestSetElementWithoutSetter() {
+ "use strict";
+
+ var o = { };
+ Object.defineProperty(o, 0, { get : function() { } });
+
+ var zero_smi = 0;
+ var zero_number = new Number(0);
+ var zero_symbol = "0";
+ var zero_string = "-0-".substring(1,2);
+
+ assertThrows(function() { o[zero_smi] = "new value"; }, TypeError);
+ assertThrows(function() { o[zero_number] = "new value"; }, TypeError);
+ assertThrows(function() { o[zero_symbol] = "new value"; }, TypeError);
+ assertThrows(function() { o[zero_string] = "new value"; }, TypeError);
+})();
+
+
+(function TestSetElementNonConfigurable() {
+ "use strict";
+ var frozen = Object.freeze({});
+ var sealed = Object.seal({});
+
+ var zero_number = 0;
+ var zero_symbol = "0";
+ var zero_string = "-0-".substring(1,2);
+
+ assertThrows(function() { frozen[zero_number] = "value"; }, TypeError);
+ assertThrows(function() { sealed[zero_number] = "value"; }, TypeError);
+ assertThrows(function() { frozen[zero_symbol] = "value"; }, TypeError);
+ assertThrows(function() { sealed[zero_symbol] = "value"; }, TypeError);
+ assertThrows(function() { frozen[zero_string] = "value"; }, TypeError);
+ assertThrows(function() { sealed[zero_string] = "value"; }, TypeError);
+})();
+
+
+(function TestAssignmentToReadOnlyElement() {
+ "use strict";
+
+ var o = {};
+ Object.defineProperty(o, 7, { value: 17 });
+
+ var seven_smi = 7;
+ var seven_number = new Number(7);
+ var seven_symbol = "7";
+ var seven_string = "-7-".substring(1,2);
+
+ // Index with number.
+ assertThrows(function() { o[seven_smi] = "value"; }, TypeError);
+ assertThrows(function() { o[seven_smi] += 10; }, TypeError);
+ assertThrows(function() { o[seven_smi] -= 10; }, TypeError);
+ assertThrows(function() { o[seven_smi] *= 10; }, TypeError);
+ assertThrows(function() { o[seven_smi] /= 10; }, TypeError);
+ assertThrows(function() { o[seven_smi]++; }, TypeError);
+ assertThrows(function() { o[seven_smi]--; }, TypeError);
+ assertThrows(function() { ++o[seven_smi]; }, TypeError);
+ assertThrows(function() { --o[seven_smi]; }, TypeError);
+
+ assertThrows(function() { o[seven_number] = "value"; }, TypeError);
+ assertThrows(function() { o[seven_number] += 10; }, TypeError);
+ assertThrows(function() { o[seven_number] -= 10; }, TypeError);
+ assertThrows(function() { o[seven_number] *= 10; }, TypeError);
+ assertThrows(function() { o[seven_number] /= 10; }, TypeError);
+ assertThrows(function() { o[seven_number]++; }, TypeError);
+ assertThrows(function() { o[seven_number]--; }, TypeError);
+ assertThrows(function() { ++o[seven_number]; }, TypeError);
+ assertThrows(function() { --o[seven_number]; }, TypeError);
+
+ assertThrows(function() { o[seven_symbol] = "value"; }, TypeError);
+ assertThrows(function() { o[seven_symbol] += 10; }, TypeError);
+ assertThrows(function() { o[seven_symbol] -= 10; }, TypeError);
+ assertThrows(function() { o[seven_symbol] *= 10; }, TypeError);
+ assertThrows(function() { o[seven_symbol] /= 10; }, TypeError);
+ assertThrows(function() { o[seven_symbol]++; }, TypeError);
+ assertThrows(function() { o[seven_symbol]--; }, TypeError);
+ assertThrows(function() { ++o[seven_symbol]; }, TypeError);
+ assertThrows(function() { --o[seven_symbol]; }, TypeError);
+
+ assertThrows(function() { o[seven_string] = "value"; }, TypeError);
+ assertThrows(function() { o[seven_string] += 10; }, TypeError);
+ assertThrows(function() { o[seven_string] -= 10; }, TypeError);
+ assertThrows(function() { o[seven_string] *= 10; }, TypeError);
+ assertThrows(function() { o[seven_string] /= 10; }, TypeError);
+ assertThrows(function() { o[seven_string]++; }, TypeError);
+ assertThrows(function() { o[seven_string]--; }, TypeError);
+ assertThrows(function() { ++o[seven_string]; }, TypeError);
+ assertThrows(function() { --o[seven_string]; }, TypeError);
+
+ assertEquals(o[seven_number], 17);
+ assertEquals(o[seven_symbol], 17);
+ assertEquals(o[seven_string], 17);
+})();
+
+
+(function TestAssignmentToReadOnlyLoop() {
+ "use strict";
+
+ var o = {};
+ Object.defineProperty(o, 7, { value: 17 });
+
+ var seven_smi = 7;
+ var seven_number = new Number(7);
+ var seven_symbol = "7";
+ var seven_string = "-7-".substring(1,2);
+
+ for (var i = 0; i < 10; i ++) {
+ assertThrows(function() { o[seven_smi] = "value" }, TypeError);
+ assertThrows(function() { o[seven_number] = "value" }, TypeError);
+ assertThrows(function() { o[seven_symbol] = "value" }, TypeError);
+ assertThrows(function() { o[seven_string] = "value" }, TypeError);
+ }
+
+ assertEquals(o[7], 17);
+})();