/* -*- 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/. */
class DecompressionStreamAlgorithms : public TransformerAlgorithmsWrapper { public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DecompressionStreamAlgorithms,
TransformerAlgorithmsBase)
// Step 3 of // https://wicg.github.io/compression/#dom-compressionstream-compressionstream // Let transformAlgorithm be an algorithm which takes a chunk argument and // runs the compress and enqueue a chunk algorithm with this and chunk.
MOZ_CAN_RUN_SCRIPT void TransformCallbackImpl(JS::Handle<JS::Value> aChunk,
TransformStreamDefaultController& aController,
ErrorResult& aRv) override {
AutoJSAPI jsapi; if (!jsapi.Init(aController.GetParentObject())) {
aRv.ThrowUnknownError("Internal error"); return;
}
JSContext* cx = jsapi.cx();
// Step 1: If chunk is not a BufferSource type, then throw a TypeError.
RootedUnion<OwningArrayBufferViewOrArrayBuffer> bufferSource(cx); if (!bufferSource.Init(cx, aChunk)) {
aRv.MightThrowJSException();
aRv.StealExceptionFromJSContext(cx); return;
}
// Step 2: Let buffer be the result of decompressing chunk with ds's format // and context. If this results in an error, then throw a TypeError. // Step 3 - 5: (Done in CompressAndEnqueue)
ProcessTypedArraysFixed(
bufferSource,
[&](const Span<uint8_t>& aData) MOZ_CAN_RUN_SCRIPT_BOUNDARY {
DecompressAndEnqueue(cx, aData, ZLibFlush::No, aController, aRv);
});
}
// Step 4 of // https://wicg.github.io/compression/#dom-compressionstream-compressionstream // Let flushAlgorithm be an algorithm which takes no argument and runs the // compress flush and enqueue algorithm with this.
MOZ_CAN_RUN_SCRIPT void FlushCallbackImpl(
TransformStreamDefaultController& aController,
ErrorResult& aRv) override {
AutoJSAPI jsapi; if (!jsapi.Init(aController.GetParentObject())) {
aRv.ThrowUnknownError("Internal error"); return;
}
JSContext* cx = jsapi.cx();
// Step 1: Let buffer be the result of decompressing an empty input with // ds's format and context, with the finish flag. // Step 2 - 4: (Done in CompressAndEnqueue)
DecompressAndEnqueue(cx, Span<const uint8_t>(), ZLibFlush::Yes, aController,
aRv);
}
// From the manual: inflate() returns ... switch (err) { case Z_DATA_ERROR: // Z_DATA_ERROR if the input data was corrupted (input stream not // conforming to the zlib format or incorrect check value, in which // case strm->msg points to a string with a more specific error)
aRv.ThrowTypeError("The input data is corrupted: "_ns +
nsDependentCString(mZStream.msg)); return; case Z_MEM_ERROR: // Z_MEM_ERROR if there was not enough memory
aRv.ThrowTypeError("Out of memory"); return; case Z_NEED_DICT: // Z_NEED_DICT if a preset dictionary is needed at this point // // From the `deflate` section of // https://wicg.github.io/compression/#supported-formats: // * The FDICT flag is not supported by these APIs, and will error the // stream if set. // And FDICT means preset dictionary per // https://datatracker.ietf.org/doc/html/rfc1950#page-5.
aRv.ThrowTypeError( "The stream needs a preset dictionary but such setup is " "unsupported"); return; case Z_STREAM_END: // Z_STREAM_END if the end of the compressed data has been reached and // all uncompressed output has been produced // // https://wicg.github.io/compression/#supported-formats has error // conditions for each compression format when additional input comes // after stream end. // Note that additional calls for inflate() immediately emits // Z_STREAM_END after this point. if (mZStream.avail_in > 0) {
aRv.ThrowTypeError("Unexpected input after the end of stream"); return;
}
mObservedStreamEnd = true; break; case Z_OK: case Z_BUF_ERROR: // * Z_OK if some progress has been made // * Z_BUF_ERROR if no progress was possible or if there was not // enough room in the output buffer when Z_FINISH is used. Note that // Z_BUF_ERROR is not fatal, and inflate() can be called again with // more input and more output space to continue decompressing. // // (But of course no input should be given after Z_FINISH) break; case Z_STREAM_ERROR: default: // * Z_STREAM_ERROR if the stream state was inconsistent // (which is fatal)
MOZ_ASSERT_UNREACHABLE("Unexpected decompression error code");
aRv.ThrowTypeError("Unexpected decompression error"); return;
}
// At this point we either exhausted the input or the output buffer
MOZ_ASSERT(!mZStream.avail_in || !mZStream.avail_out);
size_t written = kBufferSize - mZStream.avail_out; if (!written) { break;
}
// Step 3: If buffer is empty, return. // (We'll implicitly return when the array is empty.)
// Step 4: Split buffer into one or more non-empty pieces and convert them // into Uint8Arrays. // (The buffer is 'split' by having a fixed sized buffer above.)
JS::Rooted<JSObject*> view(aCx, nsJSUtils::MoveBufferAsUint8Array(
aCx, written, std::move(buffer))); if (!view || !array.append(view)) {
JS_ClearPendingException(aCx);
aRv.ThrowTypeError("Out of memory"); return;
}
} while (mZStream.avail_out == 0 && !mObservedStreamEnd); // From the manual: // * It must update next_out and avail_out when avail_out has dropped to // zero. // * inflate() should normally be called until it returns Z_STREAM_END or an // error.
if (aFlush == ZLibFlush::Yes && !mObservedStreamEnd) { // Step 2 of // https://wicg.github.io/compression/#decompress-flush-and-enqueue // If the end of the compressed input has not been reached, then throw a // TypeError.
aRv.ThrowTypeError("The input is ended without reaching the stream end"); return;
}
// Step 5: For each Uint8Array array, enqueue array in cs's transform. for (constauto& view : array) {
JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*view));
aController.Enqueue(aCx, value, aRv); if (aRv.Failed()) { return;
}
}
}
// https://wicg.github.io/compression/#dom-decompressionstream-decompressionstream
already_AddRefed<DecompressionStream> DecompressionStream::Constructor( const GlobalObject& aGlobal, CompressionFormat aFormat, ErrorResult& aRv) { // Step 1: If format is unsupported in DecompressionStream, then throw a // TypeError. // XXX: Skipped as we are using enum for this
// Step 2 - 4: (Done in DecompressionStreamAlgorithms)
// Step 5: Set this's transform to a new TransformStream.
// Step 6: Set up this's transform with transformAlgorithm set to // transformAlgorithm and flushAlgorithm set to flushAlgorithm. auto algorithms = MakeRefPtr<DecompressionStreamAlgorithms>(aFormat);
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.