Bug 1020460 - Array.prototype.toSource should be generic. r=jorendorff, a=lmandel
authorBobby Holley <bobbyholley@gmail.com>
Tue, 10 Jun 2014 20:15:56 -0700
changeset 195274 12161a842a8e1972cdb27ed36928b8f4a8999290
parent 195273 d51a335b7c2df6f3b901a423c72a69d50a8857f3
child 195275 164b61458ca52739c1228661b578397b3595a2f7
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-esr52@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff, lmandel
bugs1020460
milestone32.0a2
Bug 1020460 - Array.prototype.toSource should be generic. r=jorendorff, a=lmandel
js/src/jit-test/tests/basic/array-tosource.js
js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js
js/src/jsarray.cpp
js/src/tests/ecma_3/Array/regress-387501.js
js/src/tests/js1_7/extensions/regress-380933.js
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/array-tosource.js
@@ -0,0 +1,8 @@
+load(libdir + 'asserts.js');
+
+assertEq(Array.prototype.toSource.call([1, 'hi']), '[1, "hi"]');
+assertEq(Array.prototype.toSource.call({1: 10, 0: 42, length: 2}), "[42, 10]");
+assertEq(Array.prototype.toSource.call({1: 10, 0: 42, length: 1}), "[42]");
+assertThrowsInstanceOf(() => Array.prototype.toSource.call("someString"), TypeError);
+assertThrowsInstanceOf(() => Array.prototype.toSource.call(42), TypeError);
+assertThrowsInstanceOf(() => Array.prototype.toSource.call(undefined), TypeError);
--- a/js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js
+++ b/js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js
@@ -51,17 +51,16 @@ function test(str, f) {
         f(proxy2);
     } catch (e) {
         assertEq(Object.prototype.toString.call(e), "[object Error]");
         threw = true;
     }
     assertEq(threw, true);
 }
 
-test("new Array(1,2,3)", function(a) Array.prototype.toSource.call(a));
 test("new Boolean(true)", function(b) Boolean.prototype.toSource.call(b));
 test("new Boolean(true)", function(b) Boolean.prototype.toString.call(b));
 test("new Boolean(true)", function(b) Boolean.prototype.valueOf.call(b));
 test("new Number(1)", function(n) Number.prototype.toSource.call(n));
 test("new Number(1)", function(n) Number.prototype.toString.call(n));
 test("new Number(1)", function(n) Number.prototype.valueOf.call(n));
 test("new Number(1)", function(n) Number.prototype.toFixed.call(n));
 test("new Number(1)", function(n) Number.prototype.toExponential.call(n));
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -855,26 +855,27 @@ AddLengthProperty(ExclusiveContext *cx, 
     JS_ASSERT(!obj->nativeLookup(cx, lengthId));
 
     return JSObject::addProperty(cx, obj, lengthId, array_length_getter, array_length_setter,
                                  SHAPE_INVALID_SLOT, JSPROP_PERMANENT | JSPROP_SHARED, 0,
                                  /* allowDictionary = */ false);
 }
 
 #if JS_HAS_TOSOURCE
-MOZ_ALWAYS_INLINE bool
-IsArray(HandleValue v)
+
+static bool
+array_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
-    return v.isObject() && v.toObject().is<ArrayObject>();
-}
-
-MOZ_ALWAYS_INLINE bool
-array_toSource_impl(JSContext *cx, CallArgs args)
-{
-    JS_ASSERT(IsArray(args.thisv()));
+    JS_CHECK_RECURSION(cx, return false);
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    if (!args.thisv().isObject()) {
+        ReportIncompatible(cx, args);
+        return false;
+    }
 
     Rooted<JSObject*> obj(cx, &args.thisv().toObject());
     RootedValue elt(cx);
 
     AutoCycleDetector detector(cx, obj);
     if (!detector.init())
         return false;
 
@@ -930,23 +931,16 @@ array_toSource_impl(JSContext *cx, CallA
     JSString *str = sb.finishString();
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
-static bool
-array_toSource(JSContext *cx, unsigned argc, Value *vp)
-{
-    JS_CHECK_RECURSION(cx, return false);
-    CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod<IsArray, array_toSource_impl>(cx, args);
-}
 #endif
 
 struct EmptySeparatorOp
 {
     bool operator()(JSContext *, StringBuffer &sb) { return true; }
 };
 
 struct CharSeparatorOp
--- a/js/src/tests/ecma_3/Array/regress-387501.js
+++ b/js/src/tests/ecma_3/Array/regress-387501.js
@@ -1,18 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 387501;
 var summary =
-  'Array.prototype.toString|toLocaleString are generic, ' +
-  'Array.prototype.toSource is not generic';
+  'Array.prototype.toString|toLocaleString|toSource are generic';
 var actual = '';
 var expect = '';
 
 
 //-----------------------------------------------------------------------------
 test();
 //-----------------------------------------------------------------------------
 
@@ -25,21 +24,23 @@ function test()
   expect = '[object String]';
   actual = Array.prototype.toString.call((new String('foo')));
   assertEq(actual, expect, summary);
 
   expect = 'f,o,o';
   actual = Array.prototype.toLocaleString.call((new String('foo')));
   assertEq(actual, expect, summary);
 
+  assertEq('["f", "o", "o"]', Array.prototype.toSource.call(new String('foo')));
+
   if (typeof Array.prototype.toSource != 'undefined')
   {
     try
     {
-      Array.prototype.toSource.call(new String('foo'));
+      Array.prototype.toSource.call('foo');
       throw new Error("didn't throw");
     }
     catch(ex)
     {
       assertEq(ex instanceof TypeError, true,
                "wrong error thrown: expected TypeError, got " + ex);
     }
   }
--- a/js/src/tests/js1_7/extensions/regress-380933.js
+++ b/js/src/tests/js1_7/extensions/regress-380933.js
@@ -13,25 +13,15 @@ var f = (function(){});
 var y =
   Object.defineProperty({}, "p",
   {
     get: f,
     enumerable: true,
     configurable: true
   });
 f.__proto__ = [];
-
-try
-{
-  uneval(y);
-  throw new Error("didn't throw");
-}
-catch(ex)
-{
-  assertEq(ex instanceof TypeError, true,
-           "wrong exception thrown: expected TypeError, got " + ex);
-}
+uneval(y);
 
 if (typeof reportCompare === "function")
   reportCompare(true, true);
 
 print("Tests complete");