Revision: 20909
Author:   mstarzin...@chromium.org
Date:     Wed Apr 23 12:48:32 2014 UTC
Log:      Fix ToObject and Object.isSealed in four Array builtins.

R=mvstan...@chromium.org
TEST=mjsunit/regress/regress-builtinbust-6

Review URL: https://codereview.chromium.org/240223006
http://code.google.com/p/v8/source/detail?r=20909

Added:
 /branches/bleeding_edge/test/mjsunit/regress/regress-builtinbust-6.js
Modified:
 /branches/bleeding_edge/src/array.js

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-builtinbust-6.js Wed Apr 23 12:48:32 2014 UTC
@@ -0,0 +1,37 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test that Array builtins can be called on primitive values.
+var values = [ 23, 4.2, true, false, 0/0 ];
+for (var i = 0; i < values.length; ++i) {
+  var v = values[i];
+  Array.prototype.pop.call(v);
+  Array.prototype.push.call(v);
+  Array.prototype.shift.call(v);
+  Array.prototype.unshift.call(v);
+}
+
+// Test that ToObject on primitive values is only called once.
+var length_receiver, element_receiver;
+function length() { length_receiver = this; return 1; }
+function element() { element_receiver = this; return "x"; }
+Object.defineProperty(Number.prototype, "length", { get:length, set:length });
+Object.defineProperty(Number.prototype, "0", { get:element, set:element });
+Object.defineProperty(Number.prototype, "1", { get:element, set:element });
+
+assertDoesNotThrow("Array.prototype.pop.call(23)");
+assertEquals(new Number(23), length_receiver);
+assertSame(length_receiver, element_receiver);
+
+assertDoesNotThrow("Array.prototype.push.call(42, 'y')");
+assertEquals(new Number(42), length_receiver);
+assertSame(length_receiver, element_receiver);
+
+assertDoesNotThrow("Array.prototype.shift.call(65)");
+assertEquals(new Number(65), length_receiver);
+assertSame(length_receiver, element_receiver);
+
+assertDoesNotThrow("Array.prototype.unshift.call(99, 'z')");
+assertEquals(new Number(99), length_receiver);
+assertSame(length_receiver, element_receiver);
=======================================
--- /branches/bleeding_edge/src/array.js        Thu Apr 17 11:37:59 2014 UTC
+++ /branches/bleeding_edge/src/array.js        Wed Apr 23 12:48:32 2014 UTC
@@ -415,24 +415,20 @@
 function ArrayPop() {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop");

-  var n = TO_UINT32(this.length);
+  var array = TO_OBJECT_INLINE(this);
+  var n = TO_UINT32(array.length);
   if (n == 0) {
-    this.length = n;
+    array.length = n;
     return;
   }

-  if (ObjectIsSealed(this)) {
-    throw MakeTypeError("array_functions_change_sealed",
-                        ["Array.prototype.pop"]);
-  }
-
-  if (%IsObserved(this))
-    return ObservedArrayPop.call(this, n);
+  if (%IsObserved(array))
+    return ObservedArrayPop.call(array, n);

   n--;
-  var value = this[n];
-  Delete(this, ToName(n), true);
-  this.length = n;
+  var value = array[n];
+  Delete(array, ToName(n), true);
+  array.length = n;
   return value;
 }

@@ -461,24 +457,21 @@
 function ArrayPush() {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push");

-  var n = TO_UINT32(this.length);
-  var m = %_ArgumentsLength();
-
   if (%IsObserved(this))
     return ObservedArrayPush.apply(this, arguments);

+  var array = TO_OBJECT_INLINE(this);
+  var n = TO_UINT32(array.length);
+  var m = %_ArgumentsLength();
+
   for (var i = 0; i < m; i++) {
// Use SetProperty rather than a direct keyed store to ensure that the store // site doesn't become poisened with an elements transition KeyedStoreIC.
-    //
- // TODO(danno): Using %SetProperty is a temporary workaround. The spec says
-    // that ToObject needs to be called for primitive values (and
-    // Runtime_SetProperty seem to ignore them).
-    %SetProperty(this, i+n, %_Arguments(i), 0, kStrictMode);
+    %SetProperty(array, i+n, %_Arguments(i), 0, kStrictMode);
   }

   var new_length = n + m;
-  this.length = new_length;
+  array.length = new_length;
   return new_length;
 }

@@ -596,30 +589,31 @@
 function ArrayShift() {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift");

-  var len = TO_UINT32(this.length);
+  var array = TO_OBJECT_INLINE(this);
+  var len = TO_UINT32(array.length);

   if (len === 0) {
-    this.length = 0;
+    array.length = 0;
     return;
   }

-  if (ObjectIsSealed(this)) {
+  if (ObjectIsSealed(array)) {
     throw MakeTypeError("array_functions_change_sealed",
                         ["Array.prototype.shift"]);
   }

-  if (%IsObserved(this))
-    return ObservedArrayShift.call(this, len);
+  if (%IsObserved(array))
+    return ObservedArrayShift.call(array, len);

-  var first = this[0];
+  var first = array[0];

-  if (IS_ARRAY(this)) {
-    SmartMove(this, 0, 1, len, 0);
+  if (IS_ARRAY(array)) {
+    SmartMove(array, 0, 1, len, 0);
   } else {
-    SimpleMove(this, 0, 1, len, 0);
+    SimpleMove(array, 0, 1, len, 0);
   }

-  this.length = len - 1;
+  array.length = len - 1;

   return first;
 }
@@ -647,25 +641,26 @@
 function ArrayUnshift(arg1) {  // length == 1
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.unshift");

-  var len = TO_UINT32(this.length);
-  var num_arguments = %_ArgumentsLength();
-  var is_sealed = ObjectIsSealed(this);
-
   if (%IsObserved(this))
     return ObservedArrayUnshift.apply(this, arguments);

-  if (IS_ARRAY(this) && !is_sealed) {
-    SmartMove(this, 0, 0, len, num_arguments);
+  var array = TO_OBJECT_INLINE(this);
+  var len = TO_UINT32(array.length);
+  var num_arguments = %_ArgumentsLength();
+  var is_sealed = ObjectIsSealed(array);
+
+  if (IS_ARRAY(array) && !is_sealed) {
+    SmartMove(array, 0, 0, len, num_arguments);
   } else {
-    SimpleMove(this, 0, 0, len, num_arguments);
+    SimpleMove(array, 0, 0, len, num_arguments);
   }

   for (var i = 0; i < num_arguments; i++) {
-    this[i] = %_Arguments(i);
+    array[i] = %_Arguments(i);
   }

   var new_length = len + num_arguments;
-  this.length = new_length;
+  array.length = new_length;
   return new_length;
 }

--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to