⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 280593 in webkit


Ignore:
Timestamp:
Aug 3, 2021, 8:59:27 AM (5 years ago)
Author:
youenn@apple.com
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):

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r280592 r280593  
     12021-08-03  Youenn Fablet  <youenn@apple.com>
     2
     3        ReadableStream's pipeTo() and pipeThrough() don't handle options in spec-perfect way
     4        https://bugs.webkit.org/show_bug.cgi?id=227690
     5        <rdar://problem/80482144>
     6
     7        Reviewed by Alexey Shvayka .
     8
     9        * web-platform-tests/streams/piping/general.any-expected.txt:
     10        * web-platform-tests/streams/piping/general.any.worker-expected.txt:
     11        * web-platform-tests/streams/piping/pipe-through.any-expected.txt:
     12        * web-platform-tests/streams/piping/pipe-through.any.js:
     13        (tryPipeThrough):
     14        (test.get assert_equals):
     15        * web-platform-tests/streams/piping/pipe-through.any.worker-expected.txt:
     16        * web-platform-tests/streams/piping/throwing-options.any-expected.txt:
     17        * web-platform-tests/streams/piping/throwing-options.any.worker-expected.txt:
     18
    1192021-08-03  Cathie Chen  <cathiechen@igalia.com>
    220
  • trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/general.any-expected.txt

    r275824 r280593  
    1313PASS an undefined rejection from write should cause pipeTo() to reject when preventCancel is false
    1414PASS pipeTo() should reject if an option getter grabs a writer
    15 FAIL pipeTo() promise should resolve if null is passed null is not an Object.
     15PASS pipeTo() promise should resolve if null is passed
    1616
  • trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/general.any.worker-expected.txt

    r275824 r280593  
    1313PASS an undefined rejection from write should cause pipeTo() to reject when preventCancel is false
    1414PASS pipeTo() should reject if an option getter grabs a writer
    15 FAIL pipeTo() promise should resolve if null is passed null is not an Object.
     15PASS pipeTo() promise should resolve if null is passed
    1616
  • trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any-expected.txt

    r279635 r280593  
    4242PASS preventAbort should work
    4343PASS pipeThrough() should throw if an option getter grabs a writer
     44PASS pipeThrough() should not throw if option is null
     45PASS pipeThrough() should not throw if signal is undefined
     46PASS pipeThrough() should throw if readable/writable getters throw
    4447
  • trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any.js

    r264263 r280593  
    267267  }), 'pipeThrough should throw');
    268268}, 'pipeThrough() should throw if an option getter grabs a writer');
     269
     270test(() => {
     271  const rs = new ReadableStream();
     272  const readable = new ReadableStream();
     273  const writable = new WritableStream();
     274  rs.pipeThrough({readable, writable}, null);
     275}, 'pipeThrough() should not throw if option is null');
     276
     277test(() => {
     278  const rs = new ReadableStream();
     279  const readable = new ReadableStream();
     280  const writable = new WritableStream();
     281  rs.pipeThrough({readable, writable}, {signal:undefined});
     282}, 'pipeThrough() should not throw if signal is undefined');
     283
     284function tryPipeThrough(pair, options)
     285{
     286  const rs = new ReadableStream();
     287  if (!pair)
     288    pair = {readable:new ReadableStream(), writable:new WritableStream()};
     289  try {
     290    rs.pipeThrough(pair, options)
     291  } catch (e) {
     292    return e;
     293  }
     294}
     295
     296test(() => {
     297  let result = tryPipeThrough({
     298    get readable() {
     299      return new ReadableStream();
     300    },
     301    get writable() {
     302      throw "writable threw";
     303    }
     304  }, { });
     305  assert_equals(result, "writable threw");
     306
     307  result = tryPipeThrough({
     308    get readable() {
     309      throw "readable threw";
     310    },
     311    get writable() {
     312      throw "writable threw";
     313    }
     314  }, { });
     315  assert_equals(result, "readable threw");
     316
     317  result = tryPipeThrough({
     318    get readable() {
     319      throw "readable threw";
     320    },
     321    get writable() {
     322      throw "writable threw";
     323    }
     324  }, {
     325    get preventAbort() {
     326      throw "preventAbort threw";
     327    }
     328  });
     329  assert_equals(result, "readable threw");
     330
     331}, 'pipeThrough() should throw if readable/writable getters throw');
  • trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/pipe-through.any.worker-expected.txt

    r279635 r280593  
    4242PASS preventAbort should work
    4343PASS pipeThrough() should throw if an option getter grabs a writer
     44PASS pipeThrough() should not throw if option is null
     45PASS pipeThrough() should not throw if signal is undefined
     46PASS pipeThrough() should throw if readable/writable getters throw
    4447
  • trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/throwing-options.any-expected.txt

    r266228 r280593  
    11
    2 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() {
    3     [native code]
    4 }" ("Error")
    5 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() {
    6     [native code]
    7 }" ("Error")
    8 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() {
    9     [native code]
    10 }" ("Error")
    11 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() {
    12     [native code]
    13 }" ("Error")
    14 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() {
    15     [native code]
    16 }" ("Error")
    17 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() {
    18     [native code]
    19 }" ("Error")
    20 FAIL pipeTo should stop after getting signal throws signal
    21 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
     2PASS pipeTo should stop after getting preventAbort throws
     3PASS pipeThrough should stop after getting preventAbort throws
     4PASS pipeTo should stop after getting preventCancel throws
     5PASS pipeThrough should stop after getting preventCancel throws
     6PASS pipeTo should stop after getting preventClose throws
     7PASS pipeThrough should stop after getting preventClose throws
     8PASS pipeTo should stop after getting signal throws
     9PASS pipeThrough should stop after getting signal throws
    2210
  • trunk/LayoutTests/imported/w3c/web-platform-tests/streams/piping/throwing-options.any.worker-expected.txt

    r266228 r280593  
    11
    2 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() {
    3     [native code]
    4 }" ("Error")
    5 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() {
    6     [native code]
    7 }" ("Error")
    8 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() {
    9     [native code]
    10 }" ("Error")
    11 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() {
    12     [native code]
    13 }" ("Error")
    14 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() {
    15     [native code]
    16 }" ("Error")
    17 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() {
    18     [native code]
    19 }" ("Error")
    20 FAIL pipeTo should stop after getting signal throws signal
    21 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
     2PASS pipeTo should stop after getting preventAbort throws
     3PASS pipeThrough should stop after getting preventAbort throws
     4PASS pipeTo should stop after getting preventCancel throws
     5PASS pipeThrough should stop after getting preventCancel throws
     6PASS pipeTo should stop after getting preventClose throws
     7PASS pipeThrough should stop after getting preventClose throws
     8PASS pipeTo should stop after getting signal throws
     9PASS pipeThrough should stop after getting signal throws
    2210
  • trunk/Source/WebCore/ChangeLog

    r280591 r280593  
     12021-08-03  Youenn Fablet  <youenn@apple.com>
     2
     3        ReadableStream's pipeTo() and pipeThrough() don't handle options in spec-perfect way
     4        https://bugs.webkit.org/show_bug.cgi?id=227690
     5        <rdar://problem/80482144>
     6
     7        Reviewed by Alexey Shvayka.
     8
     9        Order getters as per spec for pipeTo and pipeThrough.
     10        Handle the case of null dictionaries as if they are undefined
     11        Use getter instead of using 'in' as per WebIDL spec.
     12        If options is undefined, skip calling any getter.
     13
     14        Covered by updated test.
     15
     16        * Modules/streams/ReadableStream.js:
     17        (pipeThrough):
     18        (pipeTo):
     19
    1202021-08-03  Youenn Fablet  <youenn@apple.com>
    221
  • trunk/Source/WebCore/Modules/streams/ReadableStream.js

    r279472 r280593  
    117117
    118118    if (@writableStreamAPIEnabled()) {
    119         if (!@isReadableStream(this))
    120             throw @makeThisTypeError("ReadableStream", "pipeThrough");
    121 
    122         if (@isReadableStreamLocked(this))
    123             throw @makeTypeError("ReadableStream is locked");
    124 
    125119        const transforms = streams;
    126120
     
    133127            throw @makeTypeError("writable should be WritableStream");
    134128
    135         if (options === @undefined)
    136             options = { };
    137 
     129        let preventClose = false;
     130        let preventAbort = false;
     131        let preventCancel = false;
    138132        let signal;
    139         if ("signal" in options) {
     133        if (!@isUndefinedOrNull(options)) {
     134            if (!@isObject(options))
     135                throw @makeTypeError("options must be an object");
     136
     137            preventAbort = !!options["preventAbort"];
     138            preventCancel = !!options["preventCancel"];
     139            preventClose = !!options["preventClose"];
     140
    140141            signal = options["signal"];
    141             if (!(signal instanceof @AbortSignal))
     142            if (signal !== @undefined && !(signal instanceof @AbortSignal))
    142143                throw @makeTypeError("options.signal must be AbortSignal");
    143144        }
    144145
    145         const preventClose = !!options["preventClose"];
    146         const preventAbort = !!options["preventAbort"];
    147         const preventCancel = !!options["preventCancel"];
     146        if (!@isReadableStream(this))
     147            throw @makeThisTypeError("ReadableStream", "pipeThrough");
     148
     149        if (@isReadableStreamLocked(this))
     150            throw @makeTypeError("ReadableStream is locked");
    148151
    149152        if (@isWritableStreamLocked(writable))
     
    172175
    173176    if (@writableStreamAPIEnabled()) {
     177        let preventClose = false;
     178        let preventAbort = false;
     179        let preventCancel = false;
     180        let signal;
     181        if (!@isUndefinedOrNull(options)) {
     182            if (!@isObject(options))
     183                return @Promise.@reject(@makeTypeError("options must be an object"));
     184
     185            try {
     186                preventAbort = !!options["preventAbort"];
     187                preventCancel = !!options["preventCancel"];
     188                preventClose = !!options["preventClose"];
     189
     190                signal = options["signal"];
     191            } catch(e) {
     192                return @Promise.@reject(e);
     193            }
     194
     195            if (signal !== @undefined && !(signal instanceof @AbortSignal))
     196                return @Promise.@reject(@makeTypeError("options.signal must be AbortSignal"));
     197        }
     198
     199        if (!@isWritableStream(destination))
     200            return @Promise.@reject(@makeTypeError("ReadableStream pipeTo requires a WritableStream"));
     201
    174202        if (!@isReadableStream(this))
    175203            return @Promise.@reject(@makeThisTypeError("ReadableStream", "pipeTo"));
    176 
    177         if (!@isWritableStream(destination))
    178             return @Promise.@reject(@makeTypeError("ReadableStream pipeTo requires a WritableStream"));
    179 
    180         if (options === @undefined)
    181             options = { };
    182 
    183         // FIXME. We should catch exceptions and reject.
    184         let signal;
    185         if ("signal" in options) {
    186             signal = options["signal"];
    187             if (!(signal instanceof @AbortSignal))
    188                 return @Promise.@reject(@makeTypeError("options.signal must be AbortSignal"));
    189         }
    190 
    191         const preventClose = !!options["preventClose"];
    192         const preventAbort = !!options["preventAbort"];
    193         const preventCancel = !!options["preventCancel"];
    194204
    195205        if (@isReadableStreamLocked(this))
Note: See TracChangeset for help on using the changeset viewer.