Quelle ReadableStreamDefaultController.cpp
Sprache: C
/* -*- 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/. */
// Note: Using the individual macros vs NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE // because I need to specify a manual implementation of // NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN.
NS_IMPL_CYCLE_COLLECTION_CLASS(ReadableStreamDefaultController)
ReadableStreamDefaultController::~ReadableStreamDefaultController() { // MG:XXX: LinkedLists are required to be empty at destruction, but it seems // it is possible to have a controller be destructed while still // having entries in its queue. // // This needs to be verified as not indicating some other issue.
mozilla::DropJSObjects(this);
mQueue.clear();
}
// Step 2. If controller.[[closeRequested]] is false and state is "readable", // return true. // Step 3. Return false. return !aController->CloseRequested() &&
state == ReadableStream::ReaderState::Readable;
}
// https://streams.spec.whatwg.org/#readable-stream-default-controller-can-close-or-enqueue // This is a variant of ReadableStreamDefaultControllerCanCloseOrEnqueue // that also throws when the function would return false to improve error // messages. bool ReadableStreamDefaultControllerCanCloseOrEnqueueAndThrow(
ReadableStreamDefaultController* aController,
CloseOrEnqueue aCloseOrEnqueue, ErrorResult& aRv) { // Step 1. Let state be controller.[[stream]].[[state]].
ReadableStream::ReaderState state = aController->Stream()->State();
nsCString prefix; if (aCloseOrEnqueue == CloseOrEnqueue::Close) {
prefix = "Cannot close a stream that "_ns;
} else {
prefix = "Cannot enqueue into a stream that "_ns;
}
switch (state) { case ReadableStream::ReaderState::Readable: // Step 2. If controller.[[closeRequested]] is false and // state is "readable", return true. // Note: We don't error/check for [[closeRequest]] first, because // [[closedRequest]] is still true even after the state is "closed". // This doesn't cause any spec observable difference. if (!aController->CloseRequested()) { returntrue;
}
// Step 3. Return false.
aRv.ThrowTypeError(prefix + "has already been requested to close."_ns); returnfalse;
case ReadableStream::ReaderState::Closed:
aRv.ThrowTypeError(prefix + "is already closed."_ns); returnfalse;
case ReadableStream::ReaderState::Errored:
aRv.ThrowTypeError(prefix + "has errored."_ns); returnfalse;
// https://streams.spec.whatwg.org/#readable-stream-default-controller-clear-algorithms // // Note: nullptr is used to indicate we run the default algorithm at the // moment, // so the below doesn't quite match the spec, but serves the correct // purpose for disconnecting the algorithms from the object graph to allow // collection. // // As far as I know, this isn't currently visible, but we need to keep // this in mind. This is a weakness of this current implementation, and // I'd prefer to have a better answer here eventually. void ReadableStreamDefaultControllerClearAlgorithms(
ReadableStreamDefaultController* aController) { // Step 1. // Step 2.
aController->ClearAlgorithms();
// If !sizeAlgorithm, we return 1, which is inlined from // https://streams.spec.whatwg.org/#make-size-algorithm-from-size-function double chunkSize =
sizeAlgorithm
? sizeAlgorithm->Call(
optionalChunk, aRv, "ReadableStreamDefaultController.[[strategySizeAlgorithm]]",
CallbackObject::eRethrowExceptions)
: 1.0;
// If this is an uncatchable exception we can't continue. if (aRv.IsUncatchableException()) { return;
}
// Step 4.2: if (aRv.MaybeSetPendingException(
aCx, "ReadableStreamDefaultController.enqueue")) {
JS::Rooted<JS::Value> errorValue(aCx);
JS_GetPendingException(aCx, &errorValue);
// Step 4.2.1
ReadableStreamDefaultControllerError(aCx, aController, errorValue, aRv); if (aRv.Failed()) { return;
}
// Step 4.2.2 Caller must treat aRv as if it were a completion // value
aRv.MightThrowJSException();
aRv.ThrowJSException(aCx, errorValue); return;
}
// Step 4.5 // Note we convert the pending exception to a JS value here, and then // re-throw it because we save this exception and re-expose it elsewhere // and there are tests to ensure the identity of these errors are the same. if (aRv.MaybeSetPendingException(
aCx, "ReadableStreamDefaultController.enqueue")) {
JS::Rooted<JS::Value> errorValue(aCx);
if (!JS_GetPendingException(aCx, &errorValue)) { // Uncatchable exception; we should mark aRv and return.
aRv.StealExceptionFromJSContext(aCx); return;
}
JS_ClearPendingException(aCx);
// Step 4.5.2 Caller must treat aRv as if it were a completion // value
aRv.MightThrowJSException();
aRv.ThrowJSException(aCx, errorValue); return;
}
}
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.