b=612334; have typed arrays treat length parans more consistently; r=waldo, a=b
authorVladimir Vukicevic <vladimir@pobox.com>
Wed, 22 Dec 2010 15:31:02 -0800
changeset 59618 026750b84bc2e69f916104cf1d391e3b4a311c41
parent 59617 d4e6e2377500bf0bbccbbc488056bc7a806ba3c9
child 59619 ad071e6d8bb340b6db40c049ef0689f6159bede3
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewerswaldo, b
bugs612334
milestone2.0b9pre
b=612334; have typed arrays treat length parans more consistently; r=waldo, a=b
js/src/jstypedarray.cpp
js/src/tests/js1_8_5/extensions/typedarray.js
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -61,16 +61,43 @@
 #include "jsvector.h"
 #include "jstypedarray.h"
 
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
+static bool
+ValueIsLength(JSContext *cx, const Value &v, jsuint *len)
+{
+    if (v.isInt32()) {
+        int32_t i = v.toInt32();
+        if (i < 0)
+            return false;
+        *len = i;
+        return true;
+    }
+
+    if (v.isDouble()) {
+        jsdouble d = v.toDouble();
+        if (JSDOUBLE_IS_NaN(d))
+            return false;
+
+        jsuint length = jsuint(d);
+        if (d != jsdouble(length))
+            return false;
+
+        *len = length;
+        return true;
+    }
+
+    return false;
+}
+
 /*
  * ArrayBuffer
  *
  * This class holds the underlying raw buffer that the TypedArray classes
  * access.  It can be created explicitly and passed to a TypedArray, or
  * can be created implicitly by constructing a TypedArray with a size.
  */
 ArrayBuffer *
@@ -719,28 +746,22 @@ class TypedArrayTemplate
         JSObject *obj = NewBuiltinClassInstance(cx, slowClass());
         if (!obj)
             return false;
 
         ThisTypeArray *tarray = 0;
 
         // figure out the type of the first argument;
         // no args is treated like an int arg of 0.
-        if (argc == 0 || argv[0].isInt32()) {
-            int32 len = 0;
-
-            if (argc != 0)
-                len = argv[0].toInt32();
+        jsuint len = 0;
+        bool hasLen = true;
+        if (argc > 0)
+            hasLen = ValueIsLength(cx, argv[0], &len);
 
-            if (len < 0) {
-                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                     JSMSG_BAD_ARRAY_LENGTH);
-                return false;
-            }
-
+        if (hasLen) {
             tarray = new ThisTypeArray();
             if (!tarray) {
                 JS_ReportOutOfMemory(cx);
                 return false;
             }
 
             if (!tarray->init(cx, len)) {
                 delete tarray;
--- a/js/src/tests/js1_8_5/extensions/typedarray.js
+++ b/js/src/tests/js1_8_5/extensions/typedarray.js
@@ -319,14 +319,23 @@ function test()
     // checkThrows(function() new Int32Array(Float64Array));
 
     check(function() Int32Array.BYTES_PER_ELEMENT == 4);
     check(function() (new Int32Array(4)).BYTES_PER_ELEMENT == 4);
     check(function() (new Int32Array()).BYTES_PER_ELEMENT == 4);
     check(function() (new Int32Array(0)).BYTES_PER_ELEMENT == 4);
     check(function() Int16Array.BYTES_PER_ELEMENT == Uint16Array.BYTES_PER_ELEMENT);
 
+    // test various types of args; Math.sqrt(4) is used to ensure that the
+    // function gets a double, and not a demoted int
+    check(function() (new Float32Array(Math.sqrt(4))).length == 2);
+    check(function() (new Float32Array({ length: 10 })).length == 10);
+    check(function() (new Float32Array({})).length == 0);
+    checkThrows(function() new Float32Array("3"));
+    checkThrows(function() new Float32Array(null));
+    checkThrows(function() new Float32Array(undefined));
+
     print ("done");
 
     reportCompare(0, TestFailCount, "typed array tests");
 
     exitFunc ('test');
 }