зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1812315 - Part 1: Implement WritableStream::SetUpNative for File System r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D167824
This commit is contained in:
Родитель
44009be00a
Коммит
d377991e6f
|
@ -27,7 +27,7 @@ namespace mozilla::dom {
|
|||
namespace {
|
||||
|
||||
class WritableFileStreamUnderlyingSinkAlgorithms final
|
||||
: public UnderlyingSinkAlgorithmsBase {
|
||||
: public UnderlyingSinkAlgorithmsWrapper {
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(
|
||||
WritableFileStreamUnderlyingSinkAlgorithms, UnderlyingSinkAlgorithmsBase)
|
||||
|
@ -36,20 +36,14 @@ class WritableFileStreamUnderlyingSinkAlgorithms final
|
|||
FileSystemWritableFileStream& aStream)
|
||||
: mStream(&aStream) {}
|
||||
|
||||
// Streams algorithms
|
||||
void StartCallback(JSContext* aCx,
|
||||
WritableStreamDefaultController& aController,
|
||||
JS::MutableHandle<JS::Value> aRetVal,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> WriteCallback(
|
||||
already_AddRefed<Promise> WriteCallback(
|
||||
JSContext* aCx, JS::Handle<JS::Value> aChunk,
|
||||
WritableStreamDefaultController& aController, ErrorResult& aRv) override;
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> CloseCallback(
|
||||
JSContext* aCx, ErrorResult& aRv) override;
|
||||
already_AddRefed<Promise> CloseCallbackImpl(JSContext* aCx,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> AbortCallback(
|
||||
already_AddRefed<Promise> AbortCallbackImpl(
|
||||
JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
|
@ -136,14 +130,11 @@ FileSystemWritableFileStream::~FileSystemWritableFileStream() {
|
|||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
// https://streams.spec.whatwg.org/#writablestream-set-up
|
||||
// https://fs.spec.whatwg.org/#create-a-new-filesystemwritablefilestream
|
||||
// * This is fallible because of OOM handling of JSAPI. See bug 1762233.
|
||||
// * Consider extracting this as UnderlyingSinkAlgorithmsWrapper if more classes
|
||||
// start subclassing WritableStream.
|
||||
// For now this skips step 2 - 4 as they are not required here.
|
||||
// XXX(krosylight): _BOUNDARY because SetUpWritableStreamDefaultController here
|
||||
// can't run script because StartCallback here is no-op. Can we let the static
|
||||
// check automatically detect this situation?
|
||||
// XXX(krosylight): _BOUNDARY because SetUpNative here can't run script because
|
||||
// StartCallback here is no-op. Can we let the static check automatically detect
|
||||
// this situation?
|
||||
/* static */
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY already_AddRefed<FileSystemWritableFileStream>
|
||||
FileSystemWritableFileStream::Create(
|
||||
|
@ -157,35 +148,32 @@ FileSystemWritableFileStream::Create(
|
|||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
// Step 5. Perform ! InitializeWritableStream(stream).
|
||||
// (Done by the constructor)
|
||||
// Step 1. Let stream be a new FileSystemWritableFileStream in realm.
|
||||
// Step 2. Set stream.[[file]] to file. (Covered by the constructor)
|
||||
RefPtr<FileSystemWritableFileStream> stream =
|
||||
new FileSystemWritableFileStream(aGlobal, aManager, std::move(aActor),
|
||||
aFileDescriptor, aMetadata);
|
||||
|
||||
// Step 1 - 3
|
||||
// Step 3 - 5
|
||||
auto algorithms =
|
||||
MakeRefPtr<WritableFileStreamUnderlyingSinkAlgorithms>(*stream);
|
||||
|
||||
// Step 6. Let controller be a new WritableStreamDefaultController.
|
||||
auto controller =
|
||||
MakeRefPtr<WritableStreamDefaultController>(aGlobal, *stream);
|
||||
|
||||
// Step 7. Perform ! SetUpWritableStreamDefaultController(stream, controller,
|
||||
// startAlgorithm, writeAlgorithm, closeAlgorithmWrapper,
|
||||
// abortAlgorithmWrapper, highWaterMark, sizeAlgorithm).
|
||||
// Step 8: Set up stream with writeAlgorithm set to writeAlgorithm,
|
||||
// closeAlgorithm set to closeAlgorithm, abortAlgorithm set to abortAlgorithm,
|
||||
// highWaterMark set to highWaterMark, and sizeAlgorithm set to sizeAlgorithm.
|
||||
IgnoredErrorResult rv;
|
||||
SetUpWritableStreamDefaultController(
|
||||
cx, stream, controller, algorithms,
|
||||
// https://fs.spec.whatwg.org/#create-a-new-filesystemwritablefilestream
|
||||
stream->SetUpNative(
|
||||
cx, *algorithms,
|
||||
// Step 6. Let highWaterMark be 1.
|
||||
1,
|
||||
Some(1),
|
||||
// Step 7. Let sizeAlgorithm be an algorithm that returns 1.
|
||||
// (nullptr returns 1, See WritableStream::Constructor for details)
|
||||
nullptr, rv);
|
||||
if (rv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 9: Return stream.
|
||||
return stream.forget();
|
||||
}
|
||||
|
||||
|
@ -640,14 +628,8 @@ NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(
|
|||
NS_IMPL_CYCLE_COLLECTION_INHERITED(WritableFileStreamUnderlyingSinkAlgorithms,
|
||||
UnderlyingSinkAlgorithmsBase, mStream)
|
||||
|
||||
void WritableFileStreamUnderlyingSinkAlgorithms::StartCallback(
|
||||
JSContext* aCx, WritableStreamDefaultController& aController,
|
||||
JS::MutableHandle<JS::Value> aRetVal, ErrorResult& aRv) {
|
||||
// https://streams.spec.whatwg.org/#writablestream-set-up
|
||||
// Step 1. Let startAlgorithm be an algorithm that returns undefined.
|
||||
aRetVal.setUndefined();
|
||||
}
|
||||
|
||||
// Step 3 of
|
||||
// https://fs.spec.whatwg.org/#create-a-new-filesystemwritablefilestream
|
||||
already_AddRefed<Promise>
|
||||
WritableFileStreamUnderlyingSinkAlgorithms::WriteCallback(
|
||||
JSContext* aCx, JS::Handle<JS::Value> aChunk,
|
||||
|
@ -655,12 +637,11 @@ WritableFileStreamUnderlyingSinkAlgorithms::WriteCallback(
|
|||
return mStream->Write(aCx, aChunk, aRv);
|
||||
}
|
||||
|
||||
// Step 4 of
|
||||
// https://fs.spec.whatwg.org/#create-a-new-filesystemwritablefilestream
|
||||
already_AddRefed<Promise>
|
||||
WritableFileStreamUnderlyingSinkAlgorithms::CloseCallback(JSContext* aCx,
|
||||
ErrorResult& aRv) {
|
||||
// https://streams.spec.whatwg.org/#writablestream-set-up
|
||||
// Step 2. Let closeAlgorithmWrapper be an algorithm that runs these steps:
|
||||
|
||||
WritableFileStreamUnderlyingSinkAlgorithms::CloseCallbackImpl(
|
||||
JSContext* aCx, ErrorResult& aRv) {
|
||||
RefPtr<Promise> promise = Promise::Create(mStream->GetParentObject(), aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
|
@ -671,28 +652,26 @@ WritableFileStreamUnderlyingSinkAlgorithms::CloseCallback(JSContext* aCx,
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
// XXX The close should be async. For now we have to always fallback to the
|
||||
// Step 2.3 below.
|
||||
// XXX The close should be async. For now we have to always fallback to a
|
||||
// resolved promise.
|
||||
mStream->Close();
|
||||
|
||||
// Step 2.3. Return a promise resolved with undefined.
|
||||
promise->MaybeResolveWithUndefined();
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// Step 5 of
|
||||
// https://fs.spec.whatwg.org/#create-a-new-filesystemwritablefilestream
|
||||
already_AddRefed<Promise>
|
||||
WritableFileStreamUnderlyingSinkAlgorithms::AbortCallback(
|
||||
WritableFileStreamUnderlyingSinkAlgorithms::AbortCallbackImpl(
|
||||
JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
|
||||
ErrorResult& aRv) {
|
||||
// https://streams.spec.whatwg.org/#writablestream-set-up
|
||||
// Step 3. Let abortAlgorithmWrapper be an algorithm that runs these steps:
|
||||
|
||||
// XXX The close or rather a dedicated abort should be async. For now we have
|
||||
// to always fall back to the Step 3.3 below.
|
||||
// to always fall back to return null.
|
||||
// (Step 3.3 of https://streams.spec.whatwg.org/#readablestream-set-up will
|
||||
// turn it into a resolved promise)
|
||||
mStream->Close();
|
||||
|
||||
// Step 3.3. Return a promise resolved with undefined.
|
||||
return Promise::CreateResolvedWithUndefined(mStream->GetParentObject(), aRv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void WritableFileStreamUnderlyingSinkAlgorithms::ReleaseObjects() {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/UnderlyingSinkCallbackHelpers.h"
|
||||
#include "StreamUtils.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -105,3 +106,25 @@ already_AddRefed<Promise> UnderlyingSinkAlgorithms::AbortCallback(
|
|||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// https://streams.spec.whatwg.org/#writable-set-up
|
||||
// Step 2.1: Let closeAlgorithmWrapper be an algorithm that runs these steps:
|
||||
already_AddRefed<Promise> UnderlyingSinkAlgorithmsWrapper::CloseCallback(
|
||||
JSContext* aCx, ErrorResult& aRv) {
|
||||
nsCOMPtr<nsIGlobalObject> global = xpc::CurrentNativeGlobal(aCx);
|
||||
return PromisifyAlgorithm(
|
||||
global, [&](ErrorResult& aRv) { return CloseCallbackImpl(aCx, aRv); },
|
||||
aRv);
|
||||
}
|
||||
|
||||
// https://streams.spec.whatwg.org/#writable-set-up
|
||||
// Step 3.1: Let abortAlgorithmWrapper be an algorithm that runs these steps:
|
||||
already_AddRefed<Promise> UnderlyingSinkAlgorithmsWrapper::AbortCallback(
|
||||
JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
|
||||
ErrorResult& aRv) {
|
||||
nsCOMPtr<nsIGlobalObject> global = xpc::CurrentNativeGlobal(aCx);
|
||||
return PromisifyAlgorithm(
|
||||
global,
|
||||
[&](ErrorResult& aRv) { return AbortCallbackImpl(aCx, aReason, aRv); },
|
||||
aRv);
|
||||
}
|
||||
|
|
|
@ -113,6 +113,46 @@ class UnderlyingSinkAlgorithms final : public UnderlyingSinkAlgorithmsBase {
|
|||
MOZ_KNOWN_LIVE RefPtr<UnderlyingSinkAbortCallback> mAbortCallback;
|
||||
};
|
||||
|
||||
// https://streams.spec.whatwg.org/#writablestream-set-up
|
||||
// Wrappers defined by the "Set up" methods in the spec.
|
||||
// (closeAlgorithmWrapper, abortAlgorithmWrapper)
|
||||
// This helps you just return nullptr when 1) the algorithm is synchronous, or
|
||||
// 2) an error occurred, as this wrapper will return a resolved or rejected
|
||||
// promise respectively.
|
||||
// Note that StartCallback is only for JS consumers to access the
|
||||
// controller, and thus is no-op here since native consumers can call
|
||||
// `ErrorNative()` etc. without direct controller access.
|
||||
class UnderlyingSinkAlgorithmsWrapper : public UnderlyingSinkAlgorithmsBase {
|
||||
public:
|
||||
void StartCallback(JSContext* aCx,
|
||||
WritableStreamDefaultController& aController,
|
||||
JS::MutableHandle<JS::Value> aRetVal,
|
||||
ErrorResult& aRv) final {
|
||||
// Step 1: Let startAlgorithm be an algorithm that returns undefined.
|
||||
aRetVal.setUndefined();
|
||||
}
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> CloseCallback(
|
||||
JSContext* aCx, ErrorResult& aRv) final;
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> AbortCallback(
|
||||
JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
|
||||
ErrorResult& aRv) final;
|
||||
|
||||
virtual already_AddRefed<Promise> CloseCallbackImpl(JSContext* aCx,
|
||||
ErrorResult& aRv) {
|
||||
// (closeAlgorithm is optional, give null by default)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<Promise> AbortCallbackImpl(
|
||||
JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
|
||||
ErrorResult& aRv) {
|
||||
// (abortAlgorithm is optional, give null by default)
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif
|
||||
|
|
|
@ -754,4 +754,38 @@ already_AddRefed<Promise> WritableStreamAddWriteRequest(WritableStream* aStream,
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
// https://streams.spec.whatwg.org/#writablestream-set-up
|
||||
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);
|
||||
|
||||
// Step 7: Perform ! SetUpWritableStreamDefaultController(stream, controller,
|
||||
// startAlgorithm, writeAlgorithm, closeAlgorithmWrapper,
|
||||
// abortAlgorithmWrapper, highWaterMark, sizeAlgorithm).
|
||||
SetUpWritableStreamDefaultController(aCx, this, controller, &aAlgorithms,
|
||||
highWaterMark, aSizeAlgorithm, aRv);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -153,12 +153,26 @@ class WritableStream : public nsISupports, public nsWrapperCache {
|
|||
JSContext* aCx, nsIGlobalObject* aGlobal, MessagePort& aPort,
|
||||
JS::MutableHandle<JSObject*> aReturnObject);
|
||||
|
||||
// Public functions to implement other specs
|
||||
// https://streams.spec.whatwg.org/#other-specs-ws
|
||||
|
||||
// https://streams.spec.whatwg.org/#writablestream-set-up
|
||||
protected:
|
||||
MOZ_CAN_RUN_SCRIPT void SetUpNative(
|
||||
JSContext* aCx, UnderlyingSinkAlgorithmsWrapper& aAlgorithms,
|
||||
Maybe<double> aHighWaterMark, QueuingStrategySize* aSizeAlgorithm,
|
||||
ErrorResult& aRv);
|
||||
|
||||
public:
|
||||
// IDL layer functions
|
||||
|
||||
nsIGlobalObject* GetParentObject() const { return mGlobal; }
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// IDL Methods
|
||||
// IDL methods
|
||||
|
||||
// TODO: Use MOZ_CAN_RUN_SCRIPT when IDL constructors can use it (bug 1749042)
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY static already_AddRefed<WritableStream>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
|
|
Загрузка…
Ссылка в новой задаче