mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 17:10:23 +00:00
LibWeb: Reorder step to get chunk size after checking for aborted stream
This fixes a crash seen on: http://wpt.live/streams/writable-streams/aborting.any.html I believe this is a spec bug, which has been reported to the Streams spec.
This commit is contained in:
parent
3594cdf948
commit
d31014d135
Notes:
github-actions[bot]
2024-11-09 13:10:46 +00:00
Author: https://github.com/shannonbooth Commit: https://github.com/LadybirdBrowser/ladybird/commit/d31014d1353 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2249
4 changed files with 1582 additions and 1 deletions
|
@ -0,0 +1,73 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: Error
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 62 tests
|
||||||
|
|
||||||
|
45 Pass
|
||||||
|
17 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Aborting a WritableStream before it starts should cause the writer's unsettled ready promise to reject
|
||||||
|
Pass Aborting a WritableStream should cause the writer's fulfilled ready promise to reset to a rejected one
|
||||||
|
Pass abort() on a released writer rejects
|
||||||
|
Pass Aborting a WritableStream immediately prevents future writes
|
||||||
|
Pass Aborting a WritableStream prevents further writes after any that are in progress
|
||||||
|
Pass Fulfillment value of writer.abort() call must be undefined even if the underlying sink returns a non-undefined value
|
||||||
|
Pass WritableStream if sink's abort throws, the promise returned by writer.abort() rejects
|
||||||
|
Pass WritableStream if sink's abort throws, the promise returned by multiple writer.abort()s is the same and rejects
|
||||||
|
Pass WritableStream if sink's abort throws, the promise returned by ws.abort() rejects
|
||||||
|
Pass WritableStream if sink's abort throws, for an abort performed during a write, the promise returned by ws.abort() rejects
|
||||||
|
Pass Aborting a WritableStream passes through the given reason
|
||||||
|
Pass Aborting a WritableStream puts it in an errored state with the error passed to abort()
|
||||||
|
Pass Aborting a WritableStream causes any outstanding write() promises to be rejected with the reason supplied
|
||||||
|
Pass Closing but then immediately aborting a WritableStream causes the stream to error
|
||||||
|
Pass Closing a WritableStream and aborting it while it closes causes the stream to ignore the abort attempt
|
||||||
|
Pass Aborting a WritableStream after it is closed is a no-op
|
||||||
|
Pass WritableStream should NOT call underlying sink's close if no abort is supplied (historical)
|
||||||
|
Pass returning a thenable from abort() should work
|
||||||
|
Pass .closed should not resolve before fulfilled write()
|
||||||
|
Pass .closed should not resolve before rejected write(); write() error should not overwrite abort() error
|
||||||
|
Pass writes should be satisfied in order when aborting
|
||||||
|
Pass writes should be satisfied in order after rejected write when aborting
|
||||||
|
Pass close() should reject with abort reason why abort() is first error
|
||||||
|
Pass underlying abort() should not be called until underlying write() completes
|
||||||
|
Pass underlying abort() should not be called if underlying close() has started
|
||||||
|
Pass if underlying close() has started and then rejects, the abort() and close() promises should reject with the underlying close rejection reason
|
||||||
|
Pass an abort() that happens during a write() should trigger the underlying abort() even with a close() queued
|
||||||
|
Pass if a writer is created for a stream with a pending abort, its ready should be rejected with the abort error
|
||||||
|
Pass writer close() promise should resolve before abort() promise
|
||||||
|
Fail writer.ready should reject on controller error without waiting for underlying write
|
||||||
|
Pass writer.abort() while there is an in-flight write, and then finish the write with rejection
|
||||||
|
Fail writer.abort(), controller.error() while there is an in-flight write, and then finish the write
|
||||||
|
Fail writer.abort(), controller.error() while there is an in-flight close, and then finish the close
|
||||||
|
Fail controller.error(), writer.abort() while there is an in-flight write, and then finish the write
|
||||||
|
Fail controller.error(), writer.abort() while there is an in-flight close, and then finish the close
|
||||||
|
Pass releaseLock() while aborting should reject the original closed promise
|
||||||
|
Pass releaseLock() during delayed async abort() should reject the writer.closed promise
|
||||||
|
Pass sink abort() should not be called until sink start() is done
|
||||||
|
Fail if start attempts to error the controller after abort() has been called, then it should lose undefined is not a function (evaluated from 'controller.error')
|
||||||
|
Pass stream abort() promise should still resolve if sink start() rejects
|
||||||
|
Pass writer abort() during sink start() should replace the writer.ready promise synchronously
|
||||||
|
Pass promises returned from other writer methods should be rejected when writer abort() happens during sink start()
|
||||||
|
Fail abort() should succeed despite rejection from write
|
||||||
|
Fail abort() should be rejected with the rejection returned from close()
|
||||||
|
Pass a rejecting sink.write() should not prevent sink.abort() from being called
|
||||||
|
Pass when start errors after stream abort(), underlying sink abort() should be called anyway
|
||||||
|
Pass when calling abort() twice on the same stream, both should give the same promise that fulfills with undefined
|
||||||
|
Pass when calling abort() twice on the same stream, but sequentially so so there's no pending abort the second time, both should fulfill with undefined
|
||||||
|
Fail calling abort() on an errored stream should fulfill with undefined undefined is not a function (evaluated from 'c.error')
|
||||||
|
Fail sink abort() should not be called if stream was erroring due to controller.error() before abort() was called
|
||||||
|
Pass sink abort() should not be called if stream was erroring due to bad strategy before abort() was called
|
||||||
|
Pass abort with no arguments should set the stored error to undefined
|
||||||
|
Pass abort with an undefined argument should set the stored error to undefined
|
||||||
|
Pass abort with a string argument should set the stored error to that argument
|
||||||
|
Pass abort on a locked stream should reject
|
||||||
|
Fail WritableStreamDefaultController.signal
|
||||||
|
Fail the abort signal is signalled synchronously - write
|
||||||
|
Fail the abort signal is signalled synchronously - close
|
||||||
|
Fail the abort signal is not signalled on error
|
||||||
|
Fail the abort signal is not signalled on write failure
|
||||||
|
Fail the abort signal is not signalled on close failure
|
||||||
|
Fail recursive abort() call
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
self.GLOBAL = {
|
||||||
|
isWindow: function() { return true; },
|
||||||
|
isWorker: function() { return false; },
|
||||||
|
isShadowRealm: function() { return false; },
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../resources/test-utils.js"></script>
|
||||||
|
<script src="../resources/recording-streams.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<script src="../../streams/writable-streams/aborting.any.js"></script>
|
File diff suppressed because it is too large
Load diff
|
@ -4255,7 +4255,7 @@ JS::NonnullGCPtr<WebIDL::Promise> writable_stream_default_writer_write(WritableS
|
||||||
auto controller = stream->controller();
|
auto controller = stream->controller();
|
||||||
|
|
||||||
// 4. Let chunkSize be ! WritableStreamDefaultControllerGetChunkSize(controller, chunk).
|
// 4. Let chunkSize be ! WritableStreamDefaultControllerGetChunkSize(controller, chunk).
|
||||||
auto chunk_size = writable_stream_default_controller_get_chunk_size(*controller, chunk);
|
// NOTE: See FIXME below
|
||||||
|
|
||||||
// 5. If stream is not equal to writer.[[stream]], return a promise rejected with a TypeError exception.
|
// 5. If stream is not equal to writer.[[stream]], return a promise rejected with a TypeError exception.
|
||||||
if (stream.ptr() != writer.stream().ptr()) {
|
if (stream.ptr() != writer.stream().ptr()) {
|
||||||
|
@ -4280,6 +4280,11 @@ JS::NonnullGCPtr<WebIDL::Promise> writable_stream_default_writer_write(WritableS
|
||||||
if (state == WritableStream::State::Erroring)
|
if (state == WritableStream::State::Erroring)
|
||||||
return WebIDL::create_rejected_promise(realm, stream->stored_error());
|
return WebIDL::create_rejected_promise(realm, stream->stored_error());
|
||||||
|
|
||||||
|
// 4. Let chunkSize be ! WritableStreamDefaultControllerGetChunkSize(controller, chunk).
|
||||||
|
// FIXME: This is out of order due to a spec bug: https://github.com/whatwg/streams/issues/1331
|
||||||
|
// An abort clears the strategySizeAlgorithm, so we need to move this past the "erroring" check
|
||||||
|
auto chunk_size = writable_stream_default_controller_get_chunk_size(*controller, chunk);
|
||||||
|
|
||||||
// 10. Assert: state is "writable".
|
// 10. Assert: state is "writable".
|
||||||
VERIFY(state == WritableStream::State::Writable);
|
VERIFY(state == WritableStream::State::Writable);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue