/* -*- 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/. */
// https://streams.spec.whatwg.org/#transformstream-set-up // (except this instead creates a new TransformStream rather than accepting an // existing instance)
already_AddRefed<TransformStream> TransformStream::CreateGeneric( const GlobalObject& aGlobal, TransformerAlgorithmsWrapper& aAlgorithms,
ErrorResult& aRv) { // Step 1. Let writableHighWaterMark be 1. double writableHighWaterMark = 1;
// Step 2. Let writableSizeAlgorithm be an algorithm that returns 1. // Note: Callers should recognize nullptr as a callback that returns 1. See // also WritableStream::Constructor for this design decision.
RefPtr<QueuingStrategySize> writableSizeAlgorithm;
// Step 3. Let readableHighWaterMark be 0. double readableHighWaterMark = 0;
// Step 4. Let readableSizeAlgorithm be an algorithm that returns 1. // Note: Callers should recognize nullptr as a callback that returns 1. See // also ReadableStream::Constructor for this design decision.
RefPtr<QueuingStrategySize> readableSizeAlgorithm;
// Step 5. Let transformAlgorithmWrapper be an algorithm that runs these steps // given a value chunk: // Step 6. Let flushAlgorithmWrapper be an algorithm that runs these steps: // (Done by TransformerAlgorithmsWrapper)
// Step 7. Let startPromise be a promise resolved with undefined.
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<Promise> startPromise =
Promise::CreateResolvedWithUndefined(global, aRv); if (!startPromise) { return nullptr;
}
// https://streams.spec.whatwg.org/#initialize-transform-stream class TransformStreamUnderlyingSinkAlgorithms final
: public UnderlyingSinkAlgorithmsBase { public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(
TransformStreamUnderlyingSinkAlgorithms, UnderlyingSinkAlgorithmsBase)
// Step 1: Assert: stream.[[writable]].[[state]] is "writable".
MOZ_ASSERT(mStream->Writable()->State() ==
WritableStream::WriterState::Writable);
// Step 2: Let controller be stream.[[controller]].
RefPtr<TransformStreamDefaultController> controller = mStream->Controller();
// Step 3: If stream.[[backpressure]] is true, if (mStream->Backpressure()) { // Step 3.1: Let backpressureChangePromise be // stream.[[backpressureChangePromise]].
RefPtr<Promise> backpressureChangePromise =
mStream->BackpressureChangePromise();
// Step 3.2: Assert: backpressureChangePromise is not undefined.
MOZ_ASSERT(backpressureChangePromise);
// Step 3.3: Return the result of reacting to backpressureChangePromise // with the following fulfillment steps: auto result = backpressureChangePromise->ThenWithCycleCollectedArgsJS(
[](JSContext* aCx, JS::Handle<JS::Value>, ErrorResult& aRv, const RefPtr<TransformStream>& aStream, const RefPtr<TransformStreamDefaultController>& aController,
JS::Handle<JS::Value> aChunk)
MOZ_CAN_RUN_SCRIPT_BOUNDARY_LAMBDA -> already_AddRefed<Promise> { // Step 1: Let writable be stream.[[writable]].
RefPtr<WritableStream> writable = aStream->Writable();
// Step 2: Let state be writable.[[state]].
WritableStream::WriterState state = writable->State();
// Step 3: If state is "erroring", throw // writable.[[storedError]]. if (state == WritableStream::WriterState::Erroring) {
JS::Rooted<JS::Value> storedError(aCx,
writable->StoredError());
aRv.MightThrowJSException();
aRv.ThrowJSException(aCx, storedError); return nullptr;
}
// Step 4: Assert: state is "writable".
MOZ_ASSERT(state == WritableStream::WriterState::Writable);
// Step 1: Let readable be stream.[[readable]].
RefPtr<ReadableStream> readable = mStream->Readable();
// Step 2: Let controller be stream.[[controller]].
RefPtr<TransformStreamDefaultController> controller = mStream->Controller();
// Step 3: Let flushPromise be the result of performing // controller.[[flushAlgorithm]].
RefPtr<TransformerAlgorithmsBase> algorithms = controller->Algorithms();
RefPtr<Promise> flushPromise =
algorithms->FlushCallback(aCx, *controller, aRv); if (aRv.Failed()) { return nullptr;
}
// https://streams.spec.whatwg.org/#initialize-transform-stream class TransformStreamUnderlyingSourceAlgorithms final
: public UnderlyingSourceAlgorithmsBase { public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(
TransformStreamUnderlyingSourceAlgorithms, UnderlyingSourceAlgorithmsBase)
// Step 2. If stream.[[backpressureChangePromise]] is not undefined, resolve // stream.[[backpressureChangePromise]] with undefined. if (Promise* promise = BackpressureChangePromise()) {
promise->MaybeResolveWithUndefined();
}
// Step 3. Set stream.[[backpressureChangePromise]] to a new promise.
RefPtr<Promise> promise = Promise::CreateInfallible(GetParentObject());
mBackpressureChangePromise = promise;
// Step 4. Set stream.[[backpressure]] to backpressure.
mBackpressure = aBackpressure;
}
// Step 8. Set stream.[[readable]] to ! CreateReadableStream(startAlgorithm, // pullAlgorithm, cancelAlgorithm, readableHighWaterMark, // readableSizeAlgorithm).
mReadable = ReadableStream::CreateAbstract(
aCx, MOZ_KnownLive(mGlobal), sourceAlgorithms,
Some(aReadableHighWaterMark), aReadableSizeAlgorithm, aRv); if (aRv.Failed()) { return;
}
// Step 9. Set stream.[[backpressure]] and // stream.[[backpressureChangePromise]] to undefined. // Note(krosylight): The spec allows setting [[backpressure]] as undefined, // but I don't see why it should be. Since the spec also allows strict boolean // type, and this is only to not trigger assertion inside the setter, we just // set it as false.
mBackpressure = false;
mBackpressureChangePromise = nullptr;
// Step 11. Set stream.[[controller]] to undefined.
mController = nullptr;
}
// https://streams.spec.whatwg.org/#ts-constructor
already_AddRefed<TransformStream> TransformStream::Constructor( const GlobalObject& aGlobal, const Optional<JS::Handle<JSObject*>>& aTransformer, const QueuingStrategy& aWritableStrategy, const QueuingStrategy& aReadableStrategy, ErrorResult& aRv) { // Step 1. If transformer is missing, set it to null.
JS::Rooted<JSObject*> transformerObj(
aGlobal.Context(),
aTransformer.WasPassed() ? aTransformer.Value() : nullptr);
// Step 2. Let transformerDict be transformer, converted to an IDL value of // type Transformer.
RootedDictionary<Transformer> transformerDict(aGlobal.Context()); if (transformerObj) {
JS::Rooted<JS::Value> objValue(aGlobal.Context(),
JS::ObjectValue(*transformerObj));
dom::BindingCallContext callCx(aGlobal.Context(), "TransformStream.constructor");
aRv.MightThrowJSException(); if (!transformerDict.Init(callCx, objValue)) {
aRv.StealExceptionFromJSContext(aGlobal.Context()); return nullptr;
}
}
// Step 3. If transformerDict["readableType"] exists, throw a RangeError // exception. if (!transformerDict.mReadableType.isUndefined()) {
aRv.ThrowRangeError( "`readableType` is unsupported and preserved for future use"); return nullptr;
}
// Step 4. If transformerDict["writableType"] exists, throw a RangeError // exception. if (!transformerDict.mWritableType.isUndefined()) {
aRv.ThrowRangeError( "`writableType` is unsupported and preserved for future use"); return nullptr;
}
// Step 5. Let readableHighWaterMark be ? // ExtractHighWaterMark(readableStrategy, 0). double readableHighWaterMark =
ExtractHighWaterMark(aReadableStrategy, 0, aRv); if (aRv.Failed()) { return nullptr;
}
// Step 6. Let readableSizeAlgorithm be ! // ExtractSizeAlgorithm(readableStrategy). // Note: Callers should recognize nullptr as a callback that returns 1. See // also ReadableStream::Constructor for this design decision.
RefPtr<QueuingStrategySize> readableSizeAlgorithm =
aReadableStrategy.mSize.WasPassed() ? &aReadableStrategy.mSize.Value()
: nullptr;
// Step 7. Let writableHighWaterMark be ? // ExtractHighWaterMark(writableStrategy, 1). double writableHighWaterMark =
ExtractHighWaterMark(aWritableStrategy, 1, aRv); if (aRv.Failed()) { return nullptr;
}
// Step 8. Let writableSizeAlgorithm be ! // ExtractSizeAlgorithm(writableStrategy). // Note: Callers should recognize nullptr as a callback that returns 1. See // also WritableStream::Constructor for this design decision.
RefPtr<QueuingStrategySize> writableSizeAlgorithm =
aWritableStrategy.mSize.WasPassed() ? &aWritableStrategy.mSize.Value()
: nullptr;
// Step 9. Let startPromise be a new promise.
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<Promise> startPromise = Promise::CreateInfallible(global);
// Step 12. If transformerDict["start"] exists, then resolve startPromise with // the result of invoking transformerDict["start"] with argument list « // this.[[controller]] » and callback this value transformer. if (transformerDict.mStart.WasPassed()) {
RefPtr<TransformerStartCallback> callback = transformerDict.mStart.Value();
RefPtr<TransformStreamDefaultController> controller =
transformStream->Controller();
JS::Rooted<JS::Value> retVal(aGlobal.Context());
callback->Call(transformerObj, *controller, &retVal, aRv, "Transformer.start", CallbackFunction::eRethrowExceptions); if (aRv.Failed()) { return nullptr;
}
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.