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:
parent
a0f0faa8e4
commit
9dc156ac62
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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++) {"
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user