Author: whe...@chromium.org
Date: Wed Jun 10 08:33:31 2009
New Revision: 2138

Modified:
    branches/bleeding_edge/src/objects.cc
    branches/bleeding_edge/src/objects.h
    branches/bleeding_edge/test/cctest/test-api.cc

Log:
Make JSObjects with both indexed interceptors and indexed accessors work  
safely.
Review URL: http://codereview.chromium.org/118499

Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc       (original)
+++ branches/bleeding_edge/src/objects.cc       Wed Jun 10 08:33:31 2009
@@ -5203,27 +5203,6 @@
  }


-Object* JSObject::SetElementPostInterceptor(uint32_t index, Object* value)  
{
-  if (HasFastElements()) return SetFastElement(index, value);
-
-  // Dictionary case.
-  ASSERT(!HasFastElements());
-
-  FixedArray* elms = FixedArray::cast(elements());
-  Object* result = Dictionary::cast(elms)->AtNumberPut(index, value);
-  if (result->IsFailure()) return result;
-  if (elms != FixedArray::cast(result)) {
-    set_elements(FixedArray::cast(result));
-  }
-
-  if (IsJSArray()) {
-    return JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
-  }
-
-  return value;
-}
-
-
  Object* JSObject::SetElementWithInterceptor(uint32_t index, Object* value)  
{
    // Make sure that the top context does not change when doing
    // callbacks or interceptor calls.
@@ -5250,7 +5229,7 @@
      if (!result.IsEmpty()) return *value_handle;
    }
    Object* raw_result =
-      this_handle->SetElementPostInterceptor(index, *value_handle);
+      this_handle->SetElementWithoutInterceptor(index, *value_handle);
    RETURN_IF_SCHEDULED_EXCEPTION();
    return raw_result;
  }
@@ -5332,6 +5311,11 @@
      return SetElementWithInterceptor(index, value);
    }

+  return SetElementWithoutInterceptor(index, value);
+}
+
+
+Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object*  
value) {
    // Fast case.
    if (HasFastElements()) return SetFastElement(index, value);

@@ -5438,7 +5422,21 @@
      Dictionary* dictionary = element_dictionary();
      int entry = dictionary->FindNumberEntry(index);
      if (entry != -1) {
-      return dictionary->ValueAt(entry);
+      Object* element = dictionary->ValueAt(entry);
+      PropertyDetails details = dictionary->DetailsAt(entry);
+      if (details.type() == CALLBACKS) {
+        // Only accessors allowed as elements.
+        FixedArray* structure = FixedArray::cast(element);
+        Object* getter = structure->get(kGetterIndex);
+        if (getter->IsJSFunction()) {
+          return GetPropertyWithDefinedGetter(receiver,
+                                              JSFunction::cast(getter));
+        } else {
+          // Getter is not a function.
+          return Heap::undefined_value();
+        }
+      }
+      return element;
      }
    }


Modified: branches/bleeding_edge/src/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h        (original)
+++ branches/bleeding_edge/src/objects.h        Wed Jun 10 08:33:31 2009
@@ -1531,7 +1531,7 @@

   private:
    Object* SetElementWithInterceptor(uint32_t index, Object* value);
-  Object* SetElementPostInterceptor(uint32_t index, Object* value);
+  Object* SetElementWithoutInterceptor(uint32_t index, Object* value);

    Object* GetElementPostInterceptor(JSObject* receiver, uint32_t index);


Modified: branches/bleeding_edge/test/cctest/test-api.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-api.cc      (original)
+++ branches/bleeding_edge/test/cctest/test-api.cc      Wed Jun 10 08:33:31 2009
@@ -551,6 +551,7 @@
      CHECK(isymbol->IsSymbol());
    }
    i::Heap::CollectAllGarbage();
+  i::Heap::CollectAllGarbage();
  }


@@ -568,6 +569,7 @@
      CHECK(isymbol->IsSymbol());
    }
    i::Heap::CollectAllGarbage();
+  i::Heap::CollectAllGarbage();
  }


@@ -2281,7 +2283,7 @@
  }


-THREADED_TEST(NamedInterceporPropertyRead) {
+THREADED_TEST(NamedInterceptorPropertyRead) {
    v8::HandleScope scope;
    Local<ObjectTemplate> templ = ObjectTemplate::New();
    templ->SetNamedPropertyHandler(XPropertyGetter);
@@ -2293,6 +2295,58 @@
      CHECK_EQ(result, v8_str("x"));
    }
  }
+
+
+static v8::Handle<Value> IndexedPropertyGetter(uint32_t index,
+                                               const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (index == 37) {
+    return v8::Handle<Value>(v8_num(625));
+  }
+  return v8::Handle<Value>();
+}
+
+
+static v8::Handle<Value> IndexedPropertySetter(uint32_t index,
+                                               Local<Value> value,
+                                               const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (index == 39) {
+    return value;
+  }
+  return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
+                                   IndexedPropertySetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("obj"), templ->NewInstance());
+  Local<Script> getter_script = Script::Compile(v8_str(
+      "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
+  Local<Script> setter_script = Script::Compile(v8_str(
+      "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
+      "obj[17] = 23;"
+      "obj.foo;"));
+  Local<Script> interceptor_setter_script = Script::Compile(v8_str(
+      "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
+      "obj[39] = 47;"
+      "obj.foo;"));  // This setter should not run, due to the interceptor.
+  Local<Script> interceptor_getter_script = Script::Compile(v8_str(
+      "obj[37];"));
+  Local<Value> result = getter_script->Run();
+  CHECK_EQ(v8_num(5), result);
+  result = setter_script->Run();
+  CHECK_EQ(v8_num(23), result);
+  result = interceptor_setter_script->Run();
+  CHECK_EQ(v8_num(23), result);
+  result = interceptor_getter_script->Run();
+  CHECK_EQ(v8_num(625), result);
+}
+

  THREADED_TEST(MultiContexts) {
    v8::HandleScope scope;

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to