diff --git a/js/src/builtin/streams/WritableStreamDefaultWriter.cpp b/js/src/builtin/streams/WritableStreamDefaultWriter.cpp index 17216b9c2593..cea6b3215066 100644 --- a/js/src/builtin/streams/WritableStreamDefaultWriter.cpp +++ b/js/src/builtin/streams/WritableStreamDefaultWriter.cpp @@ -18,7 +18,7 @@ #include "builtin/streams/MiscellaneousOperations.h" // js::ReturnPromiseRejectedWithPendingError #include "builtin/streams/WritableStream.h" // js::WritableStream #include "builtin/streams/WritableStreamOperations.h" // js::WritableStreamCloseQueuedOrInFlight -#include "builtin/streams/WritableStreamWriterOperations.h" // js::WritableStreamDefaultWriter{GetDesiredSize,Release,Write} +#include "builtin/streams/WritableStreamWriterOperations.h" // js::WritableStreamDefaultWriter{Abort,GetDesiredSize,Release,Write} #include "js/CallArgs.h" // JS::CallArgs{,FromVp} #include "js/Class.h" // js::ClassSpec, JS_NULL_CLASS_OPS #include "js/PropertySpec.h" // JS{Function,Property}Spec, JS_{FS,PS}_END, JS_{FN,PSG} @@ -154,6 +154,42 @@ static MOZ_MUST_USE bool WritableStream_ready(JSContext* cx, unsigned argc, return true; } +/** + * Streams spec, 4.5.4.4. abort(reason) + */ +static MOZ_MUST_USE bool WritableStream_abort(JSContext* cx, unsigned argc, + Value* vp) { + CallArgs args = CallArgsFromVp(argc, vp); + + // Step 1: If ! IsWritableStreamDefaultWriter(this) is false, return a promise + // rejected with a TypeError exception. + Rooted unwrappedWriter( + cx, + UnwrapAndTypeCheckThis(cx, args, "abort")); + if (!unwrappedWriter) { + return ReturnPromiseRejectedWithPendingError(cx, args); + } + + // Step 2: If this.[[ownerWritableStream]] is undefined, return a promise + // rejected with a TypeError exception. + if (!unwrappedWriter->hasStream()) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_WRITABLESTREAMWRITER_NOT_OWNED, "abort"); + return ReturnPromiseRejectedWithPendingError(cx, args); + } + + // Step 3: Return ! WritableStreamDefaultWriterAbort(this, reason). + JSObject* promise = + WritableStreamDefaultWriterAbort(cx, unwrappedWriter, args.get(0)); + if (!promise) { + return false; + } + cx->check(promise); + + args.rval().setObject(*promise); + return true; +} + /** * Streams spec, 4.5.4.5. close() */ @@ -289,6 +325,7 @@ static const JSPropertySpec WritableStreamDefaultWriter_properties[] = { JS_PSG("ready", WritableStream_ready, 0), JS_PS_END}; static const JSFunctionSpec WritableStreamDefaultWriter_methods[] = { + JS_FN("abort", WritableStream_abort, 1, 0), JS_FN("close", WritableStream_close, 0, 0), JS_FN("releaseLock", WritableStream_releaseLock, 0, 0), JS_FN("write", WritableStream_write, 1, 0), JS_FS_END}; diff --git a/js/src/builtin/streams/WritableStreamWriterOperations.cpp b/js/src/builtin/streams/WritableStreamWriterOperations.cpp index 30fbf3107dbb..ae4f287c8713 100644 --- a/js/src/builtin/streams/WritableStreamWriterOperations.cpp +++ b/js/src/builtin/streams/WritableStreamWriterOperations.cpp @@ -20,7 +20,7 @@ #include "builtin/streams/WritableStreamDefaultController.h" // js::WritableStream::controller #include "builtin/streams/WritableStreamDefaultControllerOperations.h" // js::WritableStreamDefaultController{Close,GetDesiredSize} #include "builtin/streams/WritableStreamDefaultWriter.h" // js::WritableStreamDefaultWriter -#include "builtin/streams/WritableStreamOperations.h" // js::WritableStreamCloseQueuedOrInFlight +#include "builtin/streams/WritableStreamOperations.h" // js::WritableStream{Abort,CloseQueuedOrInFlight} #include "js/Value.h" // JS::Value, JS::{Int32,Null}Value #include "vm/Compartment.h" // JS::Compartment #include "vm/JSContext.h" // JSContext @@ -44,6 +44,28 @@ using js::PromiseObject; /*** 4.6. Writable stream writer abstract operations ************************/ +/** + * Streams spec, 4.6.2. + * WritableStreamDefaultWriterAbort ( writer, reason ) + */ +JSObject* js::WritableStreamDefaultWriterAbort( + JSContext* cx, Handle unwrappedWriter, + Handle reason) { + cx->check(reason); + + // Step 1: Let stream be writer.[[ownerWritableStream]]. + // Step 2: Assert: stream is not undefined. + MOZ_ASSERT(unwrappedWriter->hasStream()); + Rooted unwrappedStream( + cx, UnwrapStreamFromWriter(cx, unwrappedWriter)); + if (!unwrappedStream) { + return nullptr; + } + + // Step 3: Return ! WritableStreamAbort(stream, reason). + return WritableStreamAbort(cx, unwrappedStream, reason); +} + /** * Streams spec, 4.6.3. * WritableStreamDefaultWriterClose ( writer ) diff --git a/js/src/builtin/streams/WritableStreamWriterOperations.h b/js/src/builtin/streams/WritableStreamWriterOperations.h index febbca13bc87..6446d4fc32f0 100644 --- a/js/src/builtin/streams/WritableStreamWriterOperations.h +++ b/js/src/builtin/streams/WritableStreamWriterOperations.h @@ -21,6 +21,10 @@ namespace js { class WritableStreamDefaultWriter; +extern JSObject* WritableStreamDefaultWriterAbort( + JSContext* cx, JS::Handle unwrappedWriter, + JS::Handle reason); + extern JSObject* WritableStreamDefaultWriterClose( JSContext* cx, JS::Handle unwrappedWriter);