SSL ReadableStreamTee.cpp
Interaktion und PortierbarkeitC
/* -*- 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 3. Skipped until we implement cloneForBranch2 path.
MOZ_RELEASE_ASSERT(!mTeeState->CloneForBranch2());
// Step 4. if (!mTeeState->Canceled1()) {
IgnoredErrorResult rv; // Since we controlled the creation of the two stream branches, we know // they both have default controllers.
RefPtr<ReadableStreamDefaultController> controller(
mTeeState->Branch1()->DefaultController());
ReadableStreamDefaultControllerEnqueue(cx, controller, chunk1, rv);
(void)NS_WARN_IF(rv.Failed());
}
// Algorithm described in // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamtee, Steps // 17 and Steps 18, genericized across branch numbers: // // Note: As specified this algorithm always returns a promise resolved with // undefined, however as some places immediately discard said promise, we // provide this version which doesn't return a promise. // // NativeByteStreamTeePullAlgorithm, which implements // UnderlyingSourcePullCallbackHelper is the version which provies the return // promise.
MOZ_CAN_RUN_SCRIPT void ByteStreamTeePullAlgorithm(JSContext* aCx,
TeeBranch aForBranch,
TeeState* aTeeState,
ErrorResult& aRv) { // Step {17,18}.1: If reading is true, if (aTeeState->Reading()) { // Step {17,18}.1.1: Set readAgainForBranch{1,2} to true.
aTeeState->SetReadAgainForBranch(aForBranch, true);
// Step {17,18}.1.1: Return a promise resolved with undefined. return;
}
// Step {17,18}.2: Set reading to true.
aTeeState->SetReading(true);
// Step {17,18}.3: Let byobRequest be // !ReadableByteStreamControllerGetBYOBRequest(branch{1,2}.[[controller]]).
RefPtr<ReadableStreamBYOBRequest> byobRequest =
ReadableByteStreamControllerGetBYOBRequest(
aCx, aTeeState->Branch(aForBranch)->Controller()->AsByte(), aRv); if (aRv.Failed()) { return;
}
// Step {17,18}.4: If byobRequest is null, perform pullWithDefaultReader. if (!byobRequest) {
PullWithDefaultReader(aCx, aTeeState, aRv);
} else { // Step {17,18}.5: Otherwise, perform pullWithBYOBReader, given // byobRequest.[[view]] and {false, true}.
JS::Rooted<JSObject*> view(aCx, byobRequest->View());
PullWithBYOBReader(aCx, aTeeState, view, aForBranch, aRv);
}
// Step {17,18}.6: Return a promise resolved with undefined.
}
// https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamtee class ByteStreamTeeSourceAlgorithms final
: public UnderlyingSourceAlgorithmsBase { public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ByteStreamTeeSourceAlgorithms,
UnderlyingSourceAlgorithmsBase)
MOZ_CAN_RUN_SCRIPT void Run(AutoSlowOperation& aAso) override { // Step Numbering in this function is relative to the Queue a microtask // of the Chunk steps of 15.2.1 of // https://streams.spec.whatwg.org/#abstract-opdef-readablebytestreamtee
AutoJSAPI jsapi; if (NS_WARN_IF(
!jsapi.Init(mTeeState->GetStream()->GetParentObject()))) { return;
}
JSContext* cx = jsapi.cx();
// Step 1. Set readAgainForBranch1 to false.
mTeeState->SetReadAgainForBranch1(false);
// Step 2. Set readAgainForBranch2 to false.
mTeeState->SetReadAgainForBranch2(false);
// Step 3. Let chunk1 and chunk2 be chunk.
JS::Rooted<JSObject*> chunk1(cx, mChunk);
JS::Rooted<JSObject*> chunk2(cx, mChunk);
// Step 4. If canceled1 is false and canceled2 is false,
ErrorResult rv; if (!mTeeState->Canceled1() && !mTeeState->Canceled2()) { // Step 4.1. Let cloneResult be CloneAsUint8Array(chunk).
JS::Rooted<JSObject*> cloneResult(cx, CloneAsUint8Array(cx, mChunk));
// Step 4.2. If cloneResult is an abrupt completion, if (!cloneResult) { // Step 4.2.1 Perform // !ReadableByteStreamControllerError(branch1.[[controller]], // cloneResult.[[Value]]).
JS::Rooted<JS::Value> exceptionValue(cx); if (!JS_GetPendingException(cx, &exceptionValue)) { // Uncatchable exception, simply return. return;
}
JS_ClearPendingException(cx);
ErrorResult rv;
ReadableByteStreamControllerError(
mTeeState->Branch1()->Controller()->AsByte(), exceptionValue,
rv); if (rv.MaybeSetPendingException(
cx, "Error during ReadableByteStreamControllerError")) { return;
}
// Step 1. Set reading to false.
mTeeState->SetReading(false);
// Step 2. If canceled1 is false, perform ! // ReadableByteStreamControllerClose(branch1.[[controller]]).
RefPtr<ReadableByteStreamController> branch1Controller =
mTeeState->Branch1()->Controller()->AsByte(); if (!mTeeState->Canceled1()) {
ReadableByteStreamControllerClose(aCx, branch1Controller, aRv); if (aRv.Failed()) { return;
}
}
// Step 3. If canceled2 is false, perform ! // ReadableByteStreamControllerClose(branch2.[[controller]]).
RefPtr<ReadableByteStreamController> branch2Controller =
mTeeState->Branch2()->Controller()->AsByte(); if (!mTeeState->Canceled2()) {
ReadableByteStreamControllerClose(aCx, branch2Controller, aRv); if (aRv.Failed()) { return;
}
}
// Step 4. If branch1.[[controller]].[[pendingPullIntos]] is not empty, // perform ! ReadableByteStreamControllerRespond(branch1.[[controller]], 0). if (!branch1Controller->PendingPullIntos().isEmpty()) {
ReadableByteStreamControllerRespond(aCx, branch1Controller, 0, aRv); if (aRv.Failed()) { return;
}
}
// Step 5. If branch2.[[controller]].[[pendingPullIntos]] is not empty, // perform ! ReadableByteStreamControllerRespond(branch2.[[controller]], 0). if (!branch2Controller->PendingPullIntos().isEmpty()) {
ReadableByteStreamControllerRespond(aCx, branch2Controller, 0, aRv); if (aRv.Failed()) { return;
}
}
// Step 6. If canceled1 is false or canceled2 is false, resolve // cancelPromise with undefined. if (!mTeeState->Canceled1() || !mTeeState->Canceled2()) {
mTeeState->CancelPromise()->MaybeResolveWithUndefined();
}
}
// Rather than store byobBranch / otherBranch, we re-derive the pointers // below, as borrowed from steps 16.2/16.3
ReadableStream* byobBranch = mTeeState->Branch(mForBranch);
ReadableStream* otherBranch =
mTeeState->Branch(OtherTeeBranch(mForBranch));
// Step 5. if (!otherCanceled) { // Step 5.1 (using the name clonedChunk because we don't want to name // the completion record explicitly)
JS::Rooted<JSObject*> clonedChunk(cx, CloneAsUint8Array(cx, mChunk));
// Step 5.2. If cloneResult is an abrupt completion, if (!clonedChunk) {
JS::Rooted<JS::Value> exception(cx); if (!JS_GetPendingException(cx, &exception)) { // Uncatchable exception. Return with pending // exception still on context. return;
}
// It's not expliclitly stated, but I assume the intention here is // that we perform a normal completion here, so we clear the // exception.
JS_ClearPendingException(cx);
// Step 5.2.1
ReadableByteStreamControllerError(
byobBranch->Controller()->AsByte(), exception, rv); if (rv.MaybeSetPendingException(cx)) { return;
}
// Rather than store byobBranch / otherBranch, we re-derive the pointers // below, as borrowed from steps 16.2/16.3
ReadableStream* byobBranch = mTeeState->Branch(mForBranch);
ReadableStream* otherBranch = mTeeState->Branch(OtherTeeBranch(mForBranch));
// Step 4. if (!byobCanceled) {
RefPtr<ReadableByteStreamController> controller =
byobBranch->Controller()->AsByte();
ReadableByteStreamControllerClose(aCx, controller, aRv); if (aRv.Failed()) { return;
}
} // Step 5. if (!otherCanceled) {
RefPtr<ReadableByteStreamController> controller =
otherBranch->Controller()->AsByte();
ReadableByteStreamControllerClose(aCx, controller, aRv); if (aRv.Failed()) { return;
}
}
// Step 6. if (!aChunk.isUndefined()) {
MOZ_ASSERT(aChunk.isObject());
MOZ_ASSERT(aChunk.toObjectOrNull());
// Step 14.1.4: If canceled1 is false or canceled2 is false, resolve // cancelPromise with undefined. if (!aTeeState->Canceled1() || !aTeeState->Canceled2()) {
aTeeState->CancelPromise()->MaybeResolveWithUndefined();
}
},
RefPtr(aTeeState), RefPtr(aThisReader));
}
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.