2011-01-04 Adrienne Walker <enne@google.com>
authorenne@google.com <enne@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Jan 2011 18:47:50 +0000 (18:47 +0000)
committerenne@google.com <enne@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Jan 2011 18:47:50 +0000 (18:47 +0000)
        Reviewed by Kenneth Russell.

        Add test cases for storing NaN in typed arrays.
        https://bugs.webkit.org/show_bug.cgi?id=46990

        * fast/canvas/webgl/array-unit-tests-expected.txt:
        * fast/canvas/webgl/array-unit-tests.html:
2011-01-04  Adrienne Walker  <enne@google.com>

        Reviewed by Kenneth Russell.

        NaN in a TypedArray should be converted to zero only for Float32Array.
        https://bugs.webkit.org/show_bug.cgi?id=46990

        Test: LayoutTests/fast/canvas/webgl/array-unit-tests.html

        * bindings/js/JSArrayBufferViewHelper.h:
        (WebCore::convertArrayValue):
        (WebCore::constructArrayBufferView):
        * html/canvas/Float32Array.h:
        (WebCore::Float32Array::set):
        (WebCore::Float32Array::item):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@75167 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/canvas/webgl/array-unit-tests-expected.txt
LayoutTests/fast/canvas/webgl/array-unit-tests.html
WebCore/ChangeLog
WebCore/bindings/js/JSArrayBufferViewHelper.h
WebCore/html/canvas/Float32Array.h

index a7fb69e..48c632c 100644 (file)
@@ -1,3 +1,13 @@
+2011-01-04  Adrienne Walker  <enne@google.com>
+
+        Reviewed by Kenneth Russell.
+
+        Add test cases for storing NaN in typed arrays.
+        https://bugs.webkit.org/show_bug.cgi?id=46990
+
+        * fast/canvas/webgl/array-unit-tests-expected.txt:
+        * fast/canvas/webgl/array-unit-tests.html:
+
 2011-01-06  Andrei Popescu  <andreip@google.com>
 
         Unreviewed, build fix.
index 994fdce..19682eb 100644 (file)
@@ -44,6 +44,7 @@ PASS Setting Float32Array from fake array with invalid length was caught
 PASS Setting Float32Array from Float32Array with out-of-range offset was caught
 PASS array.get is undefined.
 PASS array.set(0, 1) threw exception.
+PASS test storing NaN in Float32Array
 PASS test Int8Array SetAndGetPos10ToNeg10
 PASS test Int8Array ConstructWithArrayOfSignedValues
 PASS test Int8Array ConstructWithTypedArrayOfSignedValues
@@ -82,6 +83,7 @@ PASS Setting Int8Array from fake array with invalid length was caught
 PASS Setting Int8Array from Int8Array with out-of-range offset was caught
 PASS array.get is undefined.
 PASS array.set(0, 1) threw exception.
+PASS test storing NaN in Int8Array
 PASS test Int16Array SetAndGetPos10ToNeg10
 PASS test Int16Array ConstructWithArrayOfSignedValues
 PASS test Int16Array ConstructWithTypedArrayOfSignedValues
@@ -124,6 +126,7 @@ PASS Setting Int16Array from fake array with invalid length was caught
 PASS Setting Int16Array from Int16Array with out-of-range offset was caught
 PASS array.get is undefined.
 PASS array.set(0, 1) threw exception.
+PASS test storing NaN in Int16Array
 PASS test Int32Array SetAndGetPos10ToNeg10
 PASS test Int32Array ConstructWithArrayOfSignedValues
 PASS test Int32Array ConstructWithTypedArrayOfSignedValues
@@ -166,6 +169,7 @@ PASS Setting Int32Array from fake array with invalid length was caught
 PASS Setting Int32Array from Int32Array with out-of-range offset was caught
 PASS array.get is undefined.
 PASS array.set(0, 1) threw exception.
+PASS test storing NaN in Int32Array
 PASS test Uint8Array SetAndGet10To1
 PASS test Uint8Array ConstructWithArrayOfUnsignedValues
 PASS test Uint8Array ConstructWithTypedArrayOfUnsignedValues
@@ -204,6 +208,7 @@ PASS Setting Uint8Array from fake array with invalid length was caught
 PASS Setting Uint8Array from Uint8Array with out-of-range offset was caught
 PASS array.get is undefined.
 PASS array.set(0, 1) threw exception.
+PASS test storing NaN in Uint8Array
 PASS test Uint16Array SetAndGet10To1
 PASS test Uint16Array ConstructWithArrayOfUnsignedValues
 PASS test Uint16Array ConstructWithTypedArrayOfUnsignedValues
@@ -246,6 +251,7 @@ PASS Setting Uint16Array from fake array with invalid length was caught
 PASS Setting Uint16Array from Uint16Array with out-of-range offset was caught
 PASS array.get is undefined.
 PASS array.set(0, 1) threw exception.
+PASS test storing NaN in Uint16Array
 PASS test Uint32Array SetAndGet10To1
 PASS test Uint32Array ConstructWithArrayOfUnsignedValues
 PASS test Uint32Array ConstructWithTypedArrayOfUnsignedValues
@@ -288,6 +294,7 @@ PASS Setting Uint32Array from fake array with invalid length was caught
 PASS Setting Uint32Array from Uint32Array with out-of-range offset was caught
 PASS array.get is undefined.
 PASS array.set(0, 1) threw exception.
+PASS test storing NaN in Uint32Array
 Test passed.
 PASS successfullyParsed is true
 
index 7bfcfac..201cf1c 100644 (file)
@@ -554,6 +554,81 @@ function negativeTestGetAndSetMethods(type, name) {
     }
 }
 
+function testNaNConversion(type, name) {
+  running('test storing NaN in ' + name);
+
+  var array = new type([1, 1]);
+  var results = [];
+
+  // The code block in each of the case statements below is identical, but some
+  // JavaScript engines need separate copies in order to exercise all of
+  // their optimized code paths.
+  try {
+    switch (type) {
+    case Float32Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Int8Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Int16Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Int32Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Uint8Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Uint16Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Uint32Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    default:
+      fail("Unhandled type");
+      break;
+    }
+
+    // Some types preserve NaN values; all other types convert NaN to zero.
+    if (type === Float32Array) {
+      assert('initial NaN preserved', isNaN(new type([NaN])[0]));
+      for (var i = 0; i < array.length; ++i)
+        assert('NaN preserved via setter', isNaN(results[i]));
+    } else {
+      assertEq('initial NaN converted to zero', 0, new type([NaN])[0]);
+      for (var i = 0; i < array.length; ++i)
+        assertEq('NaN converted to zero by setter', 0, results[i]);
+    }
+
+    pass();
+  } catch (e) {
+      fail(e);
+  }
+}
+
 //
 // Test driver
 //
@@ -659,6 +734,7 @@ function runTests() {
     testSettingFromFakeArrayWithOutOfRangeLength(type, name);
     testSettingFromTypedArrayWithOutOfRangeOffset(type, name);
     negativeTestGetAndSetMethods(type, name);
+    testNaNConversion(type, name);
   }
 
   printSummary();
index 737cd44..4d9aedf 100644 (file)
@@ -1,3 +1,19 @@
+2011-01-04  Adrienne Walker  <enne@google.com>
+
+        Reviewed by Kenneth Russell.
+
+        NaN in a TypedArray should be converted to zero only for Float32Array.
+        https://bugs.webkit.org/show_bug.cgi?id=46990
+
+        Test: LayoutTests/fast/canvas/webgl/array-unit-tests.html
+
+        * bindings/js/JSArrayBufferViewHelper.h:
+        (WebCore::convertArrayValue):
+        (WebCore::constructArrayBufferView):
+        * html/canvas/Float32Array.h:
+        (WebCore::Float32Array::set):
+        (WebCore::Float32Array::item):
+
 2011-01-06  Patrick Gansterer  <paroga@webkit.org>
 
         Unreviewed Windows build fix for r75161.
index f34f4b9..e010406 100644 (file)
@@ -104,6 +104,25 @@ PassRefPtr<C> constructArrayBufferViewWithArrayBufferArgument(JSC::ExecState* ex
     return array;
 }
 
+template<typename T>
+inline T convertArrayValue(JSC::ExecState* exec, JSC::JSValue v)
+{
+    // For integral types, NaN values must be converted to zero.
+    return static_cast<T>(v.toInteger(exec));
+}
+
+template<>
+inline float convertArrayValue(JSC::ExecState* exec, JSC::JSValue v)
+{
+    return static_cast<float>(v.toNumber(exec));
+}
+
+template<>
+inline double convertArrayValue(JSC::ExecState* exec, JSC::JSValue v)
+{
+    return static_cast<double>(v.toNumber(exec));
+}
+
 template<class C, typename T>
 PassRefPtr<C> constructArrayBufferView(JSC::ExecState* exec)
 {
@@ -144,9 +163,7 @@ PassRefPtr<C> constructArrayBufferView(JSC::ExecState* exec)
         OwnFastMallocPtr<T> values(static_cast<T*>(tempValues));
         for (unsigned i = 0; i < length; ++i) {
             JSC::JSValue v = array->get(exec, i);
-            if (exec->hadException())
-                return 0;
-            values.get()[i] = static_cast<T>(v.toNumber(exec));
+            values.get()[i] = convertArrayValue<T>(exec, v);
         }
         
         RefPtr<C> result = C::create(values.get(), length);
index c03fcc3..d00a7c5 100644 (file)
@@ -44,8 +44,6 @@ public:
     {
         if (index >= TypedArrayBase<float>::m_length)
             return;
-        if (isnan(value)) // Clamp NaN to 0
-            value = 0;
         TypedArrayBase<float>::data()[index] = static_cast<float>(value);
     }
 
@@ -55,10 +53,6 @@ public:
     {
         ASSERT(index < TypedArrayBase<float>::m_length);
         float result = TypedArrayBase<float>::data()[index];
-        if (isnan(result)) {
-            // Clamp NaN to 0
-            result = 0;
-        }
         return result;
     }