зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1582348 - Add the most skeleton WritableStream class imaginable. r=arai
Differential Revision: https://phabricator.services.mozilla.com/D46397 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
d05c6fe9fd
Коммит
ef9d1b4371
|
@ -117,7 +117,7 @@
|
|||
&js::ReadableStreamDefaultController::class_) \
|
||||
REAL(ReadableByteStreamController, InitViaClassSpec, \
|
||||
&js::ReadableByteStreamController::class_) \
|
||||
IMAGINARY(WritableStream, dummy, dummy) \
|
||||
REAL(WritableStream, InitViaClassSpec, &js::WritableStream::class_) \
|
||||
IMAGINARY(WritableStreamDefaultWriter, dummy, dummy) \
|
||||
IMAGINARY(WritableStreamDefaultController, dummy, dummy) \
|
||||
REAL(ByteLengthQueuingStrategy, InitViaClassSpec, \
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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 WritableStream. */
|
||||
|
||||
#include "builtin/streams/WritableStream.h"
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
|
||||
#include "jsapi.h" // JS_ReportErrorNumberASCII
|
||||
#include "jspubtd.h" // JSProto_WritableStream
|
||||
|
||||
#include "builtin/streams/ClassSpecMacro.h" // JS_STREAMS_CLASS_SPEC
|
||||
#include "builtin/streams/MiscellaneousOperations.h" // js::MakeSizeAlgorithmFromSizeFunction, js::ValidateAndNormalizeHighWaterMark
|
||||
#include "builtin/streams/WritableStreamDefaultControllerOperations.h" // js::SetUpWritableStreamDefaultControllerFromUnderlyingSink
|
||||
#include "js/CallArgs.h" // JS::CallArgs{,FromVp}
|
||||
#include "js/Class.h" // JS{Function,Property}Spec, JS_{FS,PS}_END, JSCLASS_PRIVATE_IS_NSISUPPORTS, JSCLASS_HAS_PRIVATE, JS_NULL_CLASS_OPS
|
||||
#include "js/RealmOptions.h" // JS::RealmCreationOptions
|
||||
#include "js/RootingAPI.h" // JS::Handle, JS::Rooted
|
||||
#include "js/Value.h" // JS::{,Object}Value
|
||||
#include "vm/JSContext.h" // JSContext
|
||||
#include "vm/JSObject.h" // js::GetPrototypeFromBuiltinConstructor
|
||||
#include "vm/NativeObject.h" // js::PlainObject
|
||||
#include "vm/ObjectOperations.h" // js::GetProperty
|
||||
#include "vm/Realm.h" // JS::Realm
|
||||
|
||||
#include "vm/JSObject-inl.h" // js::NewBuiltinClassInstance
|
||||
#include "vm/NativeObject-inl.h" // js::ThrowIfNotConstructing
|
||||
|
||||
using js::WritableStream;
|
||||
|
||||
using JS::CallArgs;
|
||||
using JS::CallArgsFromVp;
|
||||
using JS::Handle;
|
||||
using JS::ObjectValue;
|
||||
using JS::Rooted;
|
||||
using JS::Value;
|
||||
|
||||
/*** 4.2. Class WritableStream **********************************************/
|
||||
|
||||
/**
|
||||
* Streams spec, 4.2.3. new WritableStream(underlyingSink = {}, strategy = {})
|
||||
*/
|
||||
bool WritableStream::constructor(JSContext* cx, unsigned argc, Value* vp) {
|
||||
MOZ_ASSERT(cx->realm()->creationOptions().getWritableStreamsEnabled(),
|
||||
"WritableStream should be enabled in this realm if we reach here");
|
||||
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (!ThrowIfNotConstructing(cx, args, "WritableStream")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implicit in the spec: argument default values.
|
||||
Rooted<Value> underlyingSink(cx, args.get(0));
|
||||
if (underlyingSink.isUndefined()) {
|
||||
JSObject* emptyObj = NewBuiltinClassInstance<PlainObject>(cx);
|
||||
if (!emptyObj) {
|
||||
return false;
|
||||
}
|
||||
underlyingSink = ObjectValue(*emptyObj);
|
||||
}
|
||||
|
||||
Rooted<Value> strategy(cx, args.get(1));
|
||||
if (strategy.isUndefined()) {
|
||||
JSObject* emptyObj = NewBuiltinClassInstance<PlainObject>(cx);
|
||||
if (!emptyObj) {
|
||||
return false;
|
||||
}
|
||||
strategy = ObjectValue(*emptyObj);
|
||||
}
|
||||
|
||||
// Implicit in the spec: Set this to
|
||||
// OrdinaryCreateFromConstructor(NewTarget, ...).
|
||||
// Step 1: Perform ! InitializeWritableStream(this).
|
||||
Rooted<JSObject*> proto(cx);
|
||||
if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_WritableStream,
|
||||
&proto)) {
|
||||
return false;
|
||||
}
|
||||
Rooted<WritableStream*> stream(cx,
|
||||
WritableStream::create(cx, nullptr, proto));
|
||||
if (!stream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 2: Let size be ? GetV(strategy, "size").
|
||||
Rooted<Value> size(cx);
|
||||
if (!GetProperty(cx, strategy, cx->names().size, &size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3: Let highWaterMark be ? GetV(strategy, "highWaterMark").
|
||||
Rooted<Value> highWaterMarkVal(cx);
|
||||
if (!GetProperty(cx, strategy, cx->names().highWaterMark,
|
||||
&highWaterMarkVal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 4: Let type be ? GetV(underlyingSink, "type").
|
||||
Rooted<Value> type(cx);
|
||||
if (!GetProperty(cx, underlyingSink, cx->names().type, &type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 5: If type is not undefined, throw a RangeError exception.
|
||||
if (!type.isUndefined()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_READABLESTREAM_UNDERLYINGSINK_TYPE_WRONG);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 6: Let sizeAlgorithm be ? MakeSizeAlgorithmFromSizeFunction(size).
|
||||
if (!MakeSizeAlgorithmFromSizeFunction(cx, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 7: If highWaterMark is undefined, let highWaterMark be 1.
|
||||
double highWaterMark;
|
||||
if (highWaterMarkVal.isUndefined()) {
|
||||
highWaterMark = 1;
|
||||
} else {
|
||||
// Step 8: Set highWaterMark to ?
|
||||
// ValidateAndNormalizeHighWaterMark(highWaterMark).
|
||||
if (!ValidateAndNormalizeHighWaterMark(cx, highWaterMarkVal,
|
||||
&highWaterMark)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 9: Perform
|
||||
// ? SetUpWritableStreamDefaultControllerFromUnderlyingSink(
|
||||
// this, underlyingSink, highWaterMark, sizeAlgorithm).
|
||||
if (!SetUpWritableStreamDefaultControllerFromUnderlyingSink(
|
||||
cx, stream, underlyingSink, highWaterMark, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const JSFunctionSpec WritableStream_methods[] = {JS_FS_END};
|
||||
|
||||
static const JSPropertySpec WritableStream_properties[] = {JS_PS_END};
|
||||
|
||||
JS_STREAMS_CLASS_SPEC(WritableStream, 0, SlotCount, 0,
|
||||
JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_HAS_PRIVATE,
|
||||
JS_NULL_CLASS_OPS);
|
|
@ -0,0 +1,50 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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 WritableStream. */
|
||||
|
||||
#ifndef builtin_streams_WritableStream_h
|
||||
#define builtin_streams_WritableStream_h
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
|
||||
#include "js/Class.h" // JSClass, js::ClassSpec
|
||||
#include "js/RootingAPI.h" // JS::Handle
|
||||
#include "js/Value.h" // JS::Value
|
||||
#include "vm/NativeObject.h" // js::NativeObject
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace js {
|
||||
|
||||
class WritableStream : public NativeObject {
|
||||
public:
|
||||
/**
|
||||
* Memory layout of WritableStream instances.
|
||||
*
|
||||
* See https://streams.spec.whatwg.org/#ws-internal-slots for details on
|
||||
* the stored state.
|
||||
*
|
||||
* XXX jwalden needs fleshin' out
|
||||
*/
|
||||
enum Slots { SlotCount };
|
||||
|
||||
public:
|
||||
static MOZ_MUST_USE WritableStream* create(
|
||||
JSContext* cx, void* nsISupportsObject_alreadyAddreffed = nullptr,
|
||||
JS::Handle<JSObject*> proto = nullptr);
|
||||
|
||||
static bool constructor(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
static const ClassSpec classSpec_;
|
||||
static const JSClass class_;
|
||||
static const ClassSpec protoClassSpec_;
|
||||
static const JSClass protoClass_;
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif // builtin_streams_WritableStream_h
|
|
@ -0,0 +1,34 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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/. */
|
||||
|
||||
/* Writable stream default controller abstract operations. */
|
||||
|
||||
#include "builtin/streams/WritableStreamDefaultControllerOperations.h"
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
|
||||
#include "jsapi.h" // JS_ReportErrorASCII
|
||||
|
||||
#include "builtin/streams/WritableStream.h" // js::WritableStream
|
||||
#include "vm/JSObject-inl.h" // js::NewObjectWithClassProto
|
||||
|
||||
using JS::Handle;
|
||||
using JS::Value;
|
||||
|
||||
/*** 4.8. Writable stream default controller abstract operations ************/
|
||||
|
||||
/**
|
||||
* Streams spec, 4.8.3.
|
||||
* SetUpWritableStreamDefaultControllerFromUnderlyingSink( stream,
|
||||
* underlyingSink, highWaterMark, sizeAlgorithm )
|
||||
*/
|
||||
MOZ_MUST_USE bool js::SetUpWritableStreamDefaultControllerFromUnderlyingSink(
|
||||
JSContext* cx, Handle<WritableStream*> stream, Handle<Value> underlyingSink,
|
||||
double highWaterMark, Handle<Value> sizeAlgorithm) {
|
||||
// XXX jwalden flesh me out
|
||||
JS_ReportErrorASCII(cx, "epic fail");
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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/. */
|
||||
|
||||
/* Writable stream default controller abstract operations. */
|
||||
|
||||
#ifndef builtin_streams_WritableStreamDefaultControllerOperations_h
|
||||
#define builtin_streams_WritableStreamDefaultControllerOperations_h
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
|
||||
#include "js/RootingAPI.h" // JS::Handle
|
||||
#include "js/Value.h" // JS::Value
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace js {
|
||||
|
||||
class WritableStream;
|
||||
|
||||
extern MOZ_MUST_USE bool SetUpWritableStreamDefaultControllerFromUnderlyingSink(
|
||||
JSContext* cx, JS::Handle<WritableStream*> stream,
|
||||
JS::Handle<JS::Value> underlyingSink, double highWaterMark,
|
||||
JS::Handle<JS::Value> sizeAlgorithm);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif // builtin_streams_WritableStreamDefaultControllerOperations_h
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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/. */
|
||||
|
||||
/* Writable stream abstract operations. */
|
||||
|
||||
#include "builtin/streams/WritableStreamOperations.h"
|
||||
|
||||
#include "mozilla/Attributes.h" // MOZ_MUST_USE
|
||||
|
||||
#include "jsapi.h" // JS_SetPrivate
|
||||
|
||||
#include "builtin/streams/WritableStream.h" // js::WritableStream
|
||||
#include "vm/JSObject-inl.h" // js::NewObjectWithClassProto
|
||||
|
||||
using js::WritableStream;
|
||||
|
||||
using JS::Handle;
|
||||
using JS::ObjectValue;
|
||||
using JS::Rooted;
|
||||
using JS::Value;
|
||||
|
||||
/*** 4.3. General writable stream abstract operations. **********************/
|
||||
|
||||
/**
|
||||
* Streams spec, 4.3.4. InitializeWritableStream ( stream )
|
||||
*/
|
||||
MOZ_MUST_USE /* static */
|
||||
WritableStream*
|
||||
WritableStream::create(
|
||||
JSContext* cx, void* nsISupportsObject_alreadyAddreffed /* = nullptr */,
|
||||
Handle<JSObject*> proto /* = nullptr */) {
|
||||
// In the spec, InitializeWritableStream is always passed a newly created
|
||||
// WritableStream object. We instead create it here and return it below.
|
||||
Rooted<WritableStream*> stream(
|
||||
cx, NewObjectWithClassProto<WritableStream>(cx, proto));
|
||||
if (!stream) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS_SetPrivate(stream, nsISupportsObject_alreadyAddreffed);
|
||||
|
||||
// XXX jwalden need to keep fleshin' out here
|
||||
return stream;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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/. */
|
||||
|
||||
/* Writable stream abstract operations. */
|
||||
|
||||
#ifndef builtin_streams_WritableStreamOperations_h
|
||||
#define builtin_streams_WritableStreamOperations_h
|
||||
|
||||
namespace js {} // namespace js
|
||||
|
||||
#endif // builtin_streams_WritableStreamOperations_h
|
|
@ -682,6 +682,10 @@ MSG_DEF(JSMSG_READABLESTREAMBYOBREQUEST_NO_CONTROLLER, 1, JSEXN_TYPEERR, "Read
|
|||
MSG_DEF(JSMSG_READABLESTREAMBYOBREQUEST_RESPOND_CLOSED, 0, JSEXN_TYPEERR, "ReadableStreamBYOBRequest method 'respond' called with non-zero number of bytes with a closed controller.")
|
||||
MSG_DEF(JSMSG_READABLESTREAM_METHOD_NOT_IMPLEMENTED, 1, JSEXN_TYPEERR, "ReadableStream method {0} not yet implemented")
|
||||
|
||||
// WritableStream
|
||||
MSG_DEF(JSMSG_READABLESTREAM_UNDERLYINGSINK_TYPE_WRONG, 0, JSEXN_RANGEERR,"'underlyingSink.type' must be undefined.")
|
||||
MSG_DEF(JSMSG_READABLESTREAM_NYI, 0, JSEXN_ERR, "full WritableStream support is not yet implemented")
|
||||
|
||||
// Other Stream-related
|
||||
MSG_DEF(JSMSG_STREAM_INVALID_HIGHWATERMARK, 0, JSEXN_RANGEERR, "'highWaterMark' must be a non-negative, non-NaN number.")
|
||||
MSG_DEF(JSMSG_STREAM_CONSUME_ERROR, 0, JSEXN_TYPEERR, "error consuming stream body")
|
||||
|
|
|
@ -237,6 +237,9 @@ UNIFIED_SOURCES += [
|
|||
'builtin/streams/ReadableStreamReader.cpp',
|
||||
'builtin/streams/StreamAPI.cpp',
|
||||
'builtin/streams/TeeState.cpp',
|
||||
'builtin/streams/WritableStream.cpp',
|
||||
'builtin/streams/WritableStreamDefaultControllerOperations.cpp',
|
||||
'builtin/streams/WritableStreamOperations.cpp',
|
||||
'builtin/String.cpp',
|
||||
'builtin/Symbol.cpp',
|
||||
'builtin/TestingFunctions.cpp',
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "builtin/streams/ReadableStream.h" // js::ReadableStream
|
||||
#include "builtin/streams/ReadableStreamController.h" // js::Readable{StreamDefault,ByteStream}Controller
|
||||
#include "builtin/streams/ReadableStreamReader.h" // js::ReadableStreamDefaultReader
|
||||
#include "builtin/streams/WritableStream.h" // js::WritableStream
|
||||
#include "builtin/Symbol.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "builtin/WeakMapObject.h"
|
||||
|
@ -108,6 +109,12 @@ bool GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key) {
|
|||
case JSProto_CountQueuingStrategy:
|
||||
return !cx->realm()->creationOptions().getStreamsEnabled();
|
||||
|
||||
case JSProto_WritableStream: {
|
||||
const auto& realmOptions = cx->realm()->creationOptions();
|
||||
return !realmOptions.getStreamsEnabled() ||
|
||||
!realmOptions.getWritableStreamsEnabled();
|
||||
}
|
||||
|
||||
// Return true if the given constructor has been disabled at run-time.
|
||||
case JSProto_Atomics:
|
||||
case JSProto_SharedArrayBuffer:
|
||||
|
|
Загрузка…
Ссылка в новой задаче