Submit Object.getOwnPropertyNames patch by Pavel Feldman. See http://codereview.chrom...
authormikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 15 Jan 2010 15:34:32 +0000 (15:34 +0000)
committermikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 15 Jan 2010 15:34:32 +0000 (15:34 +0000)
Add copyright to regression test to fix build broken by r3619.

TBR=sgjesse@chromium.org

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

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

src/messages.js
src/mirror-delay.js
src/runtime.cc
src/runtime.h
src/v8natives.js
test/mjsunit/object-get-own-property-names.js [new file with mode: 0644]
test/mjsunit/regress/regress-crbug-3184.js

index d3c8fcc..df008c9 100644 (file)
@@ -178,8 +178,7 @@ function FormatMessage(message) {
       result_not_primitive:         "Result of %0 must be a primitive, was %1",
       invalid_json:                 "String '%0' is not valid JSON",
       circular_structure:           "Converting circular structure to JSON",
-      object_keys_non_object:       "Object.keys called on non-object",
-      object_get_prototype_non_object: "Object.getPrototypeOf called on non-object",
+      obj_ctor_property_non_object: "Object.%0 called on non-object",
       array_indexof_not_defined:    "Array.getIndexOf: Argument undefined"
     };
   }
index ba663b2..0269f1f 100644 (file)
@@ -600,14 +600,14 @@ ObjectMirror.prototype.protoObject = function() {
 
 ObjectMirror.prototype.hasNamedInterceptor = function() {
   // Get information on interceptors for this object.
-  var x = %DebugInterceptorInfo(this.value_);
+  var x = %GetInterceptorInfo(this.value_);
   return (x & 2) != 0;
 };
 
 
 ObjectMirror.prototype.hasIndexedInterceptor = function() {
   // Get information on interceptors for this object.
-  var x = %DebugInterceptorInfo(this.value_);
+  var x = %GetInterceptorInfo(this.value_);
   return (x & 1) != 0;
 };
 
@@ -631,13 +631,13 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
   // Find all the named properties.
   if (kind & PropertyKind.Named) {
     // Get the local property names.
-    propertyNames = %DebugLocalPropertyNames(this.value_);
+    propertyNames = %GetLocalPropertyNames(this.value_);
     total += propertyNames.length;
 
     // Get names for named interceptor properties if any.
     if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
       var namedInterceptorNames =
-          %DebugNamedInterceptorPropertyNames(this.value_);
+          %GetNamedInterceptorPropertyNames(this.value_);
       if (namedInterceptorNames) {
         propertyNames = propertyNames.concat(namedInterceptorNames);
         total += namedInterceptorNames.length;
@@ -648,13 +648,13 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
   // Find all the indexed properties.
   if (kind & PropertyKind.Indexed) {
     // Get the local element names.
-    elementNames = %DebugLocalElementNames(this.value_);
+    elementNames = %GetLocalElementNames(this.value_);
     total += elementNames.length;
 
     // Get names for indexed interceptor properties.
     if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
       var indexedInterceptorNames =
-          %DebugIndexedInterceptorElementNames(this.value_);
+          %GetIndexedInterceptorElementNames(this.value_);
       if (indexedInterceptorNames) {
         elementNames = elementNames.concat(indexedInterceptorNames);
         total += indexedInterceptorNames.length;
index 617dfaa..5c45692 100644 (file)
@@ -3213,6 +3213,156 @@ static Object* Runtime_GetPropertyNamesFast(Arguments args) {
 }
 
 
+// Find the length of the prototype chain that is to to handled as one. If a
+// prototype object is hidden it is to be viewed as part of the the object it
+// is prototype for.
+static int LocalPrototypeChainLength(JSObject* obj) {
+  int count = 1;
+  Object* proto = obj->GetPrototype();
+  while (proto->IsJSObject() &&
+         JSObject::cast(proto)->map()->is_hidden_prototype()) {
+    count++;
+    proto = JSObject::cast(proto)->GetPrototype();
+  }
+  return count;
+}
+
+
+// Return the names of the local named properties.
+// args[0]: object
+static Object* Runtime_GetLocalPropertyNames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  if (!args[0]->IsJSObject()) {
+    return Heap::undefined_value();
+  }
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  // Skip the global proxy as it has no properties and always delegates to the
+  // real global object.
+  if (obj->IsJSGlobalProxy()) {
+    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
+  }
+
+  // Find the number of objects making up this.
+  int length = LocalPrototypeChainLength(*obj);
+
+  // Find the number of local properties for each of the objects.
+  int* local_property_count = NewArray<int>(length);
+  int total_property_count = 0;
+  Handle<JSObject> jsproto = obj;
+  for (int i = 0; i < length; i++) {
+    int n;
+    n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
+    local_property_count[i] = n;
+    total_property_count += n;
+    if (i < length - 1) {
+      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
+    }
+  }
+
+  // Allocate an array with storage for all the property names.
+  Handle<FixedArray> names = Factory::NewFixedArray(total_property_count);
+
+  // Get the property names.
+  jsproto = obj;
+  int proto_with_hidden_properties = 0;
+  for (int i = 0; i < length; i++) {
+    jsproto->GetLocalPropertyNames(*names,
+                                   i == 0 ? 0 : local_property_count[i - 1]);
+    if (!GetHiddenProperties(jsproto, false)->IsUndefined()) {
+      proto_with_hidden_properties++;
+    }
+    if (i < length - 1) {
+      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
+    }
+  }
+
+  // Filter out name of hidden propeties object.
+  if (proto_with_hidden_properties > 0) {
+    Handle<FixedArray> old_names = names;
+    names = Factory::NewFixedArray(
+        names->length() - proto_with_hidden_properties);
+    int dest_pos = 0;
+    for (int i = 0; i < total_property_count; i++) {
+      Object* name = old_names->get(i);
+      if (name == Heap::hidden_symbol()) {
+        continue;
+      }
+      names->set(dest_pos++, name);
+    }
+  }
+
+  DeleteArray(local_property_count);
+  return *Factory::NewJSArrayWithElements(names);
+}
+
+
+// Return the names of the local indexed properties.
+// args[0]: object
+static Object* Runtime_GetLocalElementNames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  if (!args[0]->IsJSObject()) {
+    return Heap::undefined_value();
+  }
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
+  Handle<FixedArray> names = Factory::NewFixedArray(n);
+  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
+  return *Factory::NewJSArrayWithElements(names);
+}
+
+
+// Return information on whether an object has a named or indexed interceptor.
+// args[0]: object
+static Object* Runtime_GetInterceptorInfo(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  if (!args[0]->IsJSObject()) {
+    return Smi::FromInt(0);
+  }
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  int result = 0;
+  if (obj->HasNamedInterceptor()) result |= 2;
+  if (obj->HasIndexedInterceptor()) result |= 1;
+
+  return Smi::FromInt(result);
+}
+
+
+// Return property names from named interceptor.
+// args[0]: object
+static Object* Runtime_GetNamedInterceptorPropertyNames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  if (obj->HasNamedInterceptor()) {
+    v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
+    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+  }
+  return Heap::undefined_value();
+}
+
+
+// Return element names from indexed interceptor.
+// args[0]: object
+static Object* Runtime_GetIndexedInterceptorElementNames(Arguments args) {
+  HandleScope scope;
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+
+  if (obj->HasIndexedInterceptor()) {
+    v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
+    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+  }
+  return Heap::undefined_value();
+}
+
+
 static Object* Runtime_LocalKeys(Arguments args) {
   ASSERT_EQ(args.length(), 1);
   CONVERT_CHECKED(JSObject, raw_object, args[0]);
@@ -6005,21 +6155,6 @@ static Object* Runtime_Break(Arguments args) {
 }
 
 
-// Find the length of the prototype chain that is to to handled as one. If a
-// prototype object is hidden it is to be viewed as part of the the object it
-// is prototype for.
-static int LocalPrototypeChainLength(JSObject* obj) {
-  int count = 1;
-  Object* proto = obj->GetPrototype();
-  while (proto->IsJSObject() &&
-         JSObject::cast(proto)->map()->is_hidden_prototype()) {
-    count++;
-    proto = JSObject::cast(proto)->GetPrototype();
-  }
-  return count;
-}
-
-
 static Object* DebugLookupResultValue(Object* receiver, String* name,
                                       LookupResult* result,
                                       bool* caught_exception) {
@@ -6189,93 +6324,6 @@ static Object* Runtime_DebugGetProperty(Arguments args) {
 }
 
 
-// Return the names of the local named properties.
-// args[0]: object
-static Object* Runtime_DebugLocalPropertyNames(Arguments args) {
-  HandleScope scope;
-  ASSERT(args.length() == 1);
-  if (!args[0]->IsJSObject()) {
-    return Heap::undefined_value();
-  }
-  CONVERT_ARG_CHECKED(JSObject, obj, 0);
-
-  // Skip the global proxy as it has no properties and always delegates to the
-  // real global object.
-  if (obj->IsJSGlobalProxy()) {
-    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
-  }
-
-  // Find the number of objects making up this.
-  int length = LocalPrototypeChainLength(*obj);
-
-  // Find the number of local properties for each of the objects.
-  int* local_property_count = NewArray<int>(length);
-  int total_property_count = 0;
-  Handle<JSObject> jsproto = obj;
-  for (int i = 0; i < length; i++) {
-    int n;
-    n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
-    local_property_count[i] = n;
-    total_property_count += n;
-    if (i < length - 1) {
-      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
-    }
-  }
-
-  // Allocate an array with storage for all the property names.
-  Handle<FixedArray> names = Factory::NewFixedArray(total_property_count);
-
-  // Get the property names.
-  jsproto = obj;
-  int proto_with_hidden_properties = 0;
-  for (int i = 0; i < length; i++) {
-    jsproto->GetLocalPropertyNames(*names,
-                                   i == 0 ? 0 : local_property_count[i - 1]);
-    if (!GetHiddenProperties(jsproto, false)->IsUndefined()) {
-      proto_with_hidden_properties++;
-    }
-    if (i < length - 1) {
-      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
-    }
-  }
-
-  // Filter out name of hidden propeties object.
-  if (proto_with_hidden_properties > 0) {
-    Handle<FixedArray> old_names = names;
-    names = Factory::NewFixedArray(
-        names->length() - proto_with_hidden_properties);
-    int dest_pos = 0;
-    for (int i = 0; i < total_property_count; i++) {
-      Object* name = old_names->get(i);
-      if (name == Heap::hidden_symbol()) {
-        continue;
-      }
-      names->set(dest_pos++, name);
-    }
-  }
-
-  DeleteArray(local_property_count);
-  return *Factory::NewJSArrayWithElements(names);
-}
-
-
-// Return the names of the local indexed properties.
-// args[0]: object
-static Object* Runtime_DebugLocalElementNames(Arguments args) {
-  HandleScope scope;
-  ASSERT(args.length() == 1);
-  if (!args[0]->IsJSObject()) {
-    return Heap::undefined_value();
-  }
-  CONVERT_ARG_CHECKED(JSObject, obj, 0);
-
-  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
-  Handle<FixedArray> names = Factory::NewFixedArray(n);
-  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
-  return *Factory::NewJSArrayWithElements(names);
-}
-
-
 // Return the property type calculated from the property details.
 // args[0]: smi with property details.
 static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
@@ -6306,54 +6354,6 @@ static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) {
 }
 
 
-// Return information on whether an object has a named or indexed interceptor.
-// args[0]: object
-static Object* Runtime_DebugInterceptorInfo(Arguments args) {
-  HandleScope scope;
-  ASSERT(args.length() == 1);
-  if (!args[0]->IsJSObject()) {
-    return Smi::FromInt(0);
-  }
-  CONVERT_ARG_CHECKED(JSObject, obj, 0);
-
-  int result = 0;
-  if (obj->HasNamedInterceptor()) result |= 2;
-  if (obj->HasIndexedInterceptor()) result |= 1;
-
-  return Smi::FromInt(result);
-}
-
-
-// Return property names from named interceptor.
-// args[0]: object
-static Object* Runtime_DebugNamedInterceptorPropertyNames(Arguments args) {
-  HandleScope scope;
-  ASSERT(args.length() == 1);
-  CONVERT_ARG_CHECKED(JSObject, obj, 0);
-
-  if (obj->HasNamedInterceptor()) {
-    v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
-    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
-  }
-  return Heap::undefined_value();
-}
-
-
-// Return element names from indexed interceptor.
-// args[0]: object
-static Object* Runtime_DebugIndexedInterceptorElementNames(Arguments args) {
-  HandleScope scope;
-  ASSERT(args.length() == 1);
-  CONVERT_ARG_CHECKED(JSObject, obj, 0);
-
-  if (obj->HasIndexedInterceptor()) {
-    v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
-    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
-  }
-  return Heap::undefined_value();
-}
-
-
 // Return property value from named interceptor.
 // args[0]: object
 // args[1]: property name
index b6542a6..59b5f30 100644 (file)
@@ -52,6 +52,11 @@ namespace internal {
   F(IsPropertyEnumerable, 2, 1) \
   F(GetPropertyNames, 1, 1) \
   F(GetPropertyNamesFast, 1, 1) \
+  F(GetLocalPropertyNames, 1, 1) \
+  F(GetLocalElementNames, 1, 1) \
+  F(GetInterceptorInfo, 1, 1) \
+  F(GetNamedInterceptorPropertyNames, 1, 1) \
+  F(GetIndexedInterceptorElementNames, 1, 1) \
   F(GetArgumentsProperty, 1, 1) \
   F(ToFastProperties, 1, 1) \
   F(ToSlowProperties, 1, 1) \
@@ -285,14 +290,9 @@ namespace internal {
   F(Break, 0, 1) \
   F(DebugGetPropertyDetails, 2, 1) \
   F(DebugGetProperty, 2, 1) \
-  F(DebugLocalPropertyNames, 1, 1) \
-  F(DebugLocalElementNames, 1, 1) \
   F(DebugPropertyTypeFromDetails, 1, 1) \
   F(DebugPropertyAttributesFromDetails, 1, 1) \
   F(DebugPropertyIndexFromDetails, 1, 1) \
-  F(DebugInterceptorInfo, 1, 1) \
-  F(DebugNamedInterceptorPropertyNames, 1, 1) \
-  F(DebugIndexedInterceptorElementNames, 1, 1) \
   F(DebugNamedInterceptorPropertyValue, 2, 1) \
   F(DebugIndexedInterceptorElementValue, 2, 1) \
   F(CheckExecutionState, 1, 1) \
index 700b9e4..3dcf430 100644 (file)
@@ -276,7 +276,7 @@ function ObjectLookupSetter(name) {
 
 function ObjectKeys(obj) {
   if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
-    throw MakeTypeError('object_keys_non_object', [obj]);
+    throw MakeTypeError("obj_ctor_property_non_object", ["keys"]);
   return %LocalKeys(obj);
 }
 
@@ -493,23 +493,59 @@ function DefineOwnProperty(obj, p, desc, should_throw) {
 
 // ES5 section 15.2.3.2.
 function ObjectGetPrototypeOf(obj) {
- if (!IS_OBJECT(obj) && !IS_FUNCTION(obj)) {
-   throw MakeTypeError("object_get_prototype_non_object", [obj]);
- }
- return obj.__proto__;
+  if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
+    throw MakeTypeError("obj_ctor_property_non_object", ["getPrototypeOf"]);
+  return obj.__proto__;
 }
 
 
 // ES5 section 15.2.3.3 
 function ObjectGetOwnPropertyDescriptor(obj, p) {
-  if (!IS_OBJECT(obj) && !IS_FUNCTION(obj)) {
-    throw MakeTypeError("object_get_prototype_non_object", [obj]);
-  }
+  if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
+    throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyDescriptor"]);
   var desc = GetOwnProperty(obj, p);
   return FromPropertyDescriptor(desc);
 }
 
 
+// ES5 section 15.2.3.4.
+function ObjectGetOwnPropertyNames(obj) {
+  if ((!IS_OBJECT(obj) || IS_NULL_OR_UNDEFINED(obj)) && !IS_FUNCTION(obj))
+    throw MakeTypeError("obj_ctor_property_non_object", ["getOwnPropertyNames"]);
+
+  // Find all the indexed properties.
+
+  // Get the local element names.
+  var propertyNames = %GetLocalElementNames(obj);
+
+  // Get names for indexed interceptor properties.
+  if (%GetInterceptorInfo(obj) & 1) {
+    var indexedInterceptorNames =
+        %GetIndexedInterceptorElementNames(obj);
+    if (indexedInterceptorNames) {
+      propertyNames = propertyNames.concat(indexedInterceptorNames);
+    }
+  }
+
+  // Find all the named properties.
+
+  // Get the local property names.
+  propertyNames = propertyNames.concat(%GetLocalPropertyNames(obj));
+
+  // Get names for named interceptor properties if any.
+
+  if (%GetInterceptorInfo(obj) & 2) {
+    var namedInterceptorNames =
+        %GetNamedInterceptorPropertyNames(obj);
+    if (namedInterceptorNames) {
+      propertyNames = propertyNames.concat(namedInterceptorNames);
+    }
+  }
+
+  return propertyNames;
+}
+
+
 // ES5 section 15.2.3.5.
 function ObjectCreate(proto, properties) {
   if (!IS_OBJECT(proto) && !IS_NULL(proto)) {
@@ -576,7 +612,8 @@ function SetupObject() {
     "keys", ObjectKeys,
     "create", ObjectCreate,
     "getPrototypeOf", ObjectGetPrototypeOf,
-    "getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor
+    "getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor,
+    "getOwnPropertyNames", ObjectGetOwnPropertyNames
   ));
 }
 
diff --git a/test/mjsunit/object-get-own-property-names.js b/test/mjsunit/object-get-own-property-names.js
new file mode 100644 (file)
index 0000000..f52cee2
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright 2009 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.
+
+// Test ES5 section 15.2.3.4 Object.getOwnPropertyNames.
+
+// Check simple cases.
+var obj = { a: 1, b: 2};
+var propertyNames = Object.getOwnPropertyNames(obj);
+propertyNames.sort();
+assertEquals(2, propertyNames.length);
+assertEquals("a", propertyNames[0]);
+assertEquals("b", propertyNames[1]);
+
+var obj = { a: function(){}, b: function(){} };
+var propertyNames = Object.getOwnPropertyNames(obj);
+propertyNames.sort();
+assertEquals(2, propertyNames.length);
+assertEquals("a", propertyNames[0]);
+assertEquals("b", propertyNames[1]);
+
+// Check slow case
+var obj = { a: 1, b: 2, c: 3 };
+delete obj.b;
+var propertyNames = Object.getOwnPropertyNames(obj)
+propertyNames.sort();
+assertEquals(2, propertyNames.length);
+assertEquals("a", propertyNames[0]);
+assertEquals("c", propertyNames[1]);
+
+// Check that non-enumerable properties are being returned.
+var propertyNames = Object.getOwnPropertyNames([1, 2]);
+propertyNames.sort();
+assertEquals(3, propertyNames.length);
+assertEquals("0", propertyNames[0]);
+assertEquals("1", propertyNames[1]);
+assertEquals("length", propertyNames[2]);
+
+// Check that no proto properties are returned.
+var obj = { foo: "foo" };
+obj.__proto__ = { bar: "bar" };
+propertyNames = Object.getOwnPropertyNames(obj);
+propertyNames.sort();
+assertEquals(1, propertyNames.length);
+assertEquals("foo", propertyNames[0]);
+
+// Check that getter properties are returned.
+var obj = {};
+obj.__defineGetter__("getter", function() {});
+propertyNames = Object.getOwnPropertyNames(obj);
+propertyNames.sort();
+assertEquals(1, propertyNames.length);
+assertEquals("getter", propertyNames[0]);
+
+try {
+  Object.getOwnPropertyNames(4);
+  assertTrue(false);
+} catch (e) {
+  assertTrue(/on non-object/.test(e));
+}
+
+try {
+  Object.getOwnPropertyNames("foo");
+  assertTrue(false);
+} catch (e) {
+  assertTrue(/on non-object/.test(e));
+}
+
+try {
+  Object.getOwnPropertyNames(undefined);
+  assertTrue(false);
+} catch (e) {
+  assertTrue(/on non-object/.test(e));
+}
+
+try {
+  Object.getOwnPropertyNames(null);
+  assertTrue(false);
+} catch (e) {
+  assertTrue(/on non-object/.test(e));
+}
index fe6cfed..6a851ee 100644 (file)
@@ -1,3 +1,30 @@
+// Copyright 2010 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.
+
 Object.extend = function (dest, source) {
        for (property in source) dest[property] = source[property];
        return dest;