Passing strict mode throughout SetElement.
authormmaly@chromium.org <mmaly@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 4 Mar 2011 00:21:52 +0000 (00:21 +0000)
committermmaly@chromium.org <mmaly@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 4 Mar 2011 00:21:52 +0000 (00:21 +0000)
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

14 files changed:
src/api.cc
src/debug.cc
src/handles.cc
src/handles.h
src/ic.cc
src/liveedit.cc
src/objects.cc
src/objects.h
src/parser.cc
src/runtime.cc
src/type-info.cc
test/cctest/test-api.cc
test/cctest/test-heap.cc
test/mjsunit/strict-mode.js

index b77e450..555af84 100644 (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;
index c473941..d91ad92 100644 (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);
     }
   }
 
index d91855c..efef095 100644 (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);
 }
 
 
index ccdf4d5..bb51968 100644 (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);
index 2d666d6..dfbbb91 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -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;
     }
index a395c51..744ed49 100644 (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;
 }
index a081b59..4c00591 100644 (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;
         }
index fc1c73a..d7b87c6 100644 (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.
index c8b921b..3c361a7 100644 (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
index 4a5d3b9..c69e96f 100644 (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();
 }
index 0bb7262..3438ff8 100644 (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);
     }
   }
 }
index f450a34..cd26412 100644 (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++) {"
index 9cce01e..4cc7f8b 100644 (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));
index 4071232..9137f8d 100644 (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);
+})();