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.