/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* 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/. */
// Step 5. Let storedError be stream.[[storedError]].
JS::Rooted<JS::Value> storedError(aCx, mStoredError);
// Step 6. For each writeRequest of stream.[[writeRequests]]: for (const RefPtr<Promise>& writeRequest : mWriteRequests) { // Step 6.1. Reject writeRequest with storedError.
writeRequest->MaybeReject(storedError);
}
// Step 7. Set stream.[[writeRequests]] to an empty list.
mWriteRequests.Clear();
// Step 8. If stream.[[pendingAbortRequest]] is undefined, if (!mPendingAbortRequestPromise) { // Step 8.1. Perform ! // WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream).
RejectCloseAndClosedPromiseIfNeeded();
// Step 8.2. Return. return;
}
// Step 9. Let abortRequest be stream.[[pendingAbortRequest]].
RefPtr<Promise> abortPromise = mPendingAbortRequestPromise;
JS::Rooted<JS::Value> abortReason(aCx, mPendingAbortRequestReason); bool abortWasAlreadyErroring = mPendingAbortRequestWasAlreadyErroring;
// Step 10. Set stream.[[pendingAbortRequest]] to undefined.
SetPendingAbortRequest(nullptr, JS::UndefinedHandleValue, false);
// Step 11. If abortRequest’s was already erroring is true, if (abortWasAlreadyErroring) { // Step 11.1. Reject abortRequest’s promise with storedError.
abortPromise->MaybeReject(storedError);
// Step 2. Resolve stream.[[inFlightCloseRequest]] with undefined.
mInFlightCloseRequest->MaybeResolveWithUndefined();
// Step 3. Set stream.[[inFlightCloseRequest]] to undefined.
mInFlightCloseRequest = nullptr;
// Step 4. Let state be stream.[[state]]. // Step 5. Assert: stream.[[state]] is "writable" or "erroring".
MOZ_ASSERT(mState == WriterState::Writable ||
mState == WriterState::Erroring);
// Step 6. If state is "erroring", if (mState == WriterState::Erroring) { // Step 6.1. Set stream.[[storedError]] to undefined.
mStoredError.setUndefined();
// Step 6.2. If stream.[[pendingAbortRequest]] is not undefined, if (mPendingAbortRequestPromise) { // Step 6.2.1. Resolve stream.[[pendingAbortRequest]]'s promise with // undefined.
mPendingAbortRequestPromise->MaybeResolveWithUndefined();
// Step 6.2.2. Set stream.[[pendingAbortRequest]] to undefined.
SetPendingAbortRequest(nullptr, JS::UndefinedHandleValue, false);
}
}
// Step 7. Set stream.[[state]] to "closed".
mState = WriterState::Closed;
// Step 8. Let writer be stream.[[writer]]. // Step 9. If writer is not undefined, resolve writer.[[closedPromise]] with // undefined. if (mWriter) {
mWriter->ClosedPromise()->MaybeResolveWithUndefined();
}
// Step 10. Assert: stream.[[pendingAbortRequest]] is undefined.
MOZ_ASSERT(!mPendingAbortRequestPromise); // Assert: stream.[[storedError]] is undefined.
MOZ_ASSERT(mStoredError.isUndefined());
}
// Step 2. Reject stream.[[inFlightCloseRequest]] with error.
mInFlightCloseRequest->MaybeReject(aError);
// Step 3. Set stream.[[inFlightCloseRequest]] to undefined.
mInFlightCloseRequest = nullptr;
// Step 4. Assert: stream.[[state]] is "writable" or "erroring".
MOZ_ASSERT(mState == WriterState::Writable ||
mState == WriterState::Erroring);
// Step 5. If stream.[[pendingAbortRequest]] is not undefined, if (mPendingAbortRequestPromise) { // Step 5.1. Reject stream.[[pendingAbortRequest]]'s promise with error.
mPendingAbortRequestPromise->MaybeReject(aError);
// Step 5.2. Set stream.[[pendingAbortRequest]] to undefined.
SetPendingAbortRequest(nullptr, JS::UndefinedHandleValue, false);
}
JS::Rooted<JS::Value> storedError(RootingCx(), mStoredError); // Step 2. If stream.[[closeRequest]] is not undefined, if (mCloseRequest) { // Step 2.1. Assert: stream.[[inFlightCloseRequest]] is undefined.
MOZ_ASSERT(!mInFlightCloseRequest);
// Step 2.2. Reject stream.[[closeRequest]] with stream.[[storedError]].
mCloseRequest->MaybeReject(storedError);
// Step 2.3. Set stream.[[closeRequest]] to undefined.
mCloseRequest = nullptr;
}
// Step 3. Let writer be stream.[[writer]].
RefPtr<WritableStreamDefaultWriter> writer = mWriter;
// Step 4. If writer is not undefined, if (writer) { // Step 4.1. Reject writer.[[closedPromise]] with stream.[[storedError]].
RefPtr<Promise> closedPromise = writer->ClosedPromise();
closedPromise->MaybeReject(storedError);
// Step 4.2. Set writer.[[closedPromise]].[[PromiseIsHandled]] to true.
closedPromise->SetSettledPromiseIsHandled();
}
}
// Step 2. Assert: stream.[[state]] is "writable".
MOZ_ASSERT(mState == WriterState::Writable);
// Step 3. Let controller be stream.[[controller]].
RefPtr<WritableStreamDefaultController> controller = mController; // Step 4. Assert: controller is not undefined.
MOZ_ASSERT(controller);
// Step 5. Set stream.[[state]] to "erroring".
mState = WriterState::Erroring;
// Step 6. Set stream.[[storedError]] to reason.
mStoredError = aReason;
// Step 7. Let writer be stream.[[writer]].
RefPtr<WritableStreamDefaultWriter> writer = mWriter; // Step 8. If writer is not undefined, perform ! // WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason). if (writer) {
WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, aReason);
}
// Step 9. If ! WritableStreamHasOperationMarkedInFlight(stream) is false // and controller.[[started]] is true, // perform !WritableStreamFinishErroring(stream). if (!HasOperationMarkedInFlight() && controller->Started()) {
FinishErroring(aCx, aRv);
}
}
// Step 3. Let writer be stream.[[writer]].
RefPtr<WritableStreamDefaultWriter> writer = mWriter;
// Step 4. If writer is not undefined and backpressure is not // stream.[[backpressure]], if (writer && aBackpressure != mBackpressure) { // Step 4.1. If backpressure is true, set writer.[[readyPromise]] to a new // promise. if (aBackpressure) {
RefPtr<Promise> promise =
Promise::CreateInfallible(writer->GetParentObject());
writer->SetReadyPromise(promise);
} else { // Step 4.2. Otherwise, // Step 4.2.1. Assert: backpressure is false. // Step 4.2.2. Resolve writer.[[readyPromise]] with undefined.
writer->ReadyPromise()->MaybeResolveWithUndefined();
}
}
// Step 5. Set stream.[[backpressure]] to backpressure.
mBackpressure = aBackpressure;
}
// https://streams.spec.whatwg.org/#ws-constructor
already_AddRefed<WritableStream> WritableStream::Constructor( const GlobalObject& aGlobal, const Optional<JS::Handle<JSObject*>>& aUnderlyingSink, const QueuingStrategy& aStrategy, ErrorResult& aRv) { // Step 1. If underlyingSink is missing, set it to null.
JS::Rooted<JSObject*> underlyingSinkObj(
aGlobal.Context(),
aUnderlyingSink.WasPassed() ? aUnderlyingSink.Value() : nullptr);
// Step 2. Let underlyingSinkDict be underlyingSink, converted to // an IDL value of type UnderlyingSink.
RootedDictionary<UnderlyingSink> underlyingSinkDict(aGlobal.Context()); if (underlyingSinkObj) {
JS::Rooted<JS::Value> objValue(aGlobal.Context(),
JS::ObjectValue(*underlyingSinkObj));
dom::BindingCallContext callCx(aGlobal.Context(), "WritableStream.constructor");
aRv.MightThrowJSException(); if (!underlyingSinkDict.Init(callCx, objValue)) {
aRv.StealExceptionFromJSContext(aGlobal.Context()); return nullptr;
}
}
// Step 3. If underlyingSinkDict["type"] exists, throw a RangeError exception. if (!underlyingSinkDict.mType.isUndefined()) {
aRv.ThrowRangeError("Implementation preserved member 'type'"); return nullptr;
}
// Step 5. Let sizeAlgorithm be ! ExtractSizeAlgorithm(strategy). // // Implementation Note: The specification demands that if the size doesn't // exist, we instead would provide an algorithm that returns 1. Instead, we // will teach callers that a missing callback should simply return 1, rather // than gin up a fake callback here. // // This decision may need to be revisited if the default action ever diverges // within the specification.
RefPtr<QueuingStrategySize> sizeAlgorithm =
aStrategy.mSize.WasPassed() ? &aStrategy.mSize.Value() : nullptr;
// Step 6. Let highWaterMark be ? ExtractHighWaterMark(strategy, 1). double highWaterMark = ExtractHighWaterMark(aStrategy, 1, aRv); if (aRv.Failed()) { return nullptr;
}
namespace streams_abstract { // https://streams.spec.whatwg.org/#writable-stream-abort
already_AddRefed<Promise> WritableStreamAbort(JSContext* aCx,
WritableStream* aStream,
JS::Handle<JS::Value> aReason,
ErrorResult& aRv) { // Step 1. If stream.[[state]] is "closed" or "errored", return a promise // resolved with undefined. if (aStream->State() == WritableStream::WriterState::Closed ||
aStream->State() == WritableStream::WriterState::Errored) {
RefPtr<Promise> promise =
Promise::CreateInfallible(aStream->GetParentObject());
promise->MaybeResolveWithUndefined(); return promise.forget();
}
// Step 2. Signal abort on stream.[[controller]].[[signal]] with reason.
RefPtr<WritableStreamDefaultController> controller = aStream->Controller();
controller->Signal()->SignalAbort(aReason);
// Step 3. Let state be stream.[[state]].
WritableStream::WriterState state = aStream->State();
// Step 4. If state is "closed" or "errored", return a promise resolved with // undefined. Note: We re-check the state because signaling abort runs author // code and that might have changed the state. if (aStream->State() == WritableStream::WriterState::Closed ||
aStream->State() == WritableStream::WriterState::Errored) {
RefPtr<Promise> promise =
Promise::CreateInfallible(aStream->GetParentObject());
promise->MaybeResolveWithUndefined(); return promise.forget();
}
// Step 5. If stream.[[pendingAbortRequest]] is not undefined, return // stream.[[pendingAbortRequest]]'s promise. if (aStream->GetPendingAbortRequestPromise()) {
RefPtr<Promise> promise = aStream->GetPendingAbortRequestPromise(); return promise.forget();
}
// Step 6. Assert: state is "writable" or "erroring".
MOZ_ASSERT(state == WritableStream::WriterState::Writable ||
state == WritableStream::WriterState::Erroring);
// Step 7. Let wasAlreadyErroring be false. bool wasAlreadyErroring = false;
// Step 8. If state is "erroring",
JS::Rooted<JS::Value> reason(aCx, aReason); if (state == WritableStream::WriterState::Erroring) { // Step 8.1. Set wasAlreadyErroring to true.
wasAlreadyErroring = true; // Step 8.2. Set reason to undefined.
reason.setUndefined();
}
// Step 9. Let promise be a new promise.
RefPtr<Promise> promise =
Promise::CreateInfallible(aStream->GetParentObject());
// Step 10. Set stream.[[pendingAbortRequest]] to a new pending abort request // whose promise is promise, reason is reason, and was already erroring is // wasAlreadyErroring.
aStream->SetPendingAbortRequest(promise, reason, wasAlreadyErroring);
// Step 11. If wasAlreadyErroring is false, perform ! // WritableStreamStartErroring(stream, reason). if (!wasAlreadyErroring) {
aStream->StartErroring(aCx, reason, aRv); if (aRv.Failed()) { return nullptr;
}
}
namespace streams_abstract { // https://streams.spec.whatwg.org/#writable-stream-close
already_AddRefed<Promise> WritableStreamClose(JSContext* aCx,
WritableStream* aStream,
ErrorResult& aRv) { // Step 1. Let state be stream.[[state]].
WritableStream::WriterState state = aStream->State();
// Step 2. If state is "closed" or "errored", return a promise rejected with a // TypeError exception. if (state == WritableStream::WriterState::Closed ||
state == WritableStream::WriterState::Errored) { return Promise::CreateRejectedWithTypeError(
aStream->GetParentObject(), "Can not close stream after closing or error"_ns, aRv);
}
// Step 3. Assert: state is "writable" or "erroring".
MOZ_ASSERT(state == WritableStream::WriterState::Writable ||
state == WritableStream::WriterState::Erroring);
// Step 4. Assert: ! WritableStreamCloseQueuedOrInFlight(stream) is false.
MOZ_ASSERT(!aStream->CloseQueuedOrInFlight());
// Step 5. Let promise be a new promise.
RefPtr<Promise> promise =
Promise::CreateInfallible(aStream->GetParentObject());
// Step 6. Set stream.[[closeRequest]] to promise.
aStream->SetCloseRequest(promise);
// Step 7. Let writer be stream.[[writer]].
RefPtr<WritableStreamDefaultWriter> writer = aStream->GetWriter();
// Step 8. If writer is not undefined, and stream.[[backpressure]] is true, // and state is "writable", resolve writer.[[readyPromise]] with undefined. if (writer && aStream->Backpressure() &&
state == WritableStream::WriterState::Writable) {
writer->ReadyPromise()->MaybeResolveWithUndefined();
}
// https://streams.spec.whatwg.org/#ws-close
already_AddRefed<Promise> WritableStream::Close(JSContext* aCx,
ErrorResult& aRv) { // Step 1. If ! IsWritableStreamLocked(this) is true, return a promise // rejected with a TypeError exception. if (Locked()) { return Promise::CreateRejectedWithTypeError(
GetParentObject(), "Can not close locked stream"_ns, aRv);
}
// Step 2. If ! WritableStreamCloseQueuedOrInFlight(this) is true, return a // promise rejected with a TypeError exception. if (CloseQueuedOrInFlight()) { return Promise::CreateRejectedWithTypeError(
GetParentObject(), "Stream is already closing"_ns, aRv);
}
namespace streams_abstract { // https://streams.spec.whatwg.org/#acquire-writable-stream-default-writer
already_AddRefed<WritableStreamDefaultWriter>
AcquireWritableStreamDefaultWriter(WritableStream* aStream, ErrorResult& aRv) { // Step 1. Let writer be a new WritableStreamDefaultWriter.
RefPtr<WritableStreamDefaultWriter> writer = new WritableStreamDefaultWriter(aStream->GetParentObject());
// Step 2: Let stream be a new WritableStream. // Step 3: Perform ! InitializeWritableStream(stream).
RefPtr<WritableStream> stream = new WritableStream(
aGlobal, WritableStream::HoldDropJSObjectsCaller::Implicit);
// Step 4: Let controller be a new WritableStreamDefaultController. auto controller =
MakeRefPtr<WritableStreamDefaultController>(aGlobal, *stream);
// https://streams.spec.whatwg.org/#writablestream-set-up // _BOUNDARY because `aAlgorithms->StartCallback` (called by // SetUpWritableStreamDefaultController below) should not be able to run script // in this case.
MOZ_CAN_RUN_SCRIPT_BOUNDARY void WritableStream::SetUpNative(
JSContext* aCx, UnderlyingSinkAlgorithmsWrapper& aAlgorithms,
Maybe<double> aHighWaterMark, QueuingStrategySize* aSizeAlgorithm,
ErrorResult& aRv) { // an optional number highWaterMark (default 1) double highWaterMark = aHighWaterMark.valueOr(1); // and if given, highWaterMark must be a non-negative, non-NaN number.
MOZ_ASSERT(IsNonNegativeNumber(highWaterMark));
// Step 1: Let startAlgorithm be an algorithm that returns undefined. // Step 2: Let closeAlgorithmWrapper be an algorithm that runs these steps: // Step 3: Let abortAlgorithmWrapper be an algorithm that runs these steps: // (Covered by UnderlyingSinkAlgorithmsWrapper)
// Step 4: If sizeAlgorithm was not given, then set it to an algorithm that // returns 1. (Callers will treat nullptr as such, see // WritableStream::Constructor for details)
// Step 5: Perform ! InitializeWritableStream(stream). // (Covered by the constructor)
// Step 6: Let controller be a new WritableStreamDefaultController. auto controller =
MakeRefPtr<WritableStreamDefaultController>(GetParentObject(), *this);
// https://streams.spec.whatwg.org/#writablestream-error // To error a WritableStream stream given a JavaScript value e, perform ! // WritableStreamDefaultControllerErrorIfNeeded(stream.[[controller]], e). void WritableStream::ErrorNative(JSContext* aCx, JS::Handle<JS::Value> aError,
ErrorResult& aRv) { // MOZ_KnownLive here instead of MOZ_KNOWN_LIVE at the field, because // mController is set outside of the constructor
WritableStreamDefaultControllerErrorIfNeeded(aCx, MOZ_KnownLive(mController),
aError, aRv);
}
} // namespace mozilla::dom
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.