diff --git a/src/bun.js/bindings/BunReadableStreamDefaultReader.cpp b/src/bun.js/bindings/BunReadableStreamDefaultReader.cpp index 2acf41a765..28bc2c9dd1 100644 --- a/src/bun.js/bindings/BunReadableStreamDefaultReader.cpp +++ b/src/bun.js/bindings/BunReadableStreamDefaultReader.cpp @@ -1,91 +1,19 @@ -#include "ErrorCode+List.h" -#include "root.h" - -#include -#include -#include "JavaScriptCore/JSCast.h" -#include -#include +#include "BunReadableStreamDefaultReader.h" #include "BunReadableStream.h" -#include +#include "BunReadableStreamDefaultController.h" #include "BunStreamInlines.h" #include "BunTeeState.h" #include "JSAbortSignal.h" -#include "BunReadableStreamDefaultController.h" -#include -#include "BunReadableStreamDefaultReader.h" -#include "ErrorCode.h" +#include +#include +#include + namespace Bun { using namespace JSC; -class JSReadableStreamDefaultReaderPrototype final : public JSC::JSNonFinalObject { -public: - using Base = JSC::JSNonFinalObject; - - static JSReadableStreamDefaultReaderPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSReadableStreamDefaultReaderPrototype* ptr = new (NotNull, JSC::allocateCell(vm)) JSReadableStreamDefaultReaderPrototype(vm, globalObject, structure); - ptr->finishCreation(vm); - return ptr; - } - - DECLARE_INFO; - template - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableStreamDefaultReaderPrototype, Base); - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - -private: - JSReadableStreamDefaultReaderPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&); -}; - -// JSReadableStreamDefaultReader.cpp - -static JSC_DECLARE_CUSTOM_GETTER(readableStreamDefaultReaderClosedGetter); -static JSC_DECLARE_CUSTOM_GETTER(readableStreamDefaultReaderReadyGetter); -static JSC_DECLARE_HOST_FUNCTION(readableStreamDefaultReaderRead); -static JSC_DECLARE_HOST_FUNCTION(readableStreamDefaultReaderReleaseLock); -static JSC_DECLARE_HOST_FUNCTION(readableStreamDefaultReaderCancel); - const ClassInfo JSReadableStreamDefaultReader::s_info = { "ReadableStreamDefaultReader"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableStreamDefaultReader) }; -static const HashTableValue JSReadableStreamDefaultReaderPrototypeTableValues[] = { - { "closed"_s, - static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor), - NoIntrinsic, - { HashTableValue::GetterSetterType, readableStreamDefaultReaderClosedGetter, nullptr } }, - { "ready"_s, - static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor), - NoIntrinsic, - { HashTableValue::GetterSetterType, readableStreamDefaultReaderReadyGetter, nullptr } }, - { "read"_s, - static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::Function), - NoIntrinsic, - { HashTableValue::NativeFunctionType, readableStreamDefaultReaderRead, 0 } }, - { "releaseLock"_s, - static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::Function), - NoIntrinsic, - { HashTableValue::NativeFunctionType, readableStreamDefaultReaderReleaseLock, 0 } }, - { "cancel"_s, - static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::Function), - NoIntrinsic, - { HashTableValue::NativeFunctionType, readableStreamDefaultReaderCancel, 1 } }, -}; - -const ClassInfo JSReadableStreamDefaultReaderPrototype::s_info = { "ReadableStreamDefaultReader"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableStreamDefaultReaderPrototype) }; - JSReadableStreamDefaultReader* JSReadableStreamDefaultReader::create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure, JSReadableStream* stream) { JSReadableStreamDefaultReader* reader = new (NotNull, JSC::allocateCell(vm)) JSReadableStreamDefaultReader(vm, structure); @@ -135,13 +63,6 @@ void JSReadableStreamDefaultReader::releaseLock() detach(); } -void JSReadableStreamDefaultReaderPrototype::finishCreation(JSC::VM& vm) -{ - Base::finishCreation(vm); - reifyStaticProperties(vm, JSReadableStreamDefaultReader::info(), JSReadableStreamDefaultReaderPrototypeTableValues, *this); - JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); -} - JSPromise* JSReadableStreamDefaultReader::read(JSC::VM& vm, JSGlobalObject* globalObject) { auto scope = DECLARE_THROW_SCOPE(vm); @@ -162,134 +83,27 @@ JSPromise* JSReadableStreamDefaultReader::read(JSC::VM& vm, JSGlobalObject* glob return promise; } -// JS Bindings Implementation -JSC_DEFINE_HOST_FUNCTION(readableStreamDefaultReaderRead, (JSGlobalObject * globalObject, CallFrame* callFrame)) +Structure* JSReadableStreamDefaultReader::structure(JSC::VM& vm, JSGlobalObject* globalObject) { - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - JSReadableStreamDefaultReader* reader = jsDynamicCast(callFrame->thisValue()); - if (!reader) { - scope.throwException(globalObject, createTypeError(globalObject, "ReadableStreamDefaultReader.prototype.read called on incompatible object"_s)); - return {}; - } - - JSC::JSPromise* promise = reader->read(vm, globalObject); - RETURN_IF_EXCEPTION(scope, {}); - return JSC::JSValue::encode(promise); + return globalObject->readableStreamDefaultReaderStructure(); } -class JSReadableStreamDefaultReaderConstructor final : public JSC::InternalFunction { -public: - using Base = JSC::InternalFunction; - static JSReadableStreamDefaultReaderConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSReadableStreamDefaultReaderPrototype* prototype) - { - JSReadableStreamDefaultReaderConstructor* constructor = new (NotNull, JSC::allocateCell(vm)) JSReadableStreamDefaultReaderConstructor(vm, structure); - constructor->finishCreation(vm, globalObject, prototype); - return constructor; - } - - DECLARE_INFO; - template - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return &vm.plainObjectSpace(); - } - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - -private: - JSReadableStreamDefaultReaderConstructor(JSC::VM& vm, JSC::Structure* structure) - : Base(vm, structure, call, construct) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*, JSReadableStreamDefaultReaderPrototype*); - - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES call(JSC::JSGlobalObject*, JSC::CallFrame*); - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); -}; - -// Implementation - -const ClassInfo JSReadableStreamDefaultReaderConstructor::s_info = { "ReadableStreamDefaultReader"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableStreamDefaultReaderConstructor) }; - -void JSReadableStreamDefaultReaderConstructor::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSReadableStreamDefaultReaderPrototype* prototype) +JSObject* JSReadableStreamDefaultReader::prototype(JSC::VM& vm, JSGlobalObject* globalObject) { - Base::finishCreation(vm, 1, "ReadableStreamDefaultReader"_s, PropertyAdditionMode::WithStructureTransition); - putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - ASSERT(inherits(info())); + return globalObject->readableStreamDefaultReaderPrototype(); } -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSReadableStreamDefaultReaderConstructor::call(JSC::JSGlobalObject* globalObject, JSC::CallFrame*) +JSObject* JSReadableStreamDefaultReader::constructor(JSC::VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - Bun::throwError(globalObject, scope, Bun::ErrorCode::ERR_ILLEGAL_CONSTRUCTOR, "ReadableStreamDefaultReader constructor cannot be called as a function"_s); - return {}; + return globalObject->readableStreamDefaultReaderConstructor(); } -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSReadableStreamDefaultReaderConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +template +GCClient::IsoSubspace* JSReadableStreamDefaultReader::subspaceFor(VM& vm) { - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - if (callFrame->argumentCount() < 1) { - return throwVMTypeError(globalObject, scope, "ReadableStreamDefaultReader constructor requires a ReadableStream argument"_s); - } - - JSValue streamValue = callFrame->uncheckedArgument(0); - JSReadableStream* stream = jsDynamicCast(streamValue); - if (!stream) { - return throwVMTypeError(globalObject, scope, "ReadableStreamDefaultReader constructor argument must be a ReadableStream"_s); - } - - // Check if stream is already locked - if (stream->isLocked()) { - return throwVMTypeError(globalObject, scope, "Cannot construct a ReadableStreamDefaultReader for a locked ReadableStream"_s); - } - - JSC::JSObject* newTarget = callFrame->newTarget().getObject(); - JSC::JSObject* constructor = callFrame->jsCallee(); - - auto* structure = defaultGlobalObject(globalObject)->readableStreamDefaultReaderStructure(); - - // TODO: double-check this. - if (!(!newTarget || newTarget == constructor)) { - if (newTarget) { - structure = JSC::InternalFunction::createSubclassStructure(getFunctionRealm(globalObject, newTarget), newTarget, structure); - } else { - structure = JSC::InternalFunction::createSubclassStructure(globalObject, constructor, structure); - } - } - RETURN_IF_EXCEPTION(scope, {}); - - JSReadableStreamDefaultReader* reader = JSReadableStreamDefaultReader::create(vm, globalObject, structure, stream); - RETURN_IF_EXCEPTION(scope, {}); - - // Lock the stream to this reader - stream->setReader(reader); - - // Set up initial ready state - if (stream->isDisturbed() || stream->state() == JSReadableStream::State::Errored) { - JSValue error = stream->storedError(); - if (!error) - error = jsUndefined(); - - reader->readyPromise()->reject(globalObject, error); - } else { - reader->readyPromise()->fulfillWithNonPromise(globalObject, jsUndefined()); - } - - RELEASE_AND_RETURN(scope, JSValue::encode(reader)); + if constexpr (mode == SubspaceAccess::Concurrently) + return nullptr; + return &vm.plainObjectSpace(); } -} +} // namespace Bun diff --git a/src/bun.js/bindings/BunReadableStreamDefaultReader.h b/src/bun.js/bindings/BunReadableStreamDefaultReader.h index e494248985..d0b8bfc92f 100644 --- a/src/bun.js/bindings/BunReadableStreamDefaultReader.h +++ b/src/bun.js/bindings/BunReadableStreamDefaultReader.h @@ -1,12 +1,11 @@ -#include "root.h" +#pragma once +#include "root.h" #include #include -#include "JavaScriptCore/JSCast.h" #include #include #include -#include namespace Bun { @@ -33,7 +32,12 @@ public: DECLARE_VISIT_CHILDREN; template - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm); + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return &vm.plainObjectSpace(); + } // Public API for C++ usage JSC::JSPromise* readyPromise() { return m_readyPromise.get(); } @@ -65,4 +69,4 @@ private: JSC::WriteBarrier m_readRequests; }; -} +} // namespace Bun diff --git a/src/bun.js/bindings/BunReadableStreamDefaultReaderConstructor.cpp b/src/bun.js/bindings/BunReadableStreamDefaultReaderConstructor.cpp new file mode 100644 index 0000000000..abc284fc04 --- /dev/null +++ b/src/bun.js/bindings/BunReadableStreamDefaultReaderConstructor.cpp @@ -0,0 +1,90 @@ +#include "BunReadableStreamDefaultReaderConstructor.h" +#include "BunReadableStreamDefaultReader.h" +#include "BunReadableStream.h" +#include "ErrorCode.h" +#include + +namespace Bun { + +using namespace JSC; + +const ClassInfo JSReadableStreamDefaultReaderConstructor::s_info = { "ReadableStreamDefaultReader"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableStreamDefaultReaderConstructor) }; + +JSReadableStreamDefaultReaderConstructor* JSReadableStreamDefaultReaderConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSReadableStreamDefaultReaderPrototype* prototype) +{ + JSReadableStreamDefaultReaderConstructor* constructor = new (NotNull, JSC::allocateCell(vm)) JSReadableStreamDefaultReaderConstructor(vm, structure); + constructor->finishCreation(vm, globalObject, prototype); + return constructor; +} + +void JSReadableStreamDefaultReaderConstructor::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSReadableStreamDefaultReaderPrototype* prototype) +{ + Base::finishCreation(vm, 1, "ReadableStreamDefaultReader"_s, PropertyAdditionMode::WithStructureTransition); + putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); + ASSERT(inherits(info())); +} + +JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSReadableStreamDefaultReaderConstructor::call(JSC::JSGlobalObject* globalObject, JSC::CallFrame*) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + Bun::throwError(globalObject, scope, Bun::ErrorCode::ERR_ILLEGAL_CONSTRUCTOR, "ReadableStreamDefaultReader constructor cannot be called as a function"_s); + return {}; +} + +JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSReadableStreamDefaultReaderConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (callFrame->argumentCount() < 1) { + return throwVMTypeError(globalObject, scope, "ReadableStreamDefaultReader constructor requires a ReadableStream argument"_s); + } + + JSValue streamValue = callFrame->uncheckedArgument(0); + JSReadableStream* stream = jsDynamicCast(streamValue); + if (!stream) { + return throwVMTypeError(globalObject, scope, "ReadableStreamDefaultReader constructor argument must be a ReadableStream"_s); + } + + // Check if stream is already locked + if (stream->isLocked()) { + return throwVMTypeError(globalObject, scope, "Cannot construct a ReadableStreamDefaultReader for a locked ReadableStream"_s); + } + + JSC::JSObject* newTarget = callFrame->newTarget().getObject(); + JSC::JSObject* constructor = callFrame->jsCallee(); + + auto* structure = defaultGlobalObject(globalObject)->readableStreamDefaultReaderStructure(); + + // TODO: double-check this. + if (!(!newTarget || newTarget == constructor)) { + if (newTarget) { + structure = JSC::InternalFunction::createSubclassStructure(getFunctionRealm(globalObject, newTarget), newTarget, structure); + } else { + structure = JSC::InternalFunction::createSubclassStructure(globalObject, constructor, structure); + } + } + RETURN_IF_EXCEPTION(scope, {}); + + JSReadableStreamDefaultReader* reader = JSReadableStreamDefaultReader::create(vm, globalObject, structure, stream); + RETURN_IF_EXCEPTION(scope, {}); + + // Lock the stream to this reader + stream->setReader(reader); + + // Set up initial ready state + if (stream->isDisturbed() || stream->state() == JSReadableStream::State::Errored) { + JSValue error = stream->storedError(); + if (!error) + error = jsUndefined(); + + reader->readyPromise()->reject(globalObject, error); + } else { + reader->readyPromise()->fulfillWithNonPromise(globalObject, jsUndefined()); + } + + RELEASE_AND_RETURN(scope, JSValue::encode(reader)); +} + +} // namespace Bun diff --git a/src/bun.js/bindings/BunReadableStreamDefaultReaderConstructor.h b/src/bun.js/bindings/BunReadableStreamDefaultReaderConstructor.h new file mode 100644 index 0000000000..24e7209c26 --- /dev/null +++ b/src/bun.js/bindings/BunReadableStreamDefaultReaderConstructor.h @@ -0,0 +1,48 @@ +#pragma once + +#include "root.h" +#include + +namespace Bun { + +using namespace JSC; + +class JSReadableStreamDefaultReaderPrototype; + +class JSReadableStreamDefaultReaderConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + + static JSReadableStreamDefaultReaderConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSReadableStreamDefaultReaderPrototype* prototype); + + DECLARE_INFO; + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return &vm.plainObjectSpace(); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; + +private: + JSReadableStreamDefaultReaderConstructor(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure, call, construct) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*, JSReadableStreamDefaultReaderPrototype*); + + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES call(JSC::JSGlobalObject*, JSC::CallFrame*); + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); +}; + +} // namespace Bun diff --git a/src/bun.js/bindings/BunReadableStreamDefaultReaderPrototype.cpp b/src/bun.js/bindings/BunReadableStreamDefaultReaderPrototype.cpp new file mode 100644 index 0000000000..f774115c07 --- /dev/null +++ b/src/bun.js/bindings/BunReadableStreamDefaultReaderPrototype.cpp @@ -0,0 +1,136 @@ +#include "BunReadableStreamDefaultReaderPrototype.h" +#include "BunReadableStreamDefaultReader.h" +#include "BunReadableStream.h" +#include +#include + +namespace Bun { + +using namespace JSC; + +static JSC_DECLARE_CUSTOM_GETTER(readableStreamDefaultReaderClosedGetter); +static JSC_DECLARE_CUSTOM_GETTER(readableStreamDefaultReaderReadyGetter); +static JSC_DECLARE_HOST_FUNCTION(readableStreamDefaultReaderRead); +static JSC_DECLARE_HOST_FUNCTION(readableStreamDefaultReaderReleaseLock); +static JSC_DECLARE_HOST_FUNCTION(readableStreamDefaultReaderCancel); + +const ClassInfo JSReadableStreamDefaultReaderPrototype::s_info = { "ReadableStreamDefaultReader"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableStreamDefaultReaderPrototype) }; + +static const HashTableValue JSReadableStreamDefaultReaderPrototypeTableValues[] = { + { "closed"_s, + static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor), + NoIntrinsic, + { HashTableValue::GetterSetterType, readableStreamDefaultReaderClosedGetter, nullptr } }, + { "ready"_s, + static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor), + NoIntrinsic, + { HashTableValue::GetterSetterType, readableStreamDefaultReaderReadyGetter, nullptr } }, + { "read"_s, + static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::Function), + NoIntrinsic, + { HashTableValue::NativeFunctionType, readableStreamDefaultReaderRead, 0 } }, + { "releaseLock"_s, + static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::Function), + NoIntrinsic, + { HashTableValue::NativeFunctionType, readableStreamDefaultReaderReleaseLock, 0 } }, + { "cancel"_s, + static_cast(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::Function), + NoIntrinsic, + { HashTableValue::NativeFunctionType, readableStreamDefaultReaderCancel, 1 } }, +}; + +JSReadableStreamDefaultReaderPrototype* JSReadableStreamDefaultReaderPrototype::create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) +{ + JSReadableStreamDefaultReaderPrototype* ptr = new (NotNull, JSC::allocateCell(vm)) JSReadableStreamDefaultReaderPrototype(vm, globalObject, structure); + ptr->finishCreation(vm); + return ptr; +} + +void JSReadableStreamDefaultReaderPrototype::finishCreation(JSC::VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSReadableStreamDefaultReader::info(), JSReadableStreamDefaultReaderPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +// JS Bindings Implementation +JSC_DEFINE_HOST_FUNCTION(readableStreamDefaultReaderRead, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSReadableStreamDefaultReader* reader = jsDynamicCast(callFrame->thisValue()); + if (!reader) { + scope.throwException(globalObject, createTypeError(globalObject, "ReadableStreamDefaultReader.prototype.read called on incompatible object"_s)); + return {}; + } + + JSC::JSPromise* promise = reader->read(vm, globalObject); + RETURN_IF_EXCEPTION(scope, {}); + return JSC::JSValue::encode(promise); +} + +JSC_DEFINE_HOST_FUNCTION(readableStreamDefaultReaderReleaseLock, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSReadableStreamDefaultReader* reader = jsDynamicCast(callFrame->thisValue()); + if (!reader) { + scope.throwException(globalObject, createTypeError(globalObject, "ReadableStreamDefaultReader.prototype.releaseLock called on incompatible object"_s)); + return {}; + } + + reader->releaseLock(); + return JSValue::encode(jsUndefined()); +} + +JSC_DEFINE_CUSTOM_GETTER(readableStreamDefaultReaderClosedGetter, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSReadableStreamDefaultReader* reader = jsDynamicCast(JSValue::decode(thisValue)); + if (!reader) { + scope.throwException(globalObject, createTypeError(globalObject, "ReadableStreamDefaultReader.prototype.closed called on incompatible object"_s)); + return {}; + } + + return JSValue::encode(reader->closedPromise()); +} + +JSC_DEFINE_CUSTOM_GETTER(readableStreamDefaultReaderReadyGetter, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSReadableStreamDefaultReader* reader = jsDynamicCast(JSValue::decode(thisValue)); + if (!reader) { + scope.throwException(globalObject, createTypeError(globalObject, "ReadableStreamDefaultReader.prototype.ready called on incompatible object"_s)); + return {}; + } + + return JSValue::encode(reader->readyPromise()); +} + +JSC_DEFINE_HOST_FUNCTION(readableStreamDefaultReaderCancel, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSReadableStreamDefaultReader* reader = jsDynamicCast(callFrame->thisValue()); + if (!reader) { + scope.throwException(globalObject, createTypeError(globalObject, "ReadableStreamDefaultReader.prototype.cancel called on incompatible object"_s)); + return {}; + } + + JSValue reason = callFrame->argument(0); + if (!reader->isActive()) { + scope.throwException(globalObject, createTypeError(globalObject, "ReadableStreamDefaultReader.prototype.cancel called on released reader"_s)); + return {}; + } + + return JSValue::encode(reader->stream()->cancel(globalObject, reason)); +} + +} // namespace Bun diff --git a/src/bun.js/bindings/BunReadableStreamDefaultReaderPrototype.h b/src/bun.js/bindings/BunReadableStreamDefaultReaderPrototype.h new file mode 100644 index 0000000000..ce4840c3b0 --- /dev/null +++ b/src/bun.js/bindings/BunReadableStreamDefaultReaderPrototype.h @@ -0,0 +1,40 @@ +#pragma once + +#include "root.h" +#include +#include + +namespace Bun { + +using namespace JSC; + +class JSReadableStreamDefaultReaderPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + + static JSReadableStreamDefaultReaderPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure); + + DECLARE_INFO; + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableStreamDefaultReaderPrototype, Base); + return &vm.plainObjectSpace(); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSReadableStreamDefaultReaderPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&); +}; + +} // namespace Bun