Fix inline constructors for Harmony Proxy prototypes.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 10 Jul 2012 11:28:33 +0000 (11:28 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 10 Jul 2012 11:28:33 +0000 (11:28 +0000)
R=rossberg@chromium.org
BUG=v8:2225
TEST=mjsunit/regress/regress-2225

Review URL: https://chromiumcodereview.appspot.com/10736009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12028 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/objects.cc
src/runtime.cc
test/mjsunit/regress/regress-2225.js [new file with mode: 0644]

index cd2eebf0bcaa160cc0de20d4f794f858d928f5e7..3335b21148b618e48d9e1f2e7ccfdc82e6afa2f4 100644 (file)
@@ -4862,9 +4862,9 @@ Object* JSObject::LookupAccessor(String* name, AccessorComponent component) {
   if (name->AsArrayIndex(&index)) {
     for (Object* obj = this;
          obj != heap->null_value();
-         obj = JSObject::cast(obj)->GetPrototype()) {
-      JSObject* js_object = JSObject::cast(obj);
-      if (js_object->HasDictionaryElements()) {
+         obj = JSReceiver::cast(obj)->GetPrototype()) {
+      if (obj->IsJSObject() && JSObject::cast(obj)->HasDictionaryElements()) {
+        JSObject* js_object = JSObject::cast(obj);
         SeededNumberDictionary* dictionary = js_object->element_dictionary();
         int entry = dictionary->FindEntry(index);
         if (entry != SeededNumberDictionary::kNotFound) {
@@ -4879,9 +4879,9 @@ Object* JSObject::LookupAccessor(String* name, AccessorComponent component) {
   } else {
     for (Object* obj = this;
          obj != heap->null_value();
-         obj = JSObject::cast(obj)->GetPrototype()) {
+         obj = JSReceiver::cast(obj)->GetPrototype()) {
       LookupResult result(heap->isolate());
-      JSObject::cast(obj)->LocalLookup(name, &result);
+      JSReceiver::cast(obj)->LocalLookup(name, &result);
       if (result.IsProperty()) {
         if (result.IsReadOnly()) return heap->undefined_value();
         if (result.IsPropertyCallbacks()) {
@@ -7790,25 +7790,34 @@ bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
     return false;
   }
 
-  // If the prototype is null inline constructors cause no problems.
-  if (!prototype->IsJSObject()) {
-    ASSERT(prototype->IsNull());
-    return true;
-  }
-
   Heap* heap = GetHeap();
 
-  // Traverse the proposed prototype chain looking for setters for properties of
-  // the same names as are set by the inline constructor.
+  // Traverse the proposed prototype chain looking for properties of the
+  // same names as are set by the inline constructor.
   for (Object* obj = prototype;
        obj != heap->null_value();
        obj = obj->GetPrototype()) {
-    JSObject* js_object = JSObject::cast(obj);
+    JSReceiver* receiver = JSReceiver::cast(obj);
     for (int i = 0; i < this_property_assignments_count(); i++) {
       LookupResult result(heap->isolate());
       String* name = GetThisPropertyAssignmentName(i);
-      js_object->LocalLookupRealNamedProperty(name, &result);
-      if (result.IsCallbacks()) return false;
+      receiver->LocalLookup(name, &result);
+      if (result.IsProperty()) {
+        switch (result.type()) {
+          case NORMAL:
+          case FIELD:
+          case CONSTANT_FUNCTION:
+            break;
+          case INTERCEPTOR:
+          case CALLBACKS:
+          case HANDLER:
+            return false;
+          case TRANSITION:
+          case NONEXISTENT:
+            UNREACHABLE();
+            break;
+        }
+      }
     }
   }
 
index 93479d89a7daa1e009983eda722e73104a4decd0..be6e9353ded45b3a2718b156b1af1f87596fd0f9 100644 (file)
@@ -10257,11 +10257,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
 
 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
   ASSERT(args.length() == 3);
-  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
   CONVERT_ARG_CHECKED(String, name, 1);
   CONVERT_SMI_ARG_CHECKED(flag, 2);
   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
-  return obj->LookupAccessor(name, component);
+  if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
+  return JSObject::cast(receiver)->LookupAccessor(name, component);
 }
 
 
diff --git a/test/mjsunit/regress/regress-2225.js b/test/mjsunit/regress/regress-2225.js
new file mode 100644 (file)
index 0000000..9957d8d
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-proxies
+
+var proxy_has_x = false;
+var proxy = Proxy.create({ getPropertyDescriptor:function(key) {
+  assertSame('x', key);
+  if (proxy_has_x) {
+    return { configurable:true, writable:false, value:19 };
+  }
+}});
+
+// Test __lookupGetter__/__lookupSetter__ with proxy.
+assertSame(undefined, Object.prototype.__lookupGetter__.call(proxy, 'foo'));
+assertSame(undefined, Object.prototype.__lookupSetter__.call(proxy, 'bar'));
+assertSame(undefined, Object.prototype.__lookupGetter__.call(proxy, '123'));
+assertSame(undefined, Object.prototype.__lookupSetter__.call(proxy, '456'));
+
+// Test __lookupGetter__/__lookupSetter__ with proxy in prototype chain.
+var object = Object.create(proxy);
+assertSame(undefined, Object.prototype.__lookupGetter__.call(object, 'foo'));
+assertSame(undefined, Object.prototype.__lookupSetter__.call(object, 'bar'));
+assertSame(undefined, Object.prototype.__lookupGetter__.call(object, '123'));
+assertSame(undefined, Object.prototype.__lookupSetter__.call(object, '456'));
+
+// Test inline constructors with proxy as prototype.
+function f() { this.x = 23; }
+f.prototype = proxy;
+proxy_has_x = false;
+assertSame(23, new f().x);
+proxy_has_x = true;
+assertSame(19, new f().x);
+
+// Test inline constructors with proxy in prototype chain.
+function g() { this.x = 42; }
+g.prototype.__proto__ = proxy;
+proxy_has_x = false;
+assertSame(42, new g().x);
+proxy_has_x = true;
+assertSame(19, new g().x);