speciesConstruct needs to throw if the result is a DataView
authorkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Jun 2019 23:07:28 +0000 (23:07 +0000)
committerkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Jun 2019 23:07:28 +0000 (23:07 +0000)
https://bugs.webkit.org/show_bug.cgi?id=199231

Reviewed by Mark Lam.

JSTests:

* stress/typedarray-filter.js:
(subclasses.forEach):
* stress/typedarray-map.js:
(subclasses.forEach):
* stress/typedarray-slice.js:
(typedArrays.forEach):
* stress/typedarray-subarray.js:
(subclasses.forEach):

Source/JavaScriptCore:

Previously, we only checked that the result was a
JSArrayBufferView, which can include DataViews. This is incorrect
as the result should be only be a TypedArray.

* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::speciesConstruct):

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

JSTests/ChangeLog
JSTests/stress/typedarray-filter.js
JSTests/stress/typedarray-map.js
JSTests/stress/typedarray-slice.js
JSTests/stress/typedarray-subarray.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h

index aaf13ec..e8f2838 100644 (file)
@@ -1,3 +1,19 @@
+2019-06-26  Keith Miller  <keith_miller@apple.com>
+
+        speciesConstruct needs to throw if the result is a DataView
+        https://bugs.webkit.org/show_bug.cgi?id=199231
+
+        Reviewed by Mark Lam.
+
+        * stress/typedarray-filter.js:
+        (subclasses.forEach):
+        * stress/typedarray-map.js:
+        (subclasses.forEach):
+        * stress/typedarray-slice.js:
+        (typedArrays.forEach):
+        * stress/typedarray-subarray.js:
+        (subclasses.forEach):
+
 2019-06-24  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r246714.
index 5e85923..7ce7bbf 100644 (file)
@@ -91,6 +91,17 @@ shouldBeTrue("forEachTypedArray(subclasses, testSpeciesIsDefault)");
 subclasses.forEach(function(constructor) { constructor[Symbol.species] = undefined; });
 shouldBeTrue("forEachTypedArray(subclasses, testSpeciesIsDefault)");
 
+subclasses.forEach(function(constructor) { constructor[Symbol.species] = () => new DataView(new ArrayBuffer()); });
+function testSpeciesReturnsDataView(array, constructor) {
+    try {
+        array.filter(accept);
+    } catch (e) {
+        return e instanceof TypeError;
+    }
+    return false;
+}
+shouldBeTrue("forEachTypedArray(subclasses, testSpeciesReturnsDataView)");
+
 subclasses = typedArrays.map(function(constructor) { return class extends constructor { } } );
 function testSpeciesRemoveConstructor(array, constructor) {
     array.constructor = undefined;
@@ -100,4 +111,5 @@ function testSpeciesRemoveConstructor(array, constructor) {
 }
 
 shouldBeTrue("forEachTypedArray(subclasses, testSpeciesRemoveConstructor)");
+
 finishJSTest();
index 1d9a890..8dad222 100644 (file)
@@ -90,6 +90,17 @@ shouldBeTrue("forEachTypedArray(subclasses, testSpeciesIsDefault)");
 subclasses.forEach(function(constructor) { constructor[Symbol.species] = undefined; });
 shouldBeTrue("forEachTypedArray(subclasses, testSpeciesIsDefault)");
 
+subclasses.forEach(function(constructor) { constructor[Symbol.species] = () => new DataView(new ArrayBuffer()); });
+function testSpeciesReturnsDataView(array, constructor) {
+    try {
+        array.map(id);
+    } catch (e) {
+        return e instanceof TypeError;
+    }
+    return false;
+}
+shouldBeTrue("forEachTypedArray(subclasses, testSpeciesReturnsDataView)");
+
 subclasses = typedArrays.map(function(constructor) { return class extends constructor { } } );
 function testSpeciesRemoveConstructor(array, constructor) {
     array.constructor = undefined;
index 99cbba6..fbcb1f8 100644 (file)
@@ -169,4 +169,15 @@ function testSpeciesWithTransferring(unused, constructor) {
 
 shouldBeTrue("forEachTypedArray(typedArrays, testSpeciesWithTransferring)");
 
+typedArrays.forEach(function(constructor) { constructor[Symbol.species] = () => new DataView(new ArrayBuffer()); });
+function testSpeciesReturnsDataView(array, constructor) {
+    try {
+        array.slice(0, 1);
+    } catch (e) {
+        return e instanceof TypeError;
+    }
+    return false;
+}
+shouldBeTrue("forEachTypedArray(typedArrays, testSpeciesReturnsDataView)");
+
 finishJSTest();
index eb730e4..8f3295f 100644 (file)
@@ -48,6 +48,17 @@ shouldBeTrue("forEachTypedArray(subclasses, testSpeciesIsDefault)");
 subclasses.forEach(function(constructor) { constructor[Symbol.species] = undefined; });
 shouldBeTrue("forEachTypedArray(subclasses, testSpeciesIsDefault)");
 
+subclasses.forEach(function(constructor) { constructor[Symbol.species] = () => new DataView(new ArrayBuffer()); });
+function testSpeciesReturnsDataView(array, constructor) {
+    try {
+        array.subarray(0, 0);
+    } catch (e) {
+        return e instanceof TypeError;
+    }
+    return false;
+}
+shouldBeTrue("forEachTypedArray(subclasses, testSpeciesReturnsDataView)");
+
 subclasses = typedArrays.map(function(constructor) { return class extends constructor { } } );
 function testSpeciesRemoveConstructor(array, constructor) {
     array.constructor = undefined;
index 3531e9e..bfab347 100644 (file)
@@ -1,3 +1,17 @@
+2019-06-26  Keith Miller  <keith_miller@apple.com>
+
+        speciesConstruct needs to throw if the result is a DataView
+        https://bugs.webkit.org/show_bug.cgi?id=199231
+
+        Reviewed by Mark Lam.
+
+        Previously, we only checked that the result was a
+        JSArrayBufferView, which can include DataViews. This is incorrect
+        as the result should be only be a TypedArray.
+
+        * runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
+        (JSC::speciesConstruct):
+
 2019-06-26  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Implement console.countReset
index 89a9717..adb3279 100644 (file)
@@ -70,6 +70,11 @@ inline JSArrayBufferView* speciesConstruct(ExecState* exec, JSObject* exemplar,
     RETURN_IF_EXCEPTION(scope, nullptr);
 
     if (JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(vm, result)) {
+        if (view->type() == DataViewType) {
+            throwTypeError(exec, scope, "species constructor did not return a TypedArray View"_s);
+            return nullptr;
+        }
+
         if (!view->isNeutered())
             return view;