Title: [280593] trunk
Revision
280593
Author
[email protected]
Date
2021-08-03 08:59:27 -0700 (Tue, 03 Aug 2021)

Log Message

ReadableStream's pipeTo() and pipeThrough() don't handle options in spec-perfect way
https://bugs.webkit.org/show_bug.cgi?id=227690
<rdar://problem/80482144>

LayoutTests/imported/w3c:

Reviewed by Alexey Shvayka .

* web-platform-tests/streams/piping/general.any-expected.txt:
* web-platform-tests/streams/piping/general.any.worker-expected.txt:
* web-platform-tests/streams/piping/pipe-through.any-expected.txt:
* web-platform-tests/streams/piping/pipe-through.any.js:
(tryPipeThrough):
(test.get assert_equals):
* web-platform-tests/streams/piping/pipe-through.any.worker-expected.txt:
* web-platform-tests/streams/piping/throwing-options.any-expected.txt:
* web-platform-tests/streams/piping/throwing-options.any.worker-expected.txt:

Source/WebCore:

Reviewed by Alexey Shvayka.

Order getters as per spec for pipeTo and pipeThrough.
Handle the case of null dictionaries as if they are undefined
Use getter instead of using 'in' as per WebIDL spec.
If options is undefined, skip calling any getter.

Covered by updated test.

* Modules/streams/ReadableStream.js:
(pipeThrough):
(pipeTo):

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (280592 => 280593)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-08-03 15:59:27 UTC (rev 280593)
@@ -1,3 +1,21 @@
+2021-08-03  Youenn Fablet  <[email protected]>
+
+        ReadableStream's pipeTo() and pipeThrough() don't handle options in spec-perfect way
+        https://bugs.webkit.org/show_bug.cgi?id=227690
+        <rdar://problem/80482144>
+
+        Reviewed by Alexey Shvayka .
+
+        * web-platform-tests/streams/piping/general.any-expected.txt:
+        * web-platform-tests/streams/piping/general.any.worker-expected.txt:
+        * web-platform-tests/streams/piping/pipe-through.any-expected.txt:
+        * web-platform-tests/streams/piping/pipe-through.any.js:
+        (tryPipeThrough):
+        (test.get assert_equals):
+        * web-platform-tests/streams/piping/pipe-through.any.worker-expected.txt:
+        * web-platform-tests/streams/piping/throwing-options.any-expected.txt:
+        * web-platform-tests/streams/piping/throwing-options.any.worker-expected.txt:
+
 2021-08-03  Cathie Chen  <[email protected]>
 
         Import css/css-sizing/aspect-ratio tests from WPT

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/general.any-expected.txt (280592 => 280593)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/general.any-expected.txt	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/general.any-expected.txt	2021-08-03 15:59:27 UTC (rev 280593)
@@ -12,5 +12,5 @@
 PASS an undefined rejection from write should cause pipeTo() to reject when preventCancel is true
 PASS an undefined rejection from write should cause pipeTo() to reject when preventCancel is false
 PASS pipeTo() should reject if an option getter grabs a writer
-FAIL pipeTo() promise should resolve if null is passed null is not an Object.
+PASS pipeTo() promise should resolve if null is passed
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/general.any.worker-expected.txt (280592 => 280593)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/general.any.worker-expected.txt	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/general.any.worker-expected.txt	2021-08-03 15:59:27 UTC (rev 280593)
@@ -12,5 +12,5 @@
 PASS an undefined rejection from write should cause pipeTo() to reject when preventCancel is true
 PASS an undefined rejection from write should cause pipeTo() to reject when preventCancel is false
 PASS pipeTo() should reject if an option getter grabs a writer
-FAIL pipeTo() promise should resolve if null is passed null is not an Object.
+PASS pipeTo() promise should resolve if null is passed
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any-expected.txt (280592 => 280593)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any-expected.txt	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any-expected.txt	2021-08-03 15:59:27 UTC (rev 280593)
@@ -41,4 +41,7 @@
 PASS preventClose should work
 PASS preventAbort should work
 PASS pipeThrough() should throw if an option getter grabs a writer
+PASS pipeThrough() should not throw if option is null
+PASS pipeThrough() should not throw if signal is undefined
+PASS pipeThrough() should throw if readable/writable getters throw
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any.js (280592 => 280593)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any.js	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any.js	2021-08-03 15:59:27 UTC (rev 280593)
@@ -266,3 +266,66 @@
     }
   }), 'pipeThrough should throw');
 }, 'pipeThrough() should throw if an option getter grabs a writer');
+
+test(() => {
+  const rs = new ReadableStream();
+  const readable = new ReadableStream();
+  const writable = new WritableStream();
+  rs.pipeThrough({readable, writable}, null);
+}, 'pipeThrough() should not throw if option is null');
+
+test(() => {
+  const rs = new ReadableStream();
+  const readable = new ReadableStream();
+  const writable = new WritableStream();
+  rs.pipeThrough({readable, writable}, {signal:undefined});
+}, 'pipeThrough() should not throw if signal is undefined');
+
+function tryPipeThrough(pair, options)
+{
+  const rs = new ReadableStream();
+  if (!pair)
+    pair = {readable:new ReadableStream(), writable:new WritableStream()};
+  try {
+    rs.pipeThrough(pair, options)
+  } catch (e) {
+    return e;
+  }
+}
+
+test(() => {
+  let result = tryPipeThrough({
+    get readable() {
+      return new ReadableStream();
+    },
+    get writable() {
+      throw "writable threw";
+    }
+  }, { });
+  assert_equals(result, "writable threw");
+
+  result = tryPipeThrough({
+    get readable() {
+      throw "readable threw";
+    },
+    get writable() {
+      throw "writable threw";
+    }
+  }, { });
+  assert_equals(result, "readable threw");
+
+  result = tryPipeThrough({
+    get readable() {
+      throw "readable threw";
+    },
+    get writable() {
+      throw "writable threw";
+    }
+  }, {
+    get preventAbort() {
+      throw "preventAbort threw";
+    }
+  });
+  assert_equals(result, "readable threw");
+
+}, 'pipeThrough() should throw if readable/writable getters throw');

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any.worker-expected.txt (280592 => 280593)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any.worker-expected.txt	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any.worker-expected.txt	2021-08-03 15:59:27 UTC (rev 280593)
@@ -41,4 +41,7 @@
 PASS preventClose should work
 PASS preventAbort should work
 PASS pipeThrough() should throw if an option getter grabs a writer
+PASS pipeThrough() should not throw if option is null
+PASS pipeThrough() should not throw if signal is undefined
+PASS pipeThrough() should throw if readable/writable getters throw
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/throwing-options.any-expected.txt (280592 => 280593)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/throwing-options.any-expected.txt	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/throwing-options.any-expected.txt	2021-08-03 15:59:27 UTC (rev 280593)
@@ -1,22 +1,10 @@
 
-FAIL pipeTo should stop after getting preventAbort throws promise_rejects_js: pipeTo should reject function "function () { throw e }" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeThrough should stop after getting preventAbort throws assert_throws_js: pipeThrough should throw function "() => new ReadableStream().pipeThrough(new TransformStream(), options)" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeTo should stop after getting preventCancel throws promise_rejects_js: pipeTo should reject function "function () { throw e }" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeThrough should stop after getting preventCancel throws assert_throws_js: pipeThrough should throw function "() => new ReadableStream().pipeThrough(new TransformStream(), options)" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeTo should stop after getting preventClose throws promise_rejects_js: pipeTo should reject function "function () { throw e }" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeThrough should stop after getting preventClose throws assert_throws_js: pipeThrough should throw function "() => new ReadableStream().pipeThrough(new TransformStream(), options)" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeTo should stop after getting signal throws signal
-FAIL pipeThrough should stop after getting signal throws assert_array_equals: options should be touched in the right order lengths differ, expected array ["preventAbort", "preventCancel", "preventClose", "signal"] length 4, got ["signal"] length 1
+PASS pipeTo should stop after getting preventAbort throws
+PASS pipeThrough should stop after getting preventAbort throws
+PASS pipeTo should stop after getting preventCancel throws
+PASS pipeThrough should stop after getting preventCancel throws
+PASS pipeTo should stop after getting preventClose throws
+PASS pipeThrough should stop after getting preventClose throws
+PASS pipeTo should stop after getting signal throws
+PASS pipeThrough should stop after getting signal throws
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/throwing-options.any.worker-expected.txt (280592 => 280593)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/throwing-options.any.worker-expected.txt	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/throwing-options.any.worker-expected.txt	2021-08-03 15:59:27 UTC (rev 280593)
@@ -1,22 +1,10 @@
 
-FAIL pipeTo should stop after getting preventAbort throws promise_rejects_js: pipeTo should reject function "function () { throw e }" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeThrough should stop after getting preventAbort throws assert_throws_js: pipeThrough should throw function "() => new ReadableStream().pipeThrough(new TransformStream(), options)" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeTo should stop after getting preventCancel throws promise_rejects_js: pipeTo should reject function "function () { throw e }" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeThrough should stop after getting preventCancel throws assert_throws_js: pipeThrough should throw function "() => new ReadableStream().pipeThrough(new TransformStream(), options)" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeTo should stop after getting preventClose throws promise_rejects_js: pipeTo should reject function "function () { throw e }" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeThrough should stop after getting preventClose throws assert_throws_js: pipeThrough should throw function "() => new ReadableStream().pipeThrough(new TransformStream(), options)" threw object "TypeError: options.signal must be AbortSignal" ("TypeError") expected instance of function "function Error() {
-    [native code]
-}" ("Error")
-FAIL pipeTo should stop after getting signal throws signal
-FAIL pipeThrough should stop after getting signal throws assert_array_equals: options should be touched in the right order lengths differ, expected array ["preventAbort", "preventCancel", "preventClose", "signal"] length 4, got ["signal"] length 1
+PASS pipeTo should stop after getting preventAbort throws
+PASS pipeThrough should stop after getting preventAbort throws
+PASS pipeTo should stop after getting preventCancel throws
+PASS pipeThrough should stop after getting preventCancel throws
+PASS pipeTo should stop after getting preventClose throws
+PASS pipeThrough should stop after getting preventClose throws
+PASS pipeTo should stop after getting signal throws
+PASS pipeThrough should stop after getting signal throws
 

Modified: trunk/Source/WebCore/ChangeLog (280592 => 280593)


--- trunk/Source/WebCore/ChangeLog	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/Source/WebCore/ChangeLog	2021-08-03 15:59:27 UTC (rev 280593)
@@ -1,5 +1,24 @@
 2021-08-03  Youenn Fablet  <[email protected]>
 
+        ReadableStream's pipeTo() and pipeThrough() don't handle options in spec-perfect way
+        https://bugs.webkit.org/show_bug.cgi?id=227690
+        <rdar://problem/80482144>
+
+        Reviewed by Alexey Shvayka.
+
+        Order getters as per spec for pipeTo and pipeThrough.
+        Handle the case of null dictionaries as if they are undefined
+        Use getter instead of using 'in' as per WebIDL spec.
+        If options is undefined, skip calling any getter.
+
+        Covered by updated test.
+
+        * Modules/streams/ReadableStream.js:
+        (pipeThrough):
+        (pipeTo):
+
+2021-08-03  Youenn Fablet  <[email protected]>
+
         Update FirstWithDOMWindowReuseRestriction linked-on-or-after check to latest MacOS/iOS betas
         https://bugs.webkit.org/show_bug.cgi?id=228736
         <rdar://81419036>

Modified: trunk/Source/WebCore/Modules/streams/ReadableStream.js (280592 => 280593)


--- trunk/Source/WebCore/Modules/streams/ReadableStream.js	2021-08-03 15:50:29 UTC (rev 280592)
+++ trunk/Source/WebCore/Modules/streams/ReadableStream.js	2021-08-03 15:59:27 UTC (rev 280593)
@@ -116,12 +116,6 @@
     "use strict";
 
     if (@writableStreamAPIEnabled()) {
-        if (!@isReadableStream(this))
-            throw @makeThisTypeError("ReadableStream", "pipeThrough");
-
-        if (@isReadableStreamLocked(this))
-            throw @makeTypeError("ReadableStream is locked");
-
         const transforms = streams;
 
         const readable = transforms["readable"];
@@ -132,20 +126,29 @@
         if (!@isWritableStream(writable))
             throw @makeTypeError("writable should be WritableStream");
 
-        if (options === @undefined)
-            options = { };
+        let preventClose = false;
+        let preventAbort = false;
+        let preventCancel = false;
+        let signal;
+        if (!@isUndefinedOrNull(options)) {
+            if (!@isObject(options))
+                throw @makeTypeError("options must be an object");
 
-        let signal;
-        if ("signal" in options) {
+            preventAbort = !!options["preventAbort"];
+            preventCancel = !!options["preventCancel"];
+            preventClose = !!options["preventClose"];
+
             signal = options["signal"];
-            if (!(signal instanceof @AbortSignal))
+            if (signal !== @undefined && !(signal instanceof @AbortSignal))
                 throw @makeTypeError("options.signal must be AbortSignal");
         }
 
-        const preventClose = !!options["preventClose"];
-        const preventAbort = !!options["preventAbort"];
-        const preventCancel = !!options["preventCancel"];
+        if (!@isReadableStream(this))
+            throw @makeThisTypeError("ReadableStream", "pipeThrough");
 
+        if (@isReadableStreamLocked(this))
+            throw @makeTypeError("ReadableStream is locked");
+
         if (@isWritableStreamLocked(writable))
             throw @makeTypeError("WritableStream is locked");
 
@@ -171,27 +174,34 @@
     let options = arguments[1];
 
     if (@writableStreamAPIEnabled()) {
-        if (!@isReadableStream(this))
-            return @Promise.@reject(@makeThisTypeError("ReadableStream", "pipeTo"));
+        let preventClose = false;
+        let preventAbort = false;
+        let preventCancel = false;
+        let signal;
+        if (!@isUndefinedOrNull(options)) {
+            if (!@isObject(options))
+                return @Promise.@reject(@makeTypeError("options must be an object"));
 
-        if (!@isWritableStream(destination))
-            return @Promise.@reject(@makeTypeError("ReadableStream pipeTo requires a WritableStream"));
+            try {
+                preventAbort = !!options["preventAbort"];
+                preventCancel = !!options["preventCancel"];
+                preventClose = !!options["preventClose"];
 
-        if (options === @undefined)
-            options = { };
+                signal = options["signal"];
+            } catch(e) {
+                return @Promise.@reject(e);
+            }
 
-        // FIXME. We should catch exceptions and reject.
-        let signal;
-        if ("signal" in options) {
-            signal = options["signal"];
-            if (!(signal instanceof @AbortSignal))
+            if (signal !== @undefined && !(signal instanceof @AbortSignal))
                 return @Promise.@reject(@makeTypeError("options.signal must be AbortSignal"));
         }
 
-        const preventClose = !!options["preventClose"];
-        const preventAbort = !!options["preventAbort"];
-        const preventCancel = !!options["preventCancel"];
+        if (!@isWritableStream(destination))
+            return @Promise.@reject(@makeTypeError("ReadableStream pipeTo requires a WritableStream"));
 
+        if (!@isReadableStream(this))
+            return @Promise.@reject(@makeThisTypeError("ReadableStream", "pipeTo"));
+
         if (@isReadableStreamLocked(this))
             return @Promise.@reject(@makeTypeError("ReadableStream is locked"));
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to