From fd3e5ecb1b28c9435ea88ff9c7a5a7e27a2126b0 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 4 Oct 2019 01:42:06 +0000 Subject: [PATCH] Bug 1526596 [wpt PR 15097] - ReadableStream asyncIterator, a=testonly Automatic update from web-platform-tests ReadableStream asyncIterator (#15097) Test async iteration of ReadableStream. Standard changes are in https://github.com/whatwg/streams/pull/980. -- wpt-commits: de6f8fcf9b87e80811e9267a886cf891f6f864e0 wpt-pr: 15097 UltraBlame original commit: a3f2954c055c5c09fb25ea019b6efc555fcd127c --- .../readable-streams/async-iterator.any.js | 2244 +++++++++++++++++ .../readable-streams/brand-checks.any.js | 152 ++ .../streams/readable-streams/general.any.js | 174 +- .../readable-streams/patched-global.any.js | 298 +++ 4 files changed, 2867 insertions(+), 1 deletion(-) create mode 100644 testing/web-platform/tests/streams/readable-streams/async-iterator.any.js diff --git a/testing/web-platform/tests/streams/readable-streams/async-iterator.any.js b/testing/web-platform/tests/streams/readable-streams/async-iterator.any.js new file mode 100644 index 0000000000000..df17e28e3b4b3 --- /dev/null +++ b/testing/web-platform/tests/streams/readable-streams/async-iterator.any.js @@ -0,0 +1,2244 @@ +' +use +strict +' +; +test +( +( +) += +> +{ +assert_equals +( +ReadableStream +. +prototype +[ +Symbol +. +asyncIterator +] +ReadableStream +. +prototype +. +getIterator +) +; +} +' +asyncIterator +( +) +method +is += += += +to +getIterator +( +) +method +' +) +; +test +( +( +) += +> +{ +const +s += +new +ReadableStream +( +) +; +const +it += +s +. +getIterator +( +) +; +const +proto += +Object +. +getPrototypeOf +( +it +) +; +const +AsyncIteratorPrototype += +Object +. +getPrototypeOf +( +Object +. +getPrototypeOf +( +async +function +* +( +) +{ +} +) +. +prototype +) +; +assert_equals +( +Object +. +getPrototypeOf +( +proto +) +AsyncIteratorPrototype +' +prototype +should +extend +AsyncIteratorPrototype +' +) +; +const +methods += +[ +' +next +' +' +return +' +] +. +sort +( +) +; +assert_array_equals +( +Object +. +getOwnPropertyNames +( +proto +) +. +sort +( +) +methods +' +should +have +all +the +correct +methods +' +) +; +for +( +const +m +of +methods +) +{ +const +propDesc += +Object +. +getOwnPropertyDescriptor +( +proto +m +) +; +assert_false +( +propDesc +. +enumerable +' +method +should +be +non +- +enumerable +' +) +; +assert_true +( +propDesc +. +configurable +' +method +should +be +configurable +' +) +; +assert_true +( +propDesc +. +writable +' +method +should +be +writable +' +) +; +assert_equals +( +typeof +it +[ +m +] +' +function +' +' +method +should +be +a +function +' +) +; +assert_equals +( +it +[ +m +] +. +name +m +' +method +should +have +the +correct +name +' +) +; +} +assert_equals +( +it +. +next +. +length +0 +' +next +should +have +no +parameters +' +) +; +assert_equals +( +it +. +return +. +length +1 +' +return +should +have +1 +parameter +' +) +; +assert_equals +( +typeof +it +. +throw +' +undefined +' +' +throw +should +not +exist +' +) +; +} +' +Async +iterator +instances +should +have +the +correct +list +of +properties +' +) +; +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +1 +) +; +c +. +enqueue +( +2 +) +; +c +. +enqueue +( +3 +) +; +c +. +close +( +) +; +} +} +) +; +const +chunks += +[ +] +; +for +await +( +const +chunk +of +s +) +{ +chunks +. +push +( +chunk +) +; +} +assert_array_equals +( +chunks +[ +1 +2 +3 +] +) +; +} +' +Async +- +iterating +a +push +source +' +) +; +promise_test +( +async +( +) += +> +{ +let +i += +1 +; +const +s += +new +ReadableStream +( +{ +pull +( +c +) +{ +c +. +enqueue +( +i +) +; +if +( +i +> += +3 +) +{ +c +. +close +( +) +; +} +i ++ += +1 +; +} +} +) +; +const +chunks += +[ +] +; +for +await +( +const +chunk +of +s +) +{ +chunks +. +push +( +chunk +) +; +} +assert_array_equals +( +chunks +[ +1 +2 +3 +] +) +; +} +' +Async +- +iterating +a +pull +source +' +) +; +promise_test +( +async +( +) += +> +{ +let +i += +1 +; +const +s += +recordingReadableStream +( +{ +pull +( +c +) +{ +c +. +enqueue +( +i +) +; +if +( +i +> += +3 +) +{ +c +. +close +( +) +; +} +i ++ += +1 +; +} +} +new +CountQueuingStrategy +( +{ +highWaterMark +: +0 +} +) +) +; +const +it += +s +. +getIterator +( +) +; +assert_array_equals +( +s +. +events +[ +] +) +; +const +read1 += +await +it +. +next +( +) +; +assert_equals +( +read1 +. +done +false +) +; +assert_equals +( +read1 +. +value +1 +) +; +assert_array_equals +( +s +. +events +[ +' +pull +' +] +) +; +const +read2 += +await +it +. +next +( +) +; +assert_equals +( +read2 +. +done +false +) +; +assert_equals +( +read2 +. +value +2 +) +; +assert_array_equals +( +s +. +events +[ +' +pull +' +' +pull +' +] +) +; +const +read3 += +await +it +. +next +( +) +; +assert_equals +( +read3 +. +done +false +) +; +assert_equals +( +read3 +. +value +3 +) +; +assert_array_equals +( +s +. +events +[ +' +pull +' +' +pull +' +' +pull +' +] +) +; +const +read4 += +await +it +. +next +( +) +; +assert_equals +( +read4 +. +done +true +) +; +assert_equals +( +read4 +. +value +undefined +) +; +assert_array_equals +( +s +. +events +[ +' +pull +' +' +pull +' +' +pull +' +] +) +; +} +' +Async +- +iterating +a +pull +source +manually +' +) +; +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +error +( +' +e +' +) +; +} +} +) +; +try +{ +for +await +( +const +chunk +of +s +) +{ +} +assert_unreached +( +) +; +} +catch +( +e +) +{ +assert_equals +( +e +' +e +' +) +; +} +} +' +Async +- +iterating +an +errored +stream +throws +' +) +; +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +close +( +) +; +} +} +) +; +for +await +( +const +chunk +of +s +) +{ +assert_unreached +( +) +; +} +} +' +Async +- +iterating +a +closed +stream +never +executes +the +loop +body +but +works +fine +' +) +; +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +) +; +const +loop += +async +( +) += +> +{ +for +await +( +const +chunk +of +s +) +{ +assert_unreached +( +) +; +} +assert_unreached +( +) +; +} +; +await +Promise +. +race +( +[ +loop +( +) +flushAsyncEvents +( +) +] +) +; +} +' +Async +- +iterating +an +empty +but +not +closed +/ +errored +stream +never +executes +the +loop +body +and +stalls +the +async +function +' +) +; +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +1 +) +; +c +. +enqueue +( +2 +) +; +c +. +enqueue +( +3 +) +; +c +. +close +( +) +; +} +} +) +; +const +reader += +s +. +getReader +( +) +; +const +readResult += +await +reader +. +read +( +) +; +assert_equals +( +readResult +. +done +false +) +; +assert_equals +( +readResult +. +value +1 +) +; +reader +. +releaseLock +( +) +; +const +chunks += +[ +] +; +for +await +( +const +chunk +of +s +) +{ +chunks +. +push +( +chunk +) +; +} +assert_array_equals +( +chunks +[ +2 +3 +] +) +; +} +' +Async +- +iterating +a +partially +consumed +stream +' +) +; +for +( +const +type +of +[ +' +throw +' +' +break +' +' +return +' +] +) +{ +for +( +const +preventCancel +of +[ +false +true +] +) +{ +promise_test +( +async +( +) += +> +{ +const +s += +recordingReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +0 +) +; +} +} +) +; +const +loop += +async +( +) += +> +{ +for +await +( +const +c +of +s +. +getIterator +( +{ +preventCancel +} +) +) +{ +if +( +type += += += +' +throw +' +) +{ +throw +new +Error +( +) +; +} +else +if +( +type += += += +' +break +' +) +{ +break +; +} +else +if +( +type += += += +' +return +' +) +{ +return +; +} +} +} +; +try +{ +await +loop +( +) +; +} +catch +( +e +) +{ +} +if +( +preventCancel +) +{ +assert_array_equals +( +s +. +events +[ +' +pull +' +] +cancel +( +) +should +not +be +called +) +; +} +else +{ +assert_array_equals +( +s +. +events +[ +' +pull +' +' +cancel +' +undefined +] +cancel +( +) +should +be +called +) +; +} +} +Cancellation +behavior +when +{ +type +} +ing +inside +loop +body +; +preventCancel += +{ +preventCancel +} +) +; +} +} +for +( +const +preventCancel +of +[ +false +true +] +) +{ +promise_test +( +async +( +) += +> +{ +const +s += +recordingReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +0 +) +; +} +} +) +; +const +it += +s +. +getIterator +( +{ +preventCancel +} +) +; +await +it +. +return +( +) +; +if +( +preventCancel +) +{ +assert_array_equals +( +s +. +events +[ +] +cancel +( +) +should +not +be +called +) +; +} +else +{ +assert_array_equals +( +s +. +events +[ +' +cancel +' +undefined +] +cancel +( +) +should +be +called +) +; +} +} +Cancellation +behavior +when +manually +calling +return +( +) +; +preventCancel += +{ +preventCancel +} +) +; +} +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +) +; +const +it += +s +[ +Symbol +. +asyncIterator +] +( +) +; +await +it +. +return +( +) +; +try +{ +await +it +. +return +( +) +; +assert_unreached +( +) +; +} +catch +( +e +) +{ +} +} +' +Calling +return +( +) +twice +rejects +' +) +; +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +0 +) +; +c +. +close +( +) +; +} +} +) +; +const +it += +s +[ +Symbol +. +asyncIterator +] +( +) +; +const +next += +await +it +. +next +( +) +; +assert_equals +( +Object +. +getPrototypeOf +( +next +) +Object +. +prototype +) +; +assert_array_equals +( +Object +. +getOwnPropertyNames +( +next +) +. +sort +( +) +[ +' +done +' +' +value +' +] +) +; +} +' +next +( +) +\ +' +s +fulfillment +value +has +the +right +shape +' +) +; +promise_test +( +async +t += +> +{ +const +s += +recordingReadableStream +( +) +; +const +it += +s +[ +Symbol +. +asyncIterator +] +( +) +; +it +. +next +( +) +; +await +promise_rejects +( +t +new +TypeError +( +) +it +. +return +( +) +' +return +( +) +should +reject +' +) +; +assert_array_equals +( +s +. +events +[ +' +pull +' +] +) +; +} +' +calling +return +( +) +while +there +are +pending +reads +rejects +' +) +; +test +( +( +) += +> +{ +const +s += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +0 +) +; +c +. +close +( +) +; +} +} +) +; +const +it += +s +. +getIterator +( +) +; +assert_throws +( +new +TypeError +( +) +( +) += +> +s +. +getIterator +( +) +' +getIterator +( +) +should +throw +' +) +; +} +' +getIterator +( +) +throws +if +there +\ +' +s +already +a +lock +' +) +; +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +1 +) +; +c +. +enqueue +( +2 +) +; +c +. +enqueue +( +3 +) +; +c +. +close +( +) +; +} +} +) +; +const +chunks += +[ +] +; +for +await +( +const +chunk +of +s +) +{ +chunks +. +push +( +chunk +) +; +} +assert_array_equals +( +chunks +[ +1 +2 +3 +] +) +; +const +reader += +s +. +getReader +( +) +; +await +reader +. +closed +; +} +' +Acquiring +a +reader +after +exhaustively +async +- +iterating +a +stream +' +) +; +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +1 +) +; +c +. +enqueue +( +2 +) +; +c +. +enqueue +( +3 +) +; +c +. +close +( +) +; +} +} +) +; +const +chunks += +[ +] +; +for +await +( +const +chunk +of +s +) +{ +chunks +. +push +( +chunk +) +; +if +( +chunk +> += +2 +) +{ +break +; +} +} +assert_array_equals +( +chunks +[ +1 +2 +] +) +; +const +reader += +s +. +getReader +( +) +; +await +reader +. +closed +; +} +' +Acquiring +a +reader +after +partially +async +- +iterating +a +stream +' +) +; +promise_test +( +async +( +) += +> +{ +const +s += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +1 +) +; +c +. +enqueue +( +2 +) +; +c +. +enqueue +( +3 +) +; +c +. +close +( +) +; +} +} +) +; +const +chunks += +[ +] +; +for +await +( +const +chunk +of +s +. +getIterator +( +{ +preventCancel +: +true +} +) +) +{ +chunks +. +push +( +chunk +) +; +if +( +chunk +> += +2 +) +{ +break +; +} +} +assert_array_equals +( +chunks +[ +1 +2 +] +) +; +const +reader += +s +. +getReader +( +) +; +const +readResult += +await +reader +. +read +( +) +; +assert_equals +( +readResult +. +done +false +' +should +not +be +closed +yet +' +) +; +assert_equals +( +readResult +. +value +3 +' +should +read +remaining +chunk +' +) +; +await +reader +. +closed +; +} +' +Acquiring +a +reader +and +reading +the +remaining +chunks +after +partially +async +- +iterating +a +stream +with +preventCancel += +true +' +) +; diff --git a/testing/web-platform/tests/streams/readable-streams/brand-checks.any.js b/testing/web-platform/tests/streams/readable-streams/brand-checks.any.js index f91d754f70a1b..f79e8339d3903 100644 --- a/testing/web-platform/tests/streams/readable-streams/brand-checks.any.js +++ b/testing/web-platform/tests/streams/readable-streams/brand-checks.any.js @@ -9,6 +9,9 @@ ReadableStreamDefaultReader let ReadableStreamDefaultController ; +let +ReadableStreamAsyncIteratorPrototype +; test ( ( @@ -79,6 +82,44 @@ indirectly ' ) ; +test +( +( +) += +> +{ +const +rs += +new +ReadableStream +( +) +; +ReadableStreamAsyncIteratorPrototype += +Object +. +getPrototypeOf +( +rs +. +getIterator +( +) +) +; +} +' +Can +get +ReadableStreamAsyncIteratorPrototype +object +indirectly +' +) +; function fakeRS ( @@ -322,6 +363,35 @@ return controller ; } +function +fakeRSAsyncIterator +( +) +{ +return +Object +. +setPrototypeOf +( +{ +next +( +) +{ +} +return +( +value += +undefined +) +{ +} +} +ReadableStreamAsyncIteratorPrototype +) +; +} promise_test ( t @@ -908,3 +978,85 @@ check ' ) ; +promise_test +( +t += +> +{ +return +methodRejectsForAll +( +t +ReadableStreamAsyncIteratorPrototype +' +next +' +[ +fakeRSAsyncIterator +( +) +realRS +( +) +realRSDefaultReader +( +) +undefined +null +] +) +; +} +' +ReadableStreamAsyncIteratorPrototype +. +next +enforces +a +brand +check +' +) +; +promise_test +( +t += +> +{ +return +methodRejectsForAll +( +t +ReadableStreamAsyncIteratorPrototype +' +return +' +[ +fakeRSAsyncIterator +( +) +realRS +( +) +realRSDefaultReader +( +) +undefined +null +] +) +; +} +' +ReadableStreamAsyncIteratorPrototype +. +return +enforces +a +brand +check +' +) +; diff --git a/testing/web-platform/tests/streams/readable-streams/general.any.js b/testing/web-platform/tests/streams/readable-streams/general.any.js index 90d9549e3c936..36fffdf2a8763 100644 --- a/testing/web-platform/tests/streams/readable-streams/general.any.js +++ b/testing/web-platform/tests/streams/readable-streams/general.any.js @@ -350,6 +350,9 @@ pipeTo ' tee ' +' +getIterator +' ] ; const @@ -371,6 +374,15 @@ sort ) ; const +symbols += +[ +Symbol +. +asyncIterator +] +; +const rs = new @@ -407,7 +419,30 @@ have all the correct -methods +properties +' +) +; +assert_array_equals +( +Object +. +getOwnPropertySymbols +( +proto +) +. +sort +( +) +symbols +' +should +have +all +the +correct +symbols ' ) ; @@ -721,6 +756,143 @@ parameters ' ) ; +assert_equals +( +rs +. +getIterator +. +length +0 +' +getIterator +should +have +no +required +parameters +' +) +; +assert_equals +( +rs +[ +Symbol +. +asyncIterator +] +. +length +0 +' +asyncIterator +should +have +no +required +parameters +' +) +; +const +asyncIteratorPropDesc += +Object +. +getOwnPropertyDescriptor +( +proto +Symbol +. +asyncIterator +) +; +assert_false +( +asyncIteratorPropDesc +. +enumerable +' +asyncIterator +should +be +non +- +enumerable +' +) +; +assert_true +( +asyncIteratorPropDesc +. +configurable +' +asyncIterator +should +be +configurable +' +) +; +assert_true +( +asyncIteratorPropDesc +. +writable +' +asyncIterator +should +be +writable +' +) +; +assert_equals +( +typeof +rs +[ +Symbol +. +asyncIterator +] +' +function +' +' +asyncIterator +should +be +a +function +' +) +; +assert_equals +( +rs +[ +Symbol +. +asyncIterator +] +. +name +' +getIterator +' +' +asyncIterator +should +have +the +correct +name +' +) +; } ' ReadableStream diff --git a/testing/web-platform/tests/streams/readable-streams/patched-global.any.js b/testing/web-platform/tests/streams/readable-streams/patched-global.any.js index b1d17411202bc..d074f75d3969c 100644 --- a/testing/web-platform/tests/streams/readable-streams/patched-global.any.js +++ b/testing/web-platform/tests/streams/readable-streams/patched-global.any.js @@ -330,3 +330,301 @@ ReadableStream ' ) ; +promise_test +( +async +t += +> +{ +const +rs += +new +ReadableStream +( +{ +start +( +c +) +{ +c +. +enqueue +( +1 +) +; +c +. +enqueue +( +2 +) +; +c +. +enqueue +( +3 +) +; +c +. +close +( +) +; +} +} +) +; +const +oldReadableStreamGetReader += +ReadableStream +. +prototype +. +getReader +; +const +ReadableStreamDefaultReader += +( +new +ReadableStream +( +) +) +. +getReader +( +) +. +constructor +; +const +oldDefaultReaderRead += +ReadableStreamDefaultReader +. +prototype +. +read +; +const +oldDefaultReaderCancel += +ReadableStreamDefaultReader +. +prototype +. +cancel +; +const +oldDefaultReaderReleaseLock += +ReadableStreamDefaultReader +. +prototype +. +releaseLock +; +self +. +ReadableStream +. +prototype +. +getReader += +function +( +) +{ +throw +new +Error +( +' +patched +getReader +( +) +called +' +) +; +} +; +ReadableStreamDefaultReader +. +prototype +. +read += +function +( +) +{ +throw +new +Error +( +' +patched +read +( +) +called +' +) +; +} +; +ReadableStreamDefaultReader +. +prototype +. +cancel += +function +( +) +{ +throw +new +Error +( +' +patched +cancel +( +) +called +' +) +; +} +; +ReadableStreamDefaultReader +. +prototype +. +releaseLock += +function +( +) +{ +throw +new +Error +( +' +patched +releaseLock +( +) +called +' +) +; +} +; +t +. +add_cleanup +( +( +) += +> +{ +self +. +ReadableStream +. +prototype +. +getReader += +oldReadableStreamGetReader +; +ReadableStreamDefaultReader +. +prototype +. +read += +oldDefaultReaderRead +; +ReadableStreamDefaultReader +. +prototype +. +cancel += +oldDefaultReaderCancel +; +ReadableStreamDefaultReader +. +prototype +. +releaseLock += +oldDefaultReaderReleaseLock +; +} +) +; +for +await +( +const +chunk +of +rs +) +{ +break +; +} +const +reader += +oldReadableStreamGetReader +. +call +( +rs +) +; +await +reader +. +closed +; +} +' +ReadableStream +getIterator +( +) +should +use +the +original +values +of +getReader +( +) +and +ReadableStreamDefaultReader +methods +' +) +;