Passing strict mode throughout SetElement.

Throw if assigning to read only element.
Adding tests for element assignment in strict mode.

Fix tests for strict mode SetElement.

Review URL: http://codereview.chromium.org/6613005/

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7053 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mmaly@chromium.org 2011-03-04 00:21:52 +00:00
parent a0f0faa8e4
commit 9dc156ac62
14 changed files with 260 additions and 72 deletions

View File

@ -2304,7 +2304,8 @@ bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
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;

View File

@ -1013,14 +1013,18 @@ Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
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);
}
}

View File

@ -265,7 +265,9 @@ Handle<Object> ForceSetProperty(Handle<JSObject> object,
Handle<Object> value,
PropertyAttributes attributes) {
CALL_HEAP_FUNCTION(
Runtime::ForceSetObjectProperty(object, key, value, attributes), Object);
Runtime::ForceSetObjectProperty(
object, key, value, attributes),
Object);
}
@ -426,7 +428,8 @@ Handle<String> SubString(Handle<String> str,
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;
@ -435,16 +438,18 @@ Handle<Object> SetElement(Handle<JSObject> object,
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);
}

View File

@ -266,11 +266,13 @@ Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> 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);

View File

@ -1405,7 +1405,7 @@ MaybeObject* StoreIC::Store(State state,
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;
}
@ -1631,7 +1631,7 @@ MaybeObject* KeyedStoreIC::Store(State state,
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;
}

View File

@ -286,11 +286,18 @@ class CompareOutputArrayWriter {
}
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;
}
@ -545,10 +552,13 @@ class JSArrayBasedStruct {
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);
@ -687,7 +697,7 @@ class FunctionInfoListener {
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_++;
}
@ -767,14 +777,16 @@ class FunctionInfoListener {
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();
@ -817,7 +829,7 @@ void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
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);
}
}
@ -1315,7 +1327,7 @@ static bool CheckActivation(Handle<JSArray> shared_info_array,
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;
}
}
@ -1520,7 +1532,7 @@ static const char* DropActivationsInActiveThread(
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;
@ -1561,7 +1573,8 @@ Handle<JSArray> LiveEdit::CheckAndDropActivations(
// 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);
}
@ -1580,7 +1593,7 @@ Handle<JSArray> LiveEdit::CheckAndDropActivations(
// 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;
}

View File

@ -1956,7 +1956,6 @@ MaybeObject* JSObject::SetProperty(LookupResult* result,
Handle<Object> args[2] = { key, holder };
return Top::Throw(*Factory::NewTypeError("strict_read_only_property",
HandleVector(args, 2)));
} else {
return value;
}
@ -6900,6 +6899,7 @@ bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
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.
@ -6926,6 +6926,7 @@ MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
MaybeObject* raw_result =
this_handle->SetElementWithoutInterceptor(index,
*value_handle,
strict_mode,
check_prototype);
RETURN_IF_SCHEDULED_EXCEPTION();
return raw_result;
@ -7039,6 +7040,7 @@ MaybeObject* JSObject::SetElementWithCallback(Object* structure,
// elements.
MaybeObject* JSObject::SetFastElement(uint32_t index,
Object* value,
StrictModeFlag strict_mode,
bool check_prototype) {
ASSERT(HasFastElements());
@ -7095,12 +7097,13 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
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() &&
@ -7115,25 +7118,35 @@ MaybeObject* JSObject::SetElement(uint32_t index,
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);
@ -7182,13 +7195,23 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
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;
}

View File

@ -1546,12 +1546,14 @@ class JSObject: public HeapObject {
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.
@ -1811,12 +1813,15 @@ class JSObject: public HeapObject {
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);
@ -2453,13 +2458,18 @@ class Dictionary: public HashTable<Shape, Key> {
}
// 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.

View File

@ -4117,7 +4117,7 @@ Handle<Object> JsonParser::ParseJsonObject() {
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

View File

@ -335,7 +335,10 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
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));
@ -344,7 +347,10 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
}
} 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());
@ -1186,7 +1192,8 @@ static MaybeObject* Runtime_DeclareContextSlot(Arguments args) {
} 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 {
@ -1471,7 +1478,7 @@ static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) {
// 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;
}
@ -3814,8 +3821,7 @@ MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
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;
}
@ -3823,7 +3829,7 @@ MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
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();
@ -3840,8 +3846,7 @@ MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
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);
}
@ -3868,12 +3873,12 @@ MaybeObject* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object,
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();
@ -3890,7 +3895,7 @@ MaybeObject* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object,
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);
}
@ -7562,11 +7567,17 @@ static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
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();
@ -8070,7 +8081,9 @@ static MaybeObject* Runtime_PushIfAbsent(Arguments args) {
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();
@ -8673,8 +8686,8 @@ static MaybeObject* Runtime_SwapElements(Arguments args) {
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();
}

View File

@ -337,26 +337,27 @@ void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
// 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);
}
}
}

View File

@ -10617,14 +10617,14 @@ THREADED_TEST(PixelArray) {
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++) {"

View File

@ -670,7 +670,7 @@ TEST(JSArray) {
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);
@ -685,7 +685,7 @@ TEST(JSArray) {
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);
@ -712,9 +712,9 @@ TEST(JSObjectCopy) {
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);
@ -732,8 +732,8 @@ TEST(JSObjectCopy) {
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));

View File

@ -828,3 +828,119 @@ repeat(10, function() { testAssignToUndefined(false); });
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);
})();