diff options
author | Gregory Terzian <2792687+gterzian@users.noreply.github.com> | 2024-12-18 05:14:00 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-17 21:14:00 +0000 |
commit | 379bbb41dde5c46ff39cfc9027d7df49fae733b8 (patch) | |
tree | b8224b9e9d088885fcb3dff405118d5ef932080f /components/script/dom/readablestreamdefaultreader.rs | |
parent | 026d3717177def1b77e8790f3f045feea66df872 (diff) | |
download | servo-379bbb41dde5c46ff39cfc9027d7df49fae733b8.tar.gz servo-379bbb41dde5c46ff39cfc9027d7df49fae733b8.zip |
Dom: Re-implement `ReadableStream` Part 1 : Default `Reader` and `Controller` (#34064)
* Re-implement readablestream: basics and default reader and controller
---------
Co-authored-by: Jason Tsai <jason@pews.dev>
Signed-off-by: Wu Wayne <yuweiwu@pm.me>
Add remaining WebIDLs of ReadableStream (#32605)
* Add Reader's WebIDL files
* Add necessary methods in ReadableStream.webidl
Signed-off-by: Wu Wayne <yuweiwu@pm.me>
Create safe wrapper for JSFunctions (#32620)
* Create safe wrapper for JSFunctions
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Add assert to check if the name ends in a null character
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Create macro to wrap unsafe extern "C" function calls
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Remove WRAPPER_FN
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Add macro example documentation
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Use C-string literals
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Ensure name is Cstr type
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Scope #[allow(unsafe_code)]
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
---------
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Wu Wayne <yuweiwu@pm.me>
Start implementation of default controller and reader
Start implementation of default controller and reader
* implement basic internal slots, with todos
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* enum for controller
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* re-implement native controller methods
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* add calling into pull algo
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* more details on chunk enqueuing
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* add fulfill read request, clean-up warnings
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* read request and reader typing
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* allow for more than one non-native underlying source type
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* add todo for should pull
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* add underlying source dom struct container
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* remove rc around source type
* add default controller init in stream constructor
* setup source container with prototype of source dict
* clean-up docs, dispatch of controller in pull algo call
* turn off SM streams
* remove prototype setting on underlying source container
* fix read request promise resolving
* tidy
* clean-up js conversions in read req handlers
* add queue with sizes concept
* use dom in pull promise handlers
* Demonstrate using dictionary as callback this object.
* move value with size to a struct
* fmt
* put readable stream state in a cell
* nits in expectations
* remove allow unroot by passing read result directly to promise resolving
* tidy
* root default controller inside call_pull_if_needed
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Signed-off-by: Wu Wayne <yuweiwu@pm.me>
ReadableStream: implement Cancel and Locked (#33136)
* implement Locked
* implement Cancel and close
Signed-off-by: Wu Wayne <yuweiwu@pm.me>
Add GetPromiseIsHandled and SetAnyPromiseIsHandled to Promise
Signed-off-by: Taym <haddadi.taym@gmail.com>
mach fmt
Signed-off-by: Taym <haddadi.taym@gmail.com>
Readablestream default controller: get desired size (#33497)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
stream: implement controller close (#33498)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
implement stream default controller error (#33503)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Readablestream default controller: enqueue (#33528)
* Implement ReadableStreamDefaultControllerMethods::Enqueue
Signed-off-by: Wu Wayne <yuweiwu@pm.me>
* Add spec comments
Signed-off-by: Wu Wayne <yuweiwu@pm.me>
---------
Signed-off-by: Wu Wayne <yuweiwu@pm.me>
readablestream default controller: fulfill read requests (#33542)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Fix extract_size_algorithm (#33561)
Signed-off-by: Wu Wayne <yuweiwu@pm.me>
Readablestream default controller: use strategy size (#33551)
* readablestream default controller: use strategy size, fallible enqueue
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
docs
* readablestream default controller: clear strategy size
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* prevent potential re-borrow panics when calling into the strategy size
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* document readablestream constructor
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Readablestream: impl default controller should pull, start algo (#33586)
* implement should-pull algo for default controller
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* add start algorithm setup for default controller
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
implement promise native handling for start and pull algorithms (#33603)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Implement ReadableStreamDefaultReader (#33160)
* Implement ReadableStreamDefaultReader
Make the stream mutable
readable-stream-reader-generic-release
Proper error types when releasing
Closed
Cancel
Signed-off-by: Taym <haddadi.taym@gmail.com>
* follow the spec more closely
Signed-off-by: Taym <haddadi.taym@gmail.com>
---------
Signed-off-by: Taym <haddadi.taym@gmail.com>
Implement ReadableStreamDefaultReader read (#34007)
* Implement ReadableStreamDefaultReader read
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Perform readRequest’s error steps with stream.stored_error
Signed-off-by: Taym <haddadi.taym@gmail.com>
---------
Signed-off-by: Taym <haddadi.taym@gmail.com>
Improve ReadableStreamDefaultReader close (#34014)
* improve ReadableStreamDefaultReader close
Signed-off-by: Taym <haddadi.taym@gmail.com>
* remove resolve_closed_promise
Signed-off-by: Taym <haddadi.taym@gmail.com>
---------
Signed-off-by: Taym <haddadi.taym@gmail.com>
Use Rc<Box<[u8]>> for queue to optimize get_in_memory_bytes
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Improve read_a_chunk and stop_reading implemntation (#34077)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Implement ReadableStreamDefaultReader::Constructor (#34056)
* Implement ReadableStreamDefaultReader::Constructor
Signed-off-by: Taym <haddadi.taym@gmail.com>
* make start_reading returns ReadableStreamDefaultReader
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Fix can_gc
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Add canGc to ReadableStream::GetReader
Signed-off-by: Taym <haddadi.taym@gmail.com>
---------
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Readablestream fix CanGc (#34080)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* correct ReadableStream::error_native implementation and fix clippy warnings (#34088)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* turn assertion of stream present on controller on a early return with false (#34097)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Fix already mutably borrowed crash (#34105)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Refactor `get_in_memory_bytes` to return `Option<Vec<u8>> and avoid `unreachable!` panic (#34123)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Set ReadableStream ReadableStreamDefaultReader in start_reading (#34125)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Fix Unhandled rejection with value: object `TypeError: stream is not locked` (#34204)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Fix assert!(self.is_readable()) crash in ReadableStream::close (#34207)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* fix call to to_js_object in underlying source algos (#34098)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* do not assume presence of a stream when performing pull steps (#34244)
* do not assume presence of a stream when performing pull steps
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* add doc comments
Co-authored-by: Taym Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Gregory Terzian <2792687+gterzian@users.noreply.github.com>
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Gregory Terzian <2792687+gterzian@users.noreply.github.com>
Co-authored-by: Taym Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* gracefully handle failure of underlying source algorithms (#34243)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* ensure result of calling start algo is an object (#34245)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* return js failed error if underlying source constructor threw (#34246)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Use JSVal for ValueWithSize::value (#34259)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* fix release reader lock, (#34255)
fix setting stream on controller in new,
fix matching fallthrough,
reduce visibility of controller error method
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* in stream cancel, reject promist if locked (#34271)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Fix UnderlyingSourceContainer::call_start_algorithm (#34277)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* implement controller cancel steps, fix stream cancel method (#34301)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* fix conditional in perform pull steps (#34324)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* set reader closed promise to one resolved with undefined if stream closed on init (#34321)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* fix init of stream and controller (#34323)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Stream: Fix reborrow in controller enqueue, and fix error and exception handling. (#34338)
* fix re-borrow in controller enqueue
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* do not call to_jsval on JSFailed error in enqueue
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* fix error and exception handling in controller enqueue
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* remove TODO about correctness of stored error, since this was done as part of the switch to a js val.
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Stream: Fix incorrect "this" object in underlying source callbacks (#34368)
* in controller close, throw type error if stream cannot be closed
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* store original js object for underlying source, for use as this object in callbacks
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* fix conditional logic in enqueue to ensure pull is called into (#34375)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Stream: Fix bytelength queueing strategy (#34376)
* fix handling of value that is not an object in bytelength queuing strategy
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* return type error if strategy size call fails, to prevent panic because no exception is pending
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* set correct default count queuing size strategy (#34389)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* use proto in stream constructor (#34441)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* fix edge cases in get_desired_size (#34440)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Stream: fix algo and strategy calls error handling. (#34424)
* fix error handling in cancel steps
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* in pull steps, reject promise if pull algo throws
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* if start algorithm fails, rethrow the error
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* when the strategy size fails, directly get the pending exception and use it to error the stream
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* add error handling to enqueue value with size
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* when enqueueing a value errors, ensure we error and stream with the same error used to throw an exception
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* fix native use of streams (#34468)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Implement readablestreamdefaulttee (#34405)
* Implement readablestreamdefaulttee
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Create UnderlyingSourceType::Tee each stream
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Use Dom instead of DomRoot
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Queue a microtask for readRequest chunk steps
Signed-off-by: Taym <haddadi.taym@gmail.com>
* fix create_readable_stream
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Remove unnecessary Rc
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Use correct doc link
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Add #[allow(crown::unrooted_must_root)]
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Fix crash in ClosedPromiseRejectionHandler
Signed-off-by: Taym <haddadi.taym@gmail.com>
* reflect TeeReadRequest and TeeUnderlyingSource
Signed-off-by: Taym <haddadi.taym@gmail.com>
* fix can_gc
Signed-off-by: Taym <haddadi.taym@gmail.com>
* reflect tee source, and fix use of mutable dom for tee source and request
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* Fix typo that resolves multiple test failures in 'Tee' tests
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Fix readable-streams/tee.any.js test
Signed-off-by: Taym <haddadi.taym@gmail.com>
---------
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Co-authored-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Align ReadableStreamDefaultReader with spec and fix additional tests in default-reader.any.js (#34531)
And fix crate::DomTypeHolder usage
* Align ReadableStreamDefaultReader with spec and fix additional tests in default-reader.any.js
Signed-off-by: Taym <haddadi.taym@gmail.com>
* make reader rooted in Constructor and acquire_default_reader
Signed-off-by: Taym <haddadi.taym@gmail.com>
* Remove spaces
Signed-off-by: Taym <haddadi.taym@gmail.com>
---------
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Streams: fetch stream chunks should be uint8 arrays (#34553)
* fetch stream chunks should be uint8 arrays
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
* fix clippy
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
---------
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
Co-authored-by: Taym Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Update wpt test for ReadableStream reimplementation (#34579)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Fix ignore_malloc_size_of in readablestream tee (#34578)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Remove incorrect use of handle array, fail test safely by giving only one reason (#34560)
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Update more wpt test for ReadableStream reimplementation (#34598)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Fix doc and rename Tee to DefaultTee (#34612)
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* fix: Address review comments
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Update response-stream-with-broken-then.any.js.ini test expectation
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* fix reflect_dom_object can_gc
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Fix compositeReason for DefaultTeeUnderlyingSource (#34627)
* Fix compositeReason for DefaultTeeUnderlyingSource
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Update test
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
---------
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
* Last fixes stream (#34636)
* remove now unsused from_js method of readable stream
* fix documenation of error steps
* return type error instread of panicking on a todo, when trying to construct a stream of type bytes
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
---------
Signed-off-by: Gregory Terzian <2792687+gterzian@users.noreply.github.com>
* fix crown rooting related errors (#34662)
Signed-off-by: Gregory Terzian <2792687+gterzian@users.noreply.github.com>
---------
Signed-off-by: Taym <haddadi.taym@gmail.com>
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
Signed-off-by: Gregory Terzian <2792687+gterzian@users.noreply.github.com>
Co-authored-by: Wu Wayne <yuweiwu@pm.me>
Co-authored-by: Taym Haddadi <haddadi.taym@gmail.com>
Diffstat (limited to 'components/script/dom/readablestreamdefaultreader.rs')
-rw-r--r-- | components/script/dom/readablestreamdefaultreader.rs | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/components/script/dom/readablestreamdefaultreader.rs b/components/script/dom/readablestreamdefaultreader.rs new file mode 100644 index 00000000000..0508c363ac9 --- /dev/null +++ b/components/script/dom/readablestreamdefaultreader.rs @@ -0,0 +1,530 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::cell::Cell; +use std::collections::VecDeque; +use std::mem; +use std::rc::Rc; + +use dom_struct::dom_struct; +use js::jsapi::Heap; +use js::jsval::{JSVal, UndefinedValue}; +use js::rust::{HandleObject as SafeHandleObject, HandleValue as SafeHandleValue}; + +use super::bindings::root::MutNullableDom; +use super::types::ReadableStreamDefaultController; +use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultReaderBinding::{ + ReadableStreamDefaultReaderMethods, ReadableStreamReadResult, +}; +use crate::dom::bindings::error::Error; +use crate::dom::bindings::import::module::Fallible; +use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, DomObject, Reflector}; +use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::bindings::trace::RootedTraceableBox; +use crate::dom::defaultteereadrequest::DefaultTeeReadRequest; +use crate::dom::globalscope::GlobalScope; +use crate::dom::promise::Promise; +use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler}; +use crate::dom::readablestream::ReadableStream; +use crate::realms::{enter_realm, InRealm}; +use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; + +/// <https://streams.spec.whatwg.org/#read-request> +#[derive(Clone, JSTraceable)] +#[crown::unrooted_must_root_lint::must_root] +pub enum ReadRequest { + /// <https://streams.spec.whatwg.org/#default-reader-read> + Read(Rc<Promise>), + /// <https://streams.spec.whatwg.org/#ref-for-read-request%E2%91%A2> + DefaultTee { + tee_read_request: Dom<DefaultTeeReadRequest>, + }, +} + +impl ReadRequest { + /// <https://streams.spec.whatwg.org/#read-request-chunk-steps> + pub fn chunk_steps(&self, chunk: RootedTraceableBox<Heap<JSVal>>) { + match self { + ReadRequest::Read(promise) => { + promise.resolve_native(&ReadableStreamReadResult { + done: Some(false), + value: chunk, + }); + }, + ReadRequest::DefaultTee { tee_read_request } => { + tee_read_request.enqueue_chunk_steps(chunk); + }, + } + } + + /// <https://streams.spec.whatwg.org/#read-request-close-steps> + pub fn close_steps(&self) { + match self { + ReadRequest::Read(promise) => { + let result = RootedTraceableBox::new(Heap::default()); + result.set(UndefinedValue()); + promise.resolve_native(&ReadableStreamReadResult { + done: Some(true), + value: result, + }); + }, + ReadRequest::DefaultTee { tee_read_request } => { + tee_read_request.close_steps(); + }, + } + } + + /// <https://streams.spec.whatwg.org/#read-request-error-steps> + pub fn error_steps(&self, e: SafeHandleValue) { + match self { + ReadRequest::Read(promise) => promise.reject_native(&e), + ReadRequest::DefaultTee { tee_read_request } => { + tee_read_request.error_steps(); + }, + } + } +} + +/// The rejection handler for +/// <https://streams.spec.whatwg.org/#readable-stream-tee> +#[derive(Clone, JSTraceable, MallocSizeOf)] +#[crown::unrooted_must_root_lint::must_root] +struct ClosedPromiseRejectionHandler { + branch_1_controller: Dom<ReadableStreamDefaultController>, + branch_2_controller: Dom<ReadableStreamDefaultController>, + #[ignore_malloc_size_of = "Rc"] + canceled_1: Rc<Cell<bool>>, + #[ignore_malloc_size_of = "Rc"] + canceled_2: Rc<Cell<bool>>, + #[ignore_malloc_size_of = "Rc"] + cancel_promise: Rc<Promise>, +} + +impl Callback for ClosedPromiseRejectionHandler { + /// Continuation of <https://streams.spec.whatwg.org/#readable-stream-default-controller-call-pull-if-needed> + /// Upon rejection of reader.[[closedPromise]] with reason r, + fn callback(&self, _cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, _can_gc: CanGc) { + let branch_1_controller = &self.branch_1_controller; + let branch_2_controller = &self.branch_2_controller; + + // Perform ! ReadableStreamDefaultControllerError(branch_1.[[controller]], r). + branch_1_controller.error(v); + // Perform ! ReadableStreamDefaultControllerError(branch_2.[[controller]], r). + branch_2_controller.error(v); + + // If canceled_1 is false or canceled_2 is false, resolve cancelPromise with undefined. + if !self.canceled_1.get() || !self.canceled_2.get() { + self.cancel_promise.resolve_native(&()); + } + } +} + +/// <https://streams.spec.whatwg.org/#readablestreamdefaultreader> +#[dom_struct] +pub struct ReadableStreamDefaultReader { + reflector_: Reflector, + + /// <https://streams.spec.whatwg.org/#readablestreamgenericreader-stream> + stream: MutNullableDom<ReadableStream>, + + #[ignore_malloc_size_of = "no VecDeque support"] + read_requests: DomRefCell<VecDeque<ReadRequest>>, + + /// <https://streams.spec.whatwg.org/#readablestreamgenericreader-closedpromise> + #[ignore_malloc_size_of = "Rc is hard"] + closed_promise: DomRefCell<Rc<Promise>>, +} + +impl ReadableStreamDefaultReader { + /// <https://streams.spec.whatwg.org/#default-reader-constructor> + #[allow(non_snake_case)] + pub fn Constructor( + global: &GlobalScope, + proto: Option<SafeHandleObject>, + can_gc: CanGc, + stream: &ReadableStream, + ) -> Fallible<DomRoot<Self>> { + let reader = Self::new_with_proto(global, proto, can_gc); + + // Perform ? SetUpReadableStreamDefaultReader(this, stream). + Self::set_up(&reader, stream, global, can_gc)?; + + Ok(reader) + } + + fn new_with_proto( + global: &GlobalScope, + proto: Option<SafeHandleObject>, + can_gc: CanGc, + ) -> DomRoot<ReadableStreamDefaultReader> { + reflect_dom_object_with_proto( + Box::new(ReadableStreamDefaultReader::new_inherited(global, can_gc)), + global, + proto, + can_gc, + ) + } + + pub fn new_inherited(global: &GlobalScope, can_gc: CanGc) -> ReadableStreamDefaultReader { + ReadableStreamDefaultReader { + reflector_: Reflector::new(), + stream: MutNullableDom::new(None), + read_requests: DomRefCell::new(Default::default()), + closed_promise: DomRefCell::new(Promise::new(global, can_gc)), + } + } + + /// <https://streams.spec.whatwg.org/#set-up-readable-stream-default-reader> + pub fn set_up( + &self, + stream: &ReadableStream, + global: &GlobalScope, + can_gc: CanGc, + ) -> Fallible<()> { + // If ! IsReadableStreamLocked(stream) is true, throw a TypeError exception. + if stream.is_locked() { + return Err(Error::Type("stream is locked".to_owned())); + } + // Perform ! ReadableStreamReaderGenericInitialize(reader, stream). + + self.generic_initialize(global, stream, can_gc)?; + + // Set reader.[[readRequests]] to a new empty list. + self.read_requests.borrow_mut().clear(); + + Ok(()) + } + + /// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-initialize> + pub fn generic_initialize( + &self, + global: &GlobalScope, + stream: &ReadableStream, + can_gc: CanGc, + ) -> Fallible<()> { + // Set reader.[[stream]] to stream. + self.stream.set(Some(stream)); + + // Set stream.[[reader]] to reader. + stream.set_reader(Some(self)); + + if stream.is_readable() { + // If stream.[[state]] is "readable + // Set reader.[[closedPromise]] to a new promise. + *self.closed_promise.borrow_mut() = Promise::new(global, can_gc); + } else if stream.is_closed() { + // Otherwise, if stream.[[state]] is "closed", + // Set reader.[[closedPromise]] to a promise resolved with undefined. + let cx = GlobalScope::get_cx(); + rooted!(in(*cx) let mut rval = UndefinedValue()); + *self.closed_promise.borrow_mut() = Promise::new_resolved(global, cx, rval.handle())?; + } else { + // Assert: stream.[[state]] is "errored" + assert!(stream.is_errored()); + + // Set reader.[[closedPromise]] to a promise rejected with stream.[[storedError]]. + let cx = GlobalScope::get_cx(); + rooted!(in(*cx) let mut error = UndefinedValue()); + stream.get_stored_error(error.handle_mut()); + *self.closed_promise.borrow_mut() = Promise::new_rejected(global, cx, error.handle())?; + + // Set reader.[[closedPromise]].[[PromiseIsHandled]] to true + self.closed_promise.borrow().set_promise_is_handled(); + } + + Ok(()) + } + + /// <https://streams.spec.whatwg.org/#readable-stream-close> + #[allow(crown::unrooted_must_root)] + pub fn close(&self) { + // Resolve reader.[[closedPromise]] with undefined. + self.closed_promise.borrow().resolve_native(&()); + // If reader implements ReadableStreamDefaultReader, + // Let readRequests be reader.[[readRequests]]. + let mut read_requests = self.take_read_requests(); + // Set reader.[[readRequests]] to an empty list. + // For each readRequest of readRequests, + for request in read_requests.drain(0..) { + // Perform readRequest’s close steps. + request.close_steps(); + } + } + + /// <https://streams.spec.whatwg.org/#readable-stream-add-read-request> + pub fn add_read_request(&self, read_request: &ReadRequest) { + self.read_requests + .borrow_mut() + .push_back(read_request.clone()); + } + + /// <https://streams.spec.whatwg.org/#readable-stream-get-num-read-requests> + pub fn get_num_read_requests(&self) -> usize { + self.read_requests.borrow().len() + } + + /// <https://streams.spec.whatwg.org/#readable-stream-error> + pub fn error(&self, e: SafeHandleValue) { + // Reject reader.[[closedPromise]] with e. + self.closed_promise.borrow().reject_native(&e); + + // Set reader.[[closedPromise]].[[PromiseIsHandled]] to true. + self.closed_promise.borrow().set_promise_is_handled(); + + // Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e). + self.error_read_requests(e); + } + + /// The removal steps of <https://streams.spec.whatwg.org/#readable-stream-fulfill-read-request> + #[allow(crown::unrooted_must_root)] + pub fn remove_read_request(&self) -> ReadRequest { + self.read_requests + .borrow_mut() + .pop_front() + .expect("Reader must have read request when remove is called into.") + } + + /// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-release> + #[allow(unsafe_code)] + pub fn generic_release(&self) { + // Let stream be reader.[[stream]]. + + // Assert: stream is not undefined. + assert!(self.stream.get().is_some()); + + if let Some(stream) = self.stream.get() { + // Assert: stream.[[reader]] is reader. + assert!(stream.has_default_reader()); + + if stream.is_readable() { + // If stream.[[state]] is "readable", reject reader.[[closedPromise]] with a TypeError exception. + self.closed_promise + .borrow() + .reject_error(Error::Type("stream state is not readable".to_owned())); + } else { + // Otherwise, set reader.[[closedPromise]] to a promise rejected with a TypeError exception. + let cx = GlobalScope::get_cx(); + rooted!(in(*cx) let mut error = UndefinedValue()); + unsafe { + Error::Type("Cannot release lock due to stream state.".to_owned()).to_jsval( + *cx, + &self.global(), + error.handle_mut(), + ) + }; + + *self.closed_promise.borrow_mut() = + Promise::new_rejected(&self.global(), cx, error.handle()).unwrap(); + } + // Set reader.[[closedPromise]].[[PromiseIsHandled]] to true. + self.closed_promise.borrow().set_promise_is_handled(); + + // Perform ! stream.[[controller]].[[ReleaseSteps]](). + stream.perform_release_steps(); + + // Set stream.[[reader]] to undefined. + stream.set_reader(None); + // Set reader.[[stream]] to undefined. + self.stream.set(None); + } + } + + /// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreaderrelease> + #[allow(unsafe_code)] + pub fn release(&self) { + // Perform ! ReadableStreamReaderGenericRelease(reader). + self.generic_release(); + // Let e be a new TypeError exception. + let cx = GlobalScope::get_cx(); + rooted!(in(*cx) let mut error = UndefinedValue()); + unsafe { + Error::Type("Reader is released".to_owned()).to_jsval( + *cx, + &self.global(), + error.handle_mut(), + ) + }; + + // Perform ! ReadableStreamDefaultReaderErrorReadRequests(reader, e). + self.error_read_requests(error.handle()); + } + + #[allow(crown::unrooted_must_root)] + fn take_read_requests(&self) -> VecDeque<ReadRequest> { + mem::take(&mut *self.read_requests.borrow_mut()) + } + + /// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-cancel> + fn generic_cancel(&self, reason: SafeHandleValue, can_gc: CanGc) -> Rc<Promise> { + // Let stream be reader.[[stream]]. + let stream = self.stream.get(); + + // Assert: stream is not undefined. + let stream = + stream.expect("Reader should have a stream when generic cancel is called into."); + + // Return ! ReadableStreamCancel(stream, reason). + stream.cancel(reason, can_gc) + } + + /// <https://streams.spec.whatwg.org/#abstract-opdef-readablestreamdefaultreadererrorreadrequests> + #[allow(crown::unrooted_must_root)] + fn error_read_requests(&self, rval: SafeHandleValue) { + // step 1 + let mut read_requests = self.take_read_requests(); + + // step 2 & 3 + for request in read_requests.drain(0..) { + request.error_steps(rval); + } + } + + /// <https://streams.spec.whatwg.org/#readable-stream-default-reader-read> + pub fn read(&self, read_request: &ReadRequest, can_gc: CanGc) { + // Let stream be reader.[[stream]]. + + // Assert: stream is not undefined. + assert!(self.stream.get().is_some()); + + let stream = self.stream.get().unwrap(); + + // Set stream.[[disturbed]] to true. + stream.set_is_disturbed(true); + // If stream.[[state]] is "closed", perform readRequest’s close steps. + if stream.is_closed() { + read_request.close_steps(); + } else if stream.is_errored() { + // Otherwise, if stream.[[state]] is "errored", + // perform readRequest’s error steps given stream.[[storedError]]. + let cx = GlobalScope::get_cx(); + rooted!(in(*cx) let mut error = UndefinedValue()); + stream.get_stored_error(error.handle_mut()); + read_request.error_steps(error.handle()); + } else { + // Otherwise + // Assert: stream.[[state]] is "readable". + assert!(stream.is_readable()); + // Perform ! stream.[[controller]].[[PullSteps]](readRequest). + stream.perform_pull_steps(read_request, can_gc); + } + } + + /// <https://streams.spec.whatwg.org/#ref-for-readablestreamgenericreader-closedpromise%E2%91%A1> + pub fn append_native_handler_to_closed_promise( + &self, + branch_1: &ReadableStream, + branch_2: &ReadableStream, + canceled_1: Rc<Cell<bool>>, + canceled_2: Rc<Cell<bool>>, + cancel_promise: Rc<Promise>, + can_gc: CanGc, + ) { + let branch_1_controller = branch_1.get_default_controller(); + + let branch_2_controller = branch_2.get_default_controller(); + + let global = self.global(); + let handler = PromiseNativeHandler::new( + &global, + None, + Some(Box::new(ClosedPromiseRejectionHandler { + branch_1_controller: Dom::from_ref(&branch_1_controller), + branch_2_controller: Dom::from_ref(&branch_2_controller), + canceled_1, + canceled_2, + cancel_promise, + })), + ); + + let realm = enter_realm(&*global); + let comp = InRealm::Entered(&realm); + + self.closed_promise + .borrow() + .append_native_handler(&handler, comp, can_gc); + } +} + +impl ReadableStreamDefaultReaderMethods<crate::DomTypeHolder> for ReadableStreamDefaultReader { + /// <https://streams.spec.whatwg.org/#default-reader-constructor> + fn Constructor( + global: &GlobalScope, + proto: Option<SafeHandleObject>, + can_gc: CanGc, + stream: &ReadableStream, + ) -> Fallible<DomRoot<Self>> { + ReadableStreamDefaultReader::Constructor(global, proto, can_gc, stream) + } + + /// <https://streams.spec.whatwg.org/#default-reader-read> + #[allow(unsafe_code)] + #[allow(crown::unrooted_must_root)] + fn Read(&self, can_gc: CanGc) -> Rc<Promise> { + // If this.[[stream]] is undefined, return a promise rejected with a TypeError exception. + if self.stream.get().is_none() { + let cx = GlobalScope::get_cx(); + rooted!(in(*cx) let mut error = UndefinedValue()); + unsafe { + Error::Type("stream is undefined".to_owned()).to_jsval( + *cx, + &self.global(), + error.handle_mut(), + ) + }; + return Promise::new_rejected(&self.global(), cx, error.handle()).unwrap(); + } + // Let promise be a new promise. + let promise = Promise::new(&self.reflector_.global(), can_gc); + + // Let readRequest be a new read request with the following items: + // chunk steps, given chunk + // Resolve promise with «[ "value" → chunk, "done" → false ]». + // + // close steps + // Resolve promise with «[ "value" → undefined, "done" → true ]». + // + // error steps, given e + // Reject promise with e. + + // Rooting(unrooted_must_root): the read request contains only a promise, + // which does not need to be rooted, + // as it is safely managed natively via an Rc. + let read_request = ReadRequest::Read(promise.clone()); + + // Perform ! ReadableStreamDefaultReaderRead(this, readRequest). + self.read(&read_request, can_gc); + + // Return promise. + promise + } + + /// <https://streams.spec.whatwg.org/#default-reader-release-lock> + fn ReleaseLock(&self) { + if self.stream.get().is_some() { + // step 2 - Perform ! ReadableStreamDefaultReaderRelease(this). + self.release(); + } + // step 1 - If this.[[stream]] is undefined, return. + } + + /// <https://streams.spec.whatwg.org/#generic-reader-closed> + fn Closed(&self) -> Rc<Promise> { + self.closed_promise.borrow().clone() + } + + /// <https://streams.spec.whatwg.org/#generic-reader-cancel> + fn Cancel(&self, _cx: SafeJSContext, reason: SafeHandleValue, can_gc: CanGc) -> Rc<Promise> { + if self.stream.get().is_none() { + // If this.[[stream]] is undefined, + // return a promise rejected with a TypeError exception. + let promise = Promise::new(&self.reflector_.global(), can_gc); + promise.reject_error(Error::Type("stream is undefined".to_owned())); + promise + } else { + // Return ! ReadableStreamReaderGenericCancel(this, reason). + self.generic_cancel(reason, can_gc) + } + } +} |