Use InternalArray in Object.getOwnPropertyNames() implementation
authoradamk@chromium.org <adamk@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 12 Mar 2013 20:15:03 +0000 (20:15 +0000)
committeradamk@chromium.org <adamk@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 12 Mar 2013 20:15:03 +0000 (20:15 +0000)
Review URL: https://codereview.chromium.org/12342003

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

src/array.js
src/v8natives.js
test/mjsunit/object-get-own-property-names.js

index 1ec6433..7cf744b 100644 (file)
@@ -1553,6 +1553,7 @@ function SetUpArray() {
   // exposed to user code.
   // Adding only the functions that are actually used.
   SetUpLockedPrototype(InternalArray, $Array(), $Array(
+    "concat", getFunction("concat", ArrayConcat),
     "indexOf", getFunction("indexOf", ArrayIndexOf),
     "join", getFunction("join", ArrayJoin),
     "pop", getFunction("pop", ArrayPop),
index cc2e1c5..24ad22d 100644 (file)
@@ -1014,39 +1014,44 @@ function ObjectGetOwnPropertyNames(obj) {
     return ToNameArray(names, "getOwnPropertyNames", true);
   }
 
+  var nameArrays = new InternalArray();
+
   // Find all the indexed properties.
 
   // Get the local element names.
-  var propertyNames = %GetLocalElementNames(obj);
-  for (var i = 0; i < propertyNames.length; ++i) {
-    propertyNames[i] = %_NumberToString(propertyNames[i]);
+  var localElementNames = %GetLocalElementNames(obj);
+  for (var i = 0; i < localElementNames.length; ++i) {
+    localElementNames[i] = %_NumberToString(localElementNames[i]);
   }
+  nameArrays.push(localElementNames);
 
   // Get names for indexed interceptor properties.
   var interceptorInfo = %GetInterceptorInfo(obj);
   if ((interceptorInfo & 1) != 0) {
-    var indexedInterceptorNames =
-        %GetIndexedInterceptorElementNames(obj);
-    if (indexedInterceptorNames) {
-      propertyNames = propertyNames.concat(indexedInterceptorNames);
+    var indexedInterceptorNames = %GetIndexedInterceptorElementNames(obj);
+    if (!IS_UNDEFINED(indexedInterceptorNames)) {
+      nameArrays.push(indexedInterceptorNames);
     }
   }
 
   // Find all the named properties.
 
   // Get the local property names.
-  propertyNames = propertyNames.concat(%GetLocalPropertyNames(obj));
+  nameArrays.push(%GetLocalPropertyNames(obj));
 
   // Get names for named interceptor properties if any.
   if ((interceptorInfo & 2) != 0) {
-    var namedInterceptorNames =
-        %GetNamedInterceptorPropertyNames(obj);
-    if (namedInterceptorNames) {
-      propertyNames = propertyNames.concat(namedInterceptorNames);
+    var namedInterceptorNames = %GetNamedInterceptorPropertyNames(obj);
+    if (!IS_UNDEFINED(namedInterceptorNames)) {
+      nameArrays.push(namedInterceptorNames);
     }
   }
 
-  // Property names are expected to be unique names,
+  var propertyNames =
+      %Apply(InternalArray.prototype.concat,
+             nameArrays[0], nameArrays, 1, nameArrays.length - 1);
+
+  // Property names are expected to be unique strings,
   // but interceptors can interfere with that assumption.
   if (interceptorInfo != 0) {
     var propertySet = { __proto__: null };
index 33aa85e..64607c6 100644 (file)
@@ -77,6 +77,16 @@ propertyNames.sort();
 assertEquals(1, propertyNames.length);
 assertEquals("getter", propertyNames[0]);
 
+// Check that implementation does not access Array.prototype.
+var savedConcat = Array.prototype.concat;
+Array.prototype.concat = function() { return []; }
+propertyNames = Object.getOwnPropertyNames({0: 'foo', bar: 'baz'});
+assertEquals(2, propertyNames.length);
+assertEquals('0', propertyNames[0]);
+assertEquals('bar', propertyNames[1]);
+assertSame(Array.prototype, propertyNames.__proto__);
+Array.prototype.concat = savedConcat;
+
 try {
   Object.getOwnPropertyNames(4);
   assertTrue(false);