diff options
author | 2023-09-07 04:58:44 -0700 | |
---|---|---|
committer | 2023-09-07 04:58:44 -0700 | |
commit | 57a06745a48093c25d0f4729ccea41a918d6427d (patch) | |
tree | ac2568d5c98918d6364d2a9667c164cd3f3b3867 /src/bun.js/bindings | |
parent | 4360ec83b4146e15344b304573795f084f86a7c2 (diff) | |
download | bun-57a06745a48093c25d0f4729ccea41a918d6427d.tar.gz bun-57a06745a48093c25d0f4729ccea41a918d6427d.tar.zst bun-57a06745a48093c25d0f4729ccea41a918d6427d.zip |
Progress for Next.js (#4468)
* L
* ipc
* asdfghjkl
* dfghjk
* it works!
* types
* patches for next.js
* sdfghj
* wsdfgn,./
* this
* yolo
* okay loser
* asdfghjk
* add some more APIs
* MESS
* sdfghjkl
* remove native events from streams
* stuff
* remove lazy(primordials) test
* debugging
* okay
* less fake extensions object
* fix `Buffer.toString()` args logic
* fix deserialize
* make tests work
* add test for `Buffer.toString` args
* Update server.zig
* remove test
* update test
* Update spawn-streaming-stdin.test.ts
* fix linux build
* Update fs.test.ts
* cli message improvements
* dfshaj
* Fix fs.watch bug maybe?
* remove
---------
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Diffstat (limited to 'src/bun.js/bindings')
-rw-r--r-- | src/bun.js/bindings/CommonJSModuleRecord.cpp | 8 | ||||
-rw-r--r-- | src/bun.js/bindings/ImportMetaObject.cpp | 14 | ||||
-rw-r--r-- | src/bun.js/bindings/JSBuffer.cpp | 67 | ||||
-rw-r--r-- | src/bun.js/bindings/JSReadableHelper.cpp | 263 | ||||
-rw-r--r-- | src/bun.js/bindings/JSReadableHelper.h | 13 | ||||
-rw-r--r-- | src/bun.js/bindings/JSReadableState.cpp | 426 | ||||
-rw-r--r-- | src/bun.js/bindings/JSReadableState.h | 154 | ||||
-rw-r--r-- | src/bun.js/bindings/Process.cpp | 78 | ||||
-rw-r--r-- | src/bun.js/bindings/Process.lut.h | 233 | ||||
-rw-r--r-- | src/bun.js/bindings/Serialization.cpp | 49 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.cpp | 32 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 64 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.h | 13 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.zig | 7 | ||||
-rw-r--r-- | src/bun.js/bindings/generated_classes.zig | 3 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/EventEmitter.h | 2 |
16 files changed, 406 insertions, 1020 deletions
diff --git a/src/bun.js/bindings/CommonJSModuleRecord.cpp b/src/bun.js/bindings/CommonJSModuleRecord.cpp index a1f5781d7..b94386ab3 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.cpp +++ b/src/bun.js/bindings/CommonJSModuleRecord.cpp @@ -230,7 +230,13 @@ void RequireFunctionPrototype::finishCreation(JSC::VM& vm) JSC::Identifier::fromString(vm, "main"_s), JSC::GetterSetter::create(vm, globalObject(), requireDotMainFunction, JSValue()), PropertyAttribute::Builtin | PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | 0); - this->putDirect(vm, JSC::Identifier::fromString(vm, "extensions"_s), constructEmptyObject(globalObject()), 0); + + auto extensions = constructEmptyObject(globalObject()); + extensions->putDirect(vm, JSC::Identifier::fromString(vm, ".js"_s), jsBoolean(true), 0); + extensions->putDirect(vm, JSC::Identifier::fromString(vm, ".json"_s), jsBoolean(true), 0); + extensions->putDirect(vm, JSC::Identifier::fromString(vm, ".node"_s), jsBoolean(true), 0); + + this->putDirect(vm, JSC::Identifier::fromString(vm, "extensions"_s), extensions, 0); } JSC_DEFINE_CUSTOM_GETTER(getterFilename, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp index 328b9f940..c53235824 100644 --- a/src/bun.js/bindings/ImportMetaObject.cpp +++ b/src/bun.js/bindings/ImportMetaObject.cpp @@ -239,6 +239,20 @@ extern "C" EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlobalOb RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {})); + if (!isESM) { + auto* global = jsDynamicCast<Zig::GlobalObject*>(globalObject); + if (LIKELY(global)) { + auto overrideHandler = global->m_nodeModuleOverriddenResolveFilename.get(); + if (UNLIKELY(overrideHandler)) { + ASSERT(overrideHandler.isCallable(globalObject)); + MarkedArgumentBuffer args; + args.append(moduleName); + args.append(from); + return JSValue::encode(JSC::call(globalObject, overrideHandler, JSC::getCallData(overrideHandler), JSC::jsUndefined(), args)); + } + } + } + auto result = Bun__resolveSync(globalObject, JSC::JSValue::encode(moduleName), JSValue::encode(from), isESM); if (!JSC::JSValue::decode(result).isString()) { diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 934fc9b6c..ad901b0e4 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -1429,12 +1429,12 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS { auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); - uint32_t offset = 0; - uint32_t length = castedThis->length(); - uint32_t byteLength = length; + uint32_t start = 0; + uint32_t end = castedThis->length(); + uint32_t byteLength = end; WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; - if (length == 0) + if (end == 0) return JSC::JSValue::encode(JSC::jsEmptyString(vm)); size_t argsCount = callFrame->argumentCount(); @@ -1443,66 +1443,33 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS JSC::JSValue arg2 = callFrame->argument(1); JSC::JSValue arg3 = callFrame->argument(2); - // This method could be called in following forms: - // - toString() - // - toString(encoding) - // - toString(encoding, start) - // - toString(encoding, start, end) - // - toString(offset, length) - // - toString(offset, length, encoding) if (argsCount == 0) - return jsBufferToString(vm, lexicalGlobalObject, castedThis, offset, length, encoding); + return jsBufferToString(vm, lexicalGlobalObject, castedThis, start, end, encoding); - if (arg1.isString()) { + if (!arg1.isUndefined()) { encoding = parseEncoding(lexicalGlobalObject, scope, arg1); RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); + } - if (!arg3.isUndefined()) { - // length is end - length = std::min(byteLength, static_cast<uint32_t>(arg3.toInt32(lexicalGlobalObject))); - RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); - } - - int32_t istart = 0; - - if (!arg2.isUndefined()) { - istart = arg2.toInt32(lexicalGlobalObject); - RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); - } + if (!arg2.isUndefined()) { + int32_t istart = arg2.toInt32(lexicalGlobalObject); + RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); if (istart < 0) { throwTypeError(lexicalGlobalObject, scope, "Start must be a positive integer"_s); return JSC::JSValue::encode(jsUndefined()); } - offset = static_cast<uint32_t>(istart); - length = (length > offset) ? (length - offset) : 0; - } else { - - int32_t ioffset = 0; - - if (!arg1.isUndefined()) { - ioffset = arg1.toInt32(lexicalGlobalObject); - RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); - } - - if (ioffset < 0) { - throwTypeError(lexicalGlobalObject, scope, "Offset must be a positive integer"_s); - return JSC::JSValue::encode(jsUndefined()); - } - offset = static_cast<uint32_t>(ioffset); - length = (length > offset) ? (length - offset) : 0; - - if (!arg3.isUndefined()) { - encoding = parseEncoding(lexicalGlobalObject, scope, arg3); - RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); - } + start = static_cast<uint32_t>(istart); + } - if (!arg2.isUndefined()) - length = std::min(length, static_cast<uint32_t>(arg2.toInt32(lexicalGlobalObject))); + if (!arg3.isUndefined()) { + // length is end + end = std::min(byteLength, static_cast<uint32_t>(arg3.toInt32(lexicalGlobalObject))); + RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); } - return jsBufferToString(vm, lexicalGlobalObject, castedThis, offset, length, encoding); + return jsBufferToString(vm, lexicalGlobalObject, castedThis, start, end > start ? end - start : 0, encoding); } // DOMJIT makes it slower! TODO: investigate why diff --git a/src/bun.js/bindings/JSReadableHelper.cpp b/src/bun.js/bindings/JSReadableHelper.cpp deleted file mode 100644 index 0c459f329..000000000 --- a/src/bun.js/bindings/JSReadableHelper.cpp +++ /dev/null @@ -1,263 +0,0 @@ -#include "JSReadableHelper.h" -#include "JSReadableState.h" -#include "JSBufferList.h" -#include "JSBuffer.h" -#include "JSEventEmitter.h" -#include "JSStringDecoder.h" -#include "JavaScriptCore/Lookup.h" -#include "JavaScriptCore/ObjectConstructor.h" -#include "ZigGlobalObject.h" -#include "JSDOMOperation.h" -#include "JSDOMAttribute.h" -#include "headers.h" -#include "JSDOMConvertEnumeration.h" -#include "JavaScriptCore/StrongInlines.h" -#include "BunClientData.h" - -namespace WebCore { -using namespace JSC; - -#define JSReadableHelper_EXTRACT_STREAM_STATE \ - VM& vm = lexicalGlobalObject->vm(); \ - auto throwScope = DECLARE_THROW_SCOPE(vm); \ - \ - if (callFrame->argumentCount() < 2) { \ - throwTypeError(lexicalGlobalObject, throwScope, "Not enough arguments"_s); \ - return JSValue::encode(jsUndefined()); \ - } \ - \ - JSObject* stream = callFrame->uncheckedArgument(0).toObject(lexicalGlobalObject); \ - RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); \ - JSReadableState* state = jsCast<JSReadableState*>(callFrame->uncheckedArgument(1)); \ - if (!state) { \ - throwTypeError(lexicalGlobalObject, throwScope, "Second argument not ReadableState"_s); \ - return JSValue::encode(jsUndefined()); \ - } - -static bool callRead(JSValue stream, JSFunction* read, JSC::MarkedArgumentBuffer&& args, JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, EventEmitter& emitter) -{ - WTF::NakedPtr<JSC::Exception> exceptionPtr; - JSC::CallData callData = JSC::getCallData(read); - JSValue ret = call(lexicalGlobalObject, read, callData, JSValue(stream), WTFMove(args), exceptionPtr); - if (auto* exception = exceptionPtr.get()) { - JSC::Identifier errorEventName = JSC::Identifier::fromString(vm, "error"_s); - if (emitter.hasEventListeners(errorEventName)) { - args.clear(); - JSValue val = exception->value(); - if (!val) { - val = jsUndefined(); - } - args.append(val); - emitter.emitForBindings(errorEventName, args); - } else { - reportException(lexicalGlobalObject, exception); - } - return true; - } - - return !ret.isUndefinedOrNull(); -} - -JSC_DEFINE_HOST_FUNCTION(jsReadable_maybeReadMore, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) -{ - JSReadableHelper_EXTRACT_STREAM_STATE - - auto clientData - = WebCore::clientData(vm); - auto readIdentifier = clientData->builtinNames().readPublicName(); - auto read = stream->get(lexicalGlobalObject, readIdentifier); - - auto callData = JSC::getCallData(read); - if (callData.type == CallData::Type::None) { - throwException(lexicalGlobalObject, throwScope, createNotAFunctionError(lexicalGlobalObject, read)); - return JSValue::encode({}); - } - - auto* jsEmitter = jsEventEmitterCastFast(vm, lexicalGlobalObject, stream); - RETURN_IF_EXCEPTION(throwScope, {}); - if (UNLIKELY(!jsEmitter)) { - throwTypeError(lexicalGlobalObject, throwScope, "Stream must be an EventEmitter"_s); - return JSValue::encode(JSValue {}); - } - auto& emitter = jsEmitter->wrapped(); - - while ( - !state->getBool(JSReadableState::reading) && !state->getBool(JSReadableState::ended) && (state->m_length < state->m_highWaterMark || (state->m_flowing > 0 && state->m_length == 0))) { - int64_t len = state->m_length; - MarkedArgumentBuffer args; - args.append(jsNumber(0)); - - callRead(stream, jsCast<JSFunction*>(read), WTFMove(args), vm, lexicalGlobalObject, emitter); - - if (len == state->m_length) - break; - } - RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined())); -} - -void flow(JSGlobalObject* lexicalGlobalObject, JSObject* streamObj, JSReadableState* state) -{ - VM& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - - auto clientData = WebCore::clientData(vm); - auto readIdentifier = clientData->builtinNames().readPublicName(); - auto read = streamObj->get(lexicalGlobalObject, readIdentifier); - - auto callData = JSC::getCallData(read); - if (callData.type == CallData::Type::None) { - throwException(lexicalGlobalObject, throwScope, createNotAFunctionError(lexicalGlobalObject, read)); - return; - } - - if (state->m_flowing > 0) { - WebCore::EventEmitter& emitter = jsEventEmitterCastFast(vm, lexicalGlobalObject, streamObj)->wrapped(); - - while (state->m_flowing > 0) { - - if (!callRead(streamObj, jsCast<JSFunction*>(read), MarkedArgumentBuffer(), vm, lexicalGlobalObject, emitter)) { - break; - } - } - } -} - -JSC_DEFINE_HOST_FUNCTION(jsReadable_resume, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) -{ - JSReadableHelper_EXTRACT_STREAM_STATE - - auto* jsEmitterWrap - = jsEventEmitterCastFast(vm, lexicalGlobalObject, stream); - - if (UNLIKELY(!jsEmitterWrap)) { - throwTypeError(lexicalGlobalObject, throwScope, "Stream must be an EventEmitter"_s); - return JSValue::encode(JSValue {}); - } - - auto& emitter = jsEmitterWrap->wrapped(); - auto clientData = WebCore::clientData(vm); - auto readIdentifier = clientData->builtinNames().readPublicName(); - - if (!state->getBool(JSReadableState::reading)) { - // stream.read(0) - MarkedArgumentBuffer args; - args.append(jsNumber(0)); - - callRead(stream, jsCast<JSFunction*>(stream->get(lexicalGlobalObject, readIdentifier)), WTFMove(args), vm, lexicalGlobalObject, emitter); - } - - state->setBool(JSReadableState::resumeScheduled, true); - // stream.emit('resume') - auto eventType = clientData->builtinNames().resumePublicName(); - MarkedArgumentBuffer args; - - emitter.emitForBindings(eventType, args); - - flow(lexicalGlobalObject, stream, state); - - if (state->m_flowing > 0 && !state->getBool(JSReadableState::reading)) { - // stream.read(0) - auto read = stream->get(lexicalGlobalObject, readIdentifier); - auto callData = JSC::getCallData(read); - if (callData.type == CallData::Type::None) { - throwException(lexicalGlobalObject, throwScope, createNotAFunctionError(lexicalGlobalObject, read)); - return JSValue::encode(jsUndefined()); - } - MarkedArgumentBuffer args; - args.append(jsNumber(0)); - callRead(stream, jsCast<JSFunction*>(read), WTFMove(args), vm, lexicalGlobalObject, emitter); - } - RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined())); -} - -EncodedJSValue emitReadable_(JSGlobalObject* lexicalGlobalObject, JSObject* stream, JSReadableState* state) -{ - VM& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - JSValue errored = state->m_errored.get(); - if (!state->getBool(JSReadableState::destroyed) && !errored.toBoolean(lexicalGlobalObject) && (state->m_length || state->getBool(JSReadableState::ended))) { - // stream.emit('readable') - auto clientData = WebCore::clientData(vm); - - auto eventType = clientData->builtinNames().readablePublicName(); - MarkedArgumentBuffer args; - auto* emitter - = jsEventEmitterCastFast(vm, lexicalGlobalObject, stream); - if (UNLIKELY(!emitter)) { - throwTypeError(lexicalGlobalObject, throwScope, "Stream must be an EventEmitter"_s); - return JSValue::encode(JSValue {}); - } - emitter->wrapped().emitForBindings(eventType, args); - - state->setBool(JSReadableState::emittedReadable, false); - } - - state->setBool(JSReadableState::needReadable, state->m_flowing <= 0 && !state->getBool(JSReadableState::ended) && state->m_length <= state->m_highWaterMark); - flow(lexicalGlobalObject, stream, state); - return JSValue::encode(jsUndefined()); -} - -JSC_DEFINE_HOST_FUNCTION(jsReadable_emitReadable_, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) -{ - JSReadableHelper_EXTRACT_STREAM_STATE - - emitReadable_(lexicalGlobalObject, stream, state); - - RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined())); -} - -EncodedJSValue emitReadable(JSGlobalObject* lexicalGlobalObject, JSObject* stream, JSReadableState* state) -{ - VM& vm = lexicalGlobalObject->vm(); - - state->setBool(JSReadableState::needReadable, false); - if (!state->getBool(JSReadableState::emittedReadable)) { - state->setBool(JSReadableState::emittedReadable, true); - Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); - globalObject->queueMicrotask(JSValue(globalObject->emitReadableNextTickFunction()), JSValue(stream), JSValue(state), JSValue {}, JSValue {}); - } - return JSValue::encode(jsUndefined()); -} - -JSC_DEFINE_HOST_FUNCTION(jsReadable_emitReadable, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) -{ - JSReadableHelper_EXTRACT_STREAM_STATE - - RELEASE_AND_RETURN(throwScope, emitReadable(lexicalGlobalObject, stream, state)); -} - -JSC_DEFINE_HOST_FUNCTION(jsReadable_onEofChunk, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) -{ - JSReadableHelper_EXTRACT_STREAM_STATE - - if (state->getBool(JSReadableState::ended)) - RELEASE_AND_RETURN(throwScope, JSValue::encode(jsUndefined())); - - auto decoder = jsDynamicCast<JSStringDecoder*>(state->m_decoder.get()); - if (decoder) { - JSString* chunk = jsDynamicCast<JSString*>(decoder->end(vm, lexicalGlobalObject, nullptr, 0)); - if (chunk && chunk->length()) { - auto buffer = jsDynamicCast<JSBufferList*>(state->m_buffer.get()); - if (!buffer) { - throwTypeError(lexicalGlobalObject, throwScope, "Not buffer on stream"_s); - return JSValue::encode(jsUndefined()); - } - buffer->push(vm, JSValue(chunk)); - state->m_length += state->getBool(JSReadableState::objectMode) ? 1 : chunk->length(); - } - } - - state->setBool(JSReadableState::ended, true); - - if (state->getBool(JSReadableState::sync)) { - RELEASE_AND_RETURN(throwScope, emitReadable(lexicalGlobalObject, stream, state)); - } else { - state->setBool(JSReadableState::needReadable, false); - state->setBool(JSReadableState::emittedReadable, true); - RELEASE_AND_RETURN(throwScope, emitReadable_(lexicalGlobalObject, stream, state)); - } -} - -#undef JSReadableHelper_EXTRACT_STREAM_STATE - -} // namespace WebCore diff --git a/src/bun.js/bindings/JSReadableHelper.h b/src/bun.js/bindings/JSReadableHelper.h deleted file mode 100644 index 3e2554c2b..000000000 --- a/src/bun.js/bindings/JSReadableHelper.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "root.h" - -namespace WebCore { - -JSC_DECLARE_HOST_FUNCTION(jsReadable_maybeReadMore); -JSC_DECLARE_HOST_FUNCTION(jsReadable_resume); -JSC_DECLARE_HOST_FUNCTION(jsReadable_emitReadable); -JSC_DECLARE_HOST_FUNCTION(jsReadable_onEofChunk); -JSC_DECLARE_HOST_FUNCTION(jsReadable_emitReadable_); - -} // namespace WebCore diff --git a/src/bun.js/bindings/JSReadableState.cpp b/src/bun.js/bindings/JSReadableState.cpp deleted file mode 100644 index 1f3a36def..000000000 --- a/src/bun.js/bindings/JSReadableState.cpp +++ /dev/null @@ -1,426 +0,0 @@ -#include "JSReadableState.h" -#include "JSBufferList.h" -#include "JSBuffer.h" -#include "JavaScriptCore/Lookup.h" -#include "JavaScriptCore/ObjectConstructor.h" -#include "ZigGlobalObject.h" -#include "JSDOMOperation.h" -#include "JSDOMAttribute.h" -#include "headers.h" -#include "JSDOMConvertEnumeration.h" -#include "BunClientData.h" - -namespace WebCore { - -using namespace JSC; - -static JSC_DECLARE_CUSTOM_GETTER(jsReadableState_pipesCount); - -int64_t getHighWaterMark(JSC::VM& vm, JSC::JSGlobalObject* globalObject, bool isDuplex, JSObject* options) -{ - auto throwScope = DECLARE_THROW_SCOPE(vm); - - // We must use getIfPropertyExists because: - // - it might be a getter - // - it might be from a super class - auto* clientData = WebCore::clientData(vm); - if (JSValue highWaterMarkVal = options->getIfPropertyExists(globalObject, clientData->builtinNames().highWaterMarkPublicName())) { - if (isDuplex && (highWaterMarkVal.isUndefined() || highWaterMarkVal.isNull())) { - highWaterMarkVal = options->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "readableObjectMode"_s)); - } - - if (highWaterMarkVal && highWaterMarkVal.isNumber()) { - return highWaterMarkVal.toInt32(globalObject); - } - } - - return -1; -} - -void JSReadableState::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject, bool isDuplex, JSObject* options) -{ - Base::finishCreation(vm); - - if (options != nullptr) { - JSC::JSValue objectModeVal = options->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "objectMode"_s)); - if (isDuplex && !objectModeVal) { - objectModeVal = options->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "readableObjectMode"_s)); - } - if (objectModeVal && objectModeVal.toBoolean(globalObject)) - setBool(JSReadableState::Mask::objectMode, true); - } - - m_highWaterMark = getBool( - JSReadableState::Mask::objectMode) - ? 16 - : 16 * 1024; // default value - - if (options != nullptr) { - int64_t customHightWaterMark = getHighWaterMark(vm, globalObject, isDuplex, options); - if (customHightWaterMark >= 0) - m_highWaterMark = customHightWaterMark; - } - - m_buffer.set(vm, this, JSBufferList::create(vm, globalObject, reinterpret_cast<Zig::GlobalObject*>(globalObject)->JSBufferListStructure())); - m_pipes.set(vm, this, JSC::constructEmptyArray(globalObject, nullptr, 0)); - - if (options != nullptr) { - JSC::JSValue emitCloseVal = options->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "emitClose"_s)); - if (!emitCloseVal || emitCloseVal.toBoolean(globalObject)) - setBool(JSReadableState::Mask::emitClose, true); - // Has it been destroyed. - JSC::JSValue autoDestroyVal = options->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "autoDestroy"_s)); - if (!autoDestroyVal || autoDestroyVal.toBoolean(globalObject)) - setBool(JSReadableState::Mask::autoDestroy, true); - } else { - setBool(JSReadableState::Mask::emitClose, true); - setBool(JSReadableState::Mask::autoDestroy, true); - } - - // Indicates whether the stream has finished destroying. - m_errored.set(vm, this, JSC::jsNull()); - - // Ref the piped dest which we need a drain event on it - // type: null | Writable | Set<Writable>. - if (options == nullptr) { - m_defaultEncoding.set(vm, this, JSC::jsString(vm, WTF::String("utf8"_s))); - } else { - if (JSC::JSValue defaultEncodingVal = getIfPropertyExists(globalObject, PropertyName(JSC::Identifier::fromString(vm, "defaultEncoding"_s)))) { - m_defaultEncoding.set(vm, this, defaultEncodingVal); - } else { - m_defaultEncoding.set(vm, this, JSC::jsString(vm, WTF::String("utf8"_s))); - } - } - - m_awaitDrainWriters.set(vm, this, JSC::jsNull()); - JSValue decodeValue = JSC::jsNull(); - JSValue encodingValue = JSC::jsNull(); - - if (options != nullptr) { - JSC::JSValue encodingVal = options->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "encoding"_s)); - if (encodingVal && encodingVal.isString()) { - auto constructor = reinterpret_cast<Zig::GlobalObject*>(globalObject)->JSStringDecoder(); - auto constructData = JSC::getConstructData(constructor); - MarkedArgumentBuffer args; - args.append(encodingVal); - JSObject* decoder = JSC::construct(globalObject, constructor, constructData, args); - decodeValue = decoder; - encodingValue = encodingVal; - } - } - - m_decoder.set(vm, this, decodeValue); - m_encoding.set(vm, this, encodingValue); - - // ReadableState.constructed is set to false during construction when a _construct method is implemented - // this is here so that the ReadableState behavior tracks the behavior in node, and that calling Readable.read - // will work when we return early from construct because there is no Readable._construct implemented - // See: https://github.com/nodejs/node/blob/main/lib/internal/streams/readable.js - setBool(JSReadableState::Mask::constructed, true); -} - -const JSC::ClassInfo JSReadableState::s_info = { "ReadableState"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableState) }; - -JSC::GCClient::IsoSubspace* JSReadableState::subspaceForImpl(JSC::VM& vm) -{ - return WebCore::subspaceForImpl<JSReadableState, UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForReadableState.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForReadableState = std::forward<decltype(space)>(space); }, - [](auto& spaces) { return spaces.m_subspaceForReadableState.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForReadableState = std::forward<decltype(space)>(space); }); -} - -template<typename Visitor> -void JSReadableState::visitChildrenImpl(JSCell* cell, Visitor& visitor) -{ - JSReadableState* state = jsCast<JSReadableState*>(cell); - ASSERT_GC_OBJECT_INHERITS(state, info()); - Base::visitChildren(state, visitor); - visitor.append(state->m_buffer); - visitor.append(state->m_pipes); - visitor.append(state->m_errored); - visitor.append(state->m_defaultEncoding); - visitor.append(state->m_awaitDrainWriters); - visitor.append(state->m_decoder); - visitor.append(state->m_encoding); -} -DEFINE_VISIT_CHILDREN(JSReadableState); - -STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableStatePrototype, JSReadableStatePrototype::Base); - -JSC_DEFINE_CUSTOM_GETTER(jsReadableState_pipesCount, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - auto& vm = JSC::getVM(lexicalGlobalObject); - auto throwScope = DECLARE_THROW_SCOPE(vm); - JSReadableState* state = JSC::jsDynamicCast<JSReadableState*>(JSValue::decode(thisValue)); - if (!state) { - RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined())); - } - JSArray* pipes = JSC::jsDynamicCast<JSArray*>(state->m_pipes.get()); - if (!pipes) { - RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined())); - } - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsNumber(pipes->length()))); -} - -#define JSReadableState_NULLABLE_BOOLEAN_GETTER_SETTER(NAME) \ - static JSC_DECLARE_CUSTOM_GETTER(jsReadableState_##NAME); \ - JSC_DEFINE_CUSTOM_GETTER(jsReadableState_##NAME, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) \ - { \ - auto& vm = JSC::getVM(lexicalGlobalObject); \ - auto throwScope = DECLARE_THROW_SCOPE(vm); \ - JSReadableState* state = JSC::jsDynamicCast<JSReadableState*>(JSValue::decode(thisValue)); \ - if (!state) { \ - RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined())); \ - } \ - if (state->m_##NAME == 0) \ - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsNull())); \ - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsBoolean(state->m_##NAME > 0))); \ - } \ - static JSC_DECLARE_CUSTOM_SETTER(setJSReadableState_##NAME); \ - JSC_DEFINE_CUSTOM_SETTER(setJSReadableState_##NAME, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName)) \ - { \ - auto& vm = JSC::getVM(lexicalGlobalObject); \ - auto throwScope = DECLARE_THROW_SCOPE(vm); \ - JSReadableState* state = JSC::jsDynamicCast<JSReadableState*>(JSValue::decode(thisValue)); \ - if (!state) { \ - RETURN_IF_EXCEPTION(throwScope, false); \ - } \ - auto value = JSC::JSValue::decode(encodedValue); \ - state->m_##NAME = value.isNull() ? 0 : value.toBoolean(lexicalGlobalObject) ? 1 \ - : -1; \ - RELEASE_AND_RETURN(throwScope, true); \ - } - -JSReadableState_NULLABLE_BOOLEAN_GETTER_SETTER(paused) - JSReadableState_NULLABLE_BOOLEAN_GETTER_SETTER(flowing) - -#undef JSReadableState_NULLABLE_BOOLEAN_GETTER_SETTER - -#define JSReadableState_NUMBER_GETTER_SETTER(NAME) \ - static JSC_DECLARE_CUSTOM_GETTER(jsReadableState_##NAME); \ - JSC_DEFINE_CUSTOM_GETTER(jsReadableState_##NAME, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) \ - { \ - auto& vm = JSC::getVM(lexicalGlobalObject); \ - auto throwScope = DECLARE_THROW_SCOPE(vm); \ - JSReadableState* state = JSC::jsDynamicCast<JSReadableState*>(JSValue::decode(thisValue)); \ - if (!state) { \ - RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined())); \ - } \ - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsNumber(state->m_##NAME))); \ - } \ - \ - static JSC_DECLARE_CUSTOM_SETTER(setJSReadableState_##NAME); \ - JSC_DEFINE_CUSTOM_SETTER(setJSReadableState_##NAME, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName)) \ - { \ - auto& vm = JSC::getVM(lexicalGlobalObject); \ - auto throwScope = DECLARE_THROW_SCOPE(vm); \ - JSReadableState* state = JSC::jsDynamicCast<JSReadableState*>(JSValue::decode(thisValue)); \ - if (!state) { \ - RETURN_IF_EXCEPTION(throwScope, false); \ - } \ - state->m_##NAME = JSC::JSValue::decode(encodedValue).toNumber(lexicalGlobalObject); \ - RETURN_IF_EXCEPTION(throwScope, false); \ - RELEASE_AND_RETURN(throwScope, true); \ - } - - JSReadableState_NUMBER_GETTER_SETTER(length) - JSReadableState_NUMBER_GETTER_SETTER(highWaterMark) - -#undef JSReadableState_NUMBER_GETTER_SETTER - -#define JSReadableState_BOOLEAN_GETTER_SETTER(NAME) \ - static JSC_DECLARE_CUSTOM_GETTER(jsReadableState_##NAME); \ - JSC_DEFINE_CUSTOM_GETTER(jsReadableState_##NAME, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) \ - { \ - auto& vm = JSC::getVM(lexicalGlobalObject); \ - auto throwScope = DECLARE_THROW_SCOPE(vm); \ - JSReadableState* state = JSC::jsDynamicCast<JSReadableState*>(JSValue::decode(thisValue)); \ - if (!state) { \ - RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined())); \ - } \ - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsBoolean(state->getBool(JSReadableState::Mask::NAME)))); \ - } \ - \ - static JSC_DECLARE_CUSTOM_SETTER(setJSReadableState_##NAME); \ - JSC_DEFINE_CUSTOM_SETTER(setJSReadableState_##NAME, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName)) \ - { \ - auto& vm = JSC::getVM(lexicalGlobalObject); \ - auto throwScope = DECLARE_THROW_SCOPE(vm); \ - JSReadableState* state = JSC::jsDynamicCast<JSReadableState*>(JSValue::decode(thisValue)); \ - if (!state) { \ - RETURN_IF_EXCEPTION(throwScope, false); \ - } \ - state->setBool(JSReadableState::Mask::NAME, JSC::JSValue::decode(encodedValue).toBoolean(lexicalGlobalObject)); \ - RELEASE_AND_RETURN(throwScope, true); \ - } - - JSReadableState_BOOLEAN_GETTER_SETTER(objectMode) - JSReadableState_BOOLEAN_GETTER_SETTER(ended) - JSReadableState_BOOLEAN_GETTER_SETTER(endEmitted) - JSReadableState_BOOLEAN_GETTER_SETTER(reading) - JSReadableState_BOOLEAN_GETTER_SETTER(constructed) - JSReadableState_BOOLEAN_GETTER_SETTER(sync) - JSReadableState_BOOLEAN_GETTER_SETTER(needReadable) - JSReadableState_BOOLEAN_GETTER_SETTER(emittedReadable) - JSReadableState_BOOLEAN_GETTER_SETTER(readableListening) - JSReadableState_BOOLEAN_GETTER_SETTER(resumeScheduled) - JSReadableState_BOOLEAN_GETTER_SETTER(errorEmitted) - JSReadableState_BOOLEAN_GETTER_SETTER(emitClose) - JSReadableState_BOOLEAN_GETTER_SETTER(autoDestroy) - JSReadableState_BOOLEAN_GETTER_SETTER(destroyed) - JSReadableState_BOOLEAN_GETTER_SETTER(closed) - JSReadableState_BOOLEAN_GETTER_SETTER(closeEmitted) - JSReadableState_BOOLEAN_GETTER_SETTER(multiAwaitDrain) - JSReadableState_BOOLEAN_GETTER_SETTER(readingMore) - JSReadableState_BOOLEAN_GETTER_SETTER(dataEmitted) - -#undef JSReadableState_BOOLEAN_GETTER_SETTER - -#define JSReadableState_JSVALUE_GETTER_SETTER(NAME) \ - static JSC_DECLARE_CUSTOM_GETTER(jsReadableState_##NAME); \ - JSC_DEFINE_CUSTOM_GETTER(jsReadableState_##NAME, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) \ - { \ - auto& vm = JSC::getVM(lexicalGlobalObject); \ - auto throwScope = DECLARE_THROW_SCOPE(vm); \ - JSReadableState* state = JSC::jsDynamicCast<JSReadableState*>(JSValue::decode(thisValue)); \ - if (!state) { \ - RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined())); \ - } \ - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(state->m_##NAME.get())); \ - } \ - static JSC_DECLARE_CUSTOM_SETTER(setJSReadableState_##NAME); \ - JSC_DEFINE_CUSTOM_SETTER(setJSReadableState_##NAME, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName)) \ - { \ - auto& vm = JSC::getVM(lexicalGlobalObject); \ - auto throwScope = DECLARE_THROW_SCOPE(vm); \ - JSReadableState* state = JSC::jsDynamicCast<JSReadableState*>(JSValue::decode(thisValue)); \ - if (!state) { \ - RETURN_IF_EXCEPTION(throwScope, false); \ - } \ - auto value = JSC::JSValue::decode(encodedValue); \ - state->m_##NAME.set(vm, state, value); \ - RELEASE_AND_RETURN(throwScope, true); \ - } - - JSReadableState_JSVALUE_GETTER_SETTER(buffer) - JSReadableState_JSVALUE_GETTER_SETTER(pipes) - JSReadableState_JSVALUE_GETTER_SETTER(errored) - JSReadableState_JSVALUE_GETTER_SETTER(defaultEncoding) - JSReadableState_JSVALUE_GETTER_SETTER(awaitDrainWriters) - JSReadableState_JSVALUE_GETTER_SETTER(decoder) - JSReadableState_JSVALUE_GETTER_SETTER(encoding) - -#undef JSReadableState_JSVALUE_GETTER_SETTER - -#define JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(NAME) \ - { \ -#NAME ""_s, static_cast < unsigned>(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, \ - { \ - HashTableValue::GetterSetterType, jsReadableState_##NAME, setJSReadableState_##NAME \ - } \ - } - - /* Hash table for prototype */ - static const HashTableValue JSReadableStatePrototypeTableValues[] - = { - { "pipesCount"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, jsReadableState_pipesCount, 0 } }, - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(paused), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(flowing), - - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(objectMode), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(ended), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(endEmitted), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(reading), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(constructed), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(sync), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(needReadable), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(emittedReadable), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(readableListening), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(resumeScheduled), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(errorEmitted), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(emitClose), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(autoDestroy), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(destroyed), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(closed), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(closeEmitted), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(multiAwaitDrain), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(readingMore), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(dataEmitted), - - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(length), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(highWaterMark), - - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(buffer), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(pipes), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(errored), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(defaultEncoding), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(awaitDrainWriters), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(decoder), - JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(encoding), - }; - -#undef JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE - -void JSReadableStatePrototype::finishCreation(VM& vm, JSC::JSGlobalObject* globalThis) -{ - Base::finishCreation(vm); - reifyStaticProperties(vm, JSReadableState::info(), JSReadableStatePrototypeTableValues, *this); - JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); -} - -const ClassInfo JSReadableStatePrototype::s_info = { "ReadableState"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableStatePrototype) }; - -void JSReadableStateConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSReadableStatePrototype* prototype) -{ - Base::finishCreation(vm, 0, "ReadableState"_s, PropertyAdditionMode::WithoutStructureTransition); - putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - ASSERT(inherits(info())); -} - -JSReadableStateConstructor* JSReadableStateConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSReadableStatePrototype* prototype) -{ - JSReadableStateConstructor* ptr = new (NotNull, JSC::allocateCell<JSReadableStateConstructor>(vm)) JSReadableStateConstructor(vm, structure, construct); - ptr->finishCreation(vm, globalObject, prototype); - return ptr; -} - -JSC::EncodedJSValue JSReadableStateConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) -{ - JSC::VM& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - if (callFrame->argumentCount() < 3) { - throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); - return JSValue::encode(jsUndefined()); - } - JSValue optionsVal = callFrame->uncheckedArgument(0); - JSValue streamVal = callFrame->uncheckedArgument(1); - JSValue isDuplexVal = callFrame->uncheckedArgument(2); - - bool isDuplex; - if (!isDuplexVal.isBoolean()) { - // change this to `stream instanceof Duplex` after native Duplex is implemented. - JSC::throwTypeError(lexicalGlobalObject, throwScope, "isDuplex should be boolean"_s); - return JSValue::encode(jsUndefined()); - } - isDuplex = isDuplexVal.toBoolean(lexicalGlobalObject); - RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); - JSObject* options = nullptr; - if (optionsVal && optionsVal.isObject()) { - options = optionsVal.toObject(lexicalGlobalObject); - } - RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); - - JSReadableState* stringDecoder = JSReadableState::create( - vm, lexicalGlobalObject, reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject)->JSReadableStateStructure(), isDuplex, options); - return JSC::JSValue::encode(stringDecoder); -} - -void JSReadableStateConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSReadableStatePrototype* prototype) -{ -} - -const ClassInfo JSReadableStateConstructor::s_info = { "ReadableState"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableStateConstructor) }; - -} // namespace Zig diff --git a/src/bun.js/bindings/JSReadableState.h b/src/bun.js/bindings/JSReadableState.h deleted file mode 100644 index c67baebad..000000000 --- a/src/bun.js/bindings/JSReadableState.h +++ /dev/null @@ -1,154 +0,0 @@ -#pragma once - -#include "root.h" -#include "BufferEncodingType.h" - -namespace WebCore { -using namespace JSC; - -class JSReadableState : public JSC::JSDestructibleObject { - using Base = JSC::JSDestructibleObject; - -public: - JSReadableState(JSC::VM& vm, JSC::Structure* structure) - : Base(vm, structure) - , m_paused(0) - { - } - - DECLARE_VISIT_CHILDREN; - DECLARE_INFO; - - static constexpr unsigned StructureFlags = Base::StructureFlags; - - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return subspaceForImpl(vm); - } - - static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm); - - 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()); - } - - static JSReadableState* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, bool isDuplex, JSObject* options) - { - JSReadableState* accessor = new (NotNull, JSC::allocateCell<JSReadableState>(vm)) JSReadableState(vm, structure); - accessor->finishCreation(vm, globalObject, isDuplex, options); - return accessor; - } - - void finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject, bool isDuplex, JSObject* options); - static void destroy(JSCell*) {} - - enum Mask : uint32_t { - objectMode = 1 << 0, - emitClose = 1 << 1, - autoDestroy = 1 << 2, - ended = 1 << 3, - endEmitted = 1 << 4, - reading = 1 << 5, - constructed = 1 << 6, - sync = 1 << 7, - needReadable = 1 << 8, - emittedReadable = 1 << 9, - readableListening = 1 << 10, - resumeScheduled = 1 << 11, - errorEmitted = 1 << 12, - destroyed = 1 << 13, - closed = 1 << 14, - closeEmitted = 1 << 15, - multiAwaitDrain = 1 << 16, - readingMore = 1 << 17, - dataEmitted = 1 << 18, - }; - - constexpr bool getBool(Mask mask) { return m_bools.contains(mask); } - constexpr void setBool(Mask mask, bool val) - { - m_bools.set(mask, val); - } - - // 0 for null, 1 for true, -1 for false - int8_t m_paused = 0; - int8_t m_flowing = 0; - - WTF::OptionSet<Mask> m_bools; - - int64_t m_length = 0; - int64_t m_highWaterMark; - - mutable WriteBarrier<Unknown> m_buffer; - mutable WriteBarrier<Unknown> m_pipes; - mutable WriteBarrier<Unknown> m_errored; - mutable WriteBarrier<Unknown> m_defaultEncoding; - mutable WriteBarrier<Unknown> m_awaitDrainWriters; - mutable WriteBarrier<Unknown> m_decoder; - mutable WriteBarrier<Unknown> m_encoding; -}; - -class JSReadableStatePrototype : public JSC::JSNonFinalObject { -public: - using Base = JSC::JSNonFinalObject; - static JSReadableStatePrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSReadableStatePrototype* ptr = new (NotNull, JSC::allocateCell<JSReadableStatePrototype>(vm)) JSReadableStatePrototype(vm, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - 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: - JSReadableStatePrototype(JSC::VM& vm, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); -}; - -class JSReadableStateConstructor final : public JSC::InternalFunction { -public: - using Base = JSC::InternalFunction; - static JSReadableStateConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSReadableStatePrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - 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()); - } - - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSReadableStatePrototype* prototype); - - // Must be defined for each specialization class. - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); - DECLARE_EXPORT_INFO; - -private: - JSReadableStateConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) - : Base(vm, structure, nativeFunction, nativeFunction) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSReadableStatePrototype* prototype); -}; - -} diff --git a/src/bun.js/bindings/Process.cpp b/src/bun.js/bindings/Process.cpp index 252d00075..282cf6460 100644 --- a/src/bun.js/bindings/Process.cpp +++ b/src/bun.js/bindings/Process.cpp @@ -76,7 +76,10 @@ extern "C" uint8_t Bun__getExitCode(void*); extern "C" uint8_t Bun__setExitCode(void*, uint8_t); extern "C" void* Bun__getVM(); extern "C" Zig::GlobalObject* Bun__getDefaultGlobal(); +extern "C" bool Bun__GlobalObject__hasIPC(JSGlobalObject*); extern "C" const char* Bun__githubURL; +extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__Process__send); +extern "C" JSC_DECLARE_HOST_FUNCTION(Bun__Process__disconnect); static void dispatchExitInternal(JSC::JSGlobalObject* globalObject, Process* process, int exitCode) { @@ -525,6 +528,21 @@ static void loadSignalNumberMap() static void onDidChangeListeners(EventEmitter& eventEmitter, const Identifier& eventName, bool isAdded) { + if (eventName.string() == "message"_s) { + if (isAdded) { + if (Bun__GlobalObject__hasIPC(eventEmitter.scriptExecutionContext()->jsGlobalObject()) + && eventEmitter.listenerCount(eventName) == 1) { + eventEmitter.scriptExecutionContext()->refEventLoop(); + eventEmitter.m_hasIPCRef = true; + } + } else { + if (eventEmitter.listenerCount(eventName) == 0 && eventEmitter.m_hasIPCRef) { + eventEmitter.scriptExecutionContext()->unrefEventLoop(); + } + } + return; + } + loadSignalNumberMap(); static std::once_flag signalNumberToNameMapOnceFlag; @@ -739,6 +757,20 @@ JSC_DEFINE_CUSTOM_SETTER(setProcessExitCode, (JSC::JSGlobalObject * lexicalGloba return true; } +JSC_DEFINE_CUSTOM_GETTER(processConnected, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName name)) +{ + Process* process = jsDynamicCast<Process*>(JSValue::decode(thisValue)); + if (!process) { + return JSValue::encode(jsUndefined()); + } + + return JSValue::encode(jsBoolean(Bun__GlobalObject__hasIPC(process->globalObject()))); +} +JSC_DEFINE_CUSTOM_SETTER(setProcessConnected, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, JSC::PropertyName)) +{ + return false; +} + static JSValue constructVersions(VM& vm, JSObject* processObject) { auto* globalObject = processObject->globalObject(); @@ -912,6 +944,26 @@ static JSValue constructStdin(VM& vm, JSObject* processObject) RELEASE_AND_RETURN(scope, result); } +static JSValue constructProcessSend(VM& vm, JSObject* processObject) +{ + auto* globalObject = processObject->globalObject(); + if (Bun__GlobalObject__hasIPC(globalObject)) { + return JSC::JSFunction::create(vm, globalObject, 1, String("send"_s), Bun__Process__send, ImplementationVisibility::Public); + } else { + return jsNumber(4); + } +} + +static JSValue constructProcessDisconnect(VM& vm, JSObject* processObject) +{ + auto* globalObject = processObject->globalObject(); + if (Bun__GlobalObject__hasIPC(globalObject)) { + return JSC::JSFunction::create(vm, globalObject, 1, String("disconnect"_s), Bun__Process__disconnect, ImplementationVisibility::Public); + } else { + return jsUndefined(); + } +} + static JSValue constructPid(VM& vm, JSObject* processObject) { return jsNumber(getpid()); @@ -1687,6 +1739,29 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill, return JSValue::encode(jsUndefined()); } +extern "C" void Process__emitMessageEvent(Zig::GlobalObject* global, EncodedJSValue value) +{ + auto* process = static_cast<Process*>(global->processObject()); + auto& vm = global->vm(); + auto ident = Identifier::fromString(vm, "message"_s); + if (process->wrapped().hasEventListeners(ident)) { + JSC::MarkedArgumentBuffer args; + args.append(JSValue::decode(value)); + process->wrapped().emit(ident, args); + } +} + +extern "C" void Process__emitDisconnectEvent(Zig::GlobalObject* global) +{ + auto* process = static_cast<Process*>(global->processObject()); + auto& vm = global->vm(); + auto ident = Identifier::fromString(vm, "disconnect"_s); + if (process->wrapped().hasEventListeners(ident)) { + JSC::MarkedArgumentBuffer args; + process->wrapped().emit(ident, args); + } +} + /* Source for Process.lut.h @begin processObjectTable abort Process_functionAbort Function 1 @@ -1699,9 +1774,11 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill, browser constructBrowser PropertyCallback chdir Process_functionChdir Function 1 config constructProcessConfigObject PropertyCallback + connected processConnected CustomAccessor cpuUsage Process_functionCpuUsage Function 1 cwd Process_functionCwd Function 1 debugPort processDebugPort CustomAccessor + disconnect constructProcessDisconnect PropertyCallback dlopen Process_functionDlopen Function 1 emitWarning Process_emitWarning Function 1 env constructEnv PropertyCallback @@ -1731,6 +1808,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill, release constructProcessReleaseObject PropertyCallback revision constructRevision PropertyCallback setSourceMapsEnabled Process_stubEmptyFunction Function 1 + send constructProcessSend PropertyCallback stderr constructStderr PropertyCallback stdin constructStdin PropertyCallback stdout constructStdout PropertyCallback diff --git a/src/bun.js/bindings/Process.lut.h b/src/bun.js/bindings/Process.lut.h index 4086fb19e..dda54ff01 100644 --- a/src/bun.js/bindings/Process.lut.h +++ b/src/bun.js/bindings/Process.lut.h @@ -1,6 +1,6 @@ // File generated via `make generate-builtins` -static const struct CompactHashIndex processObjectTableIndex[143] = { - { 44, -1 }, +static const struct CompactHashIndex processObjectTableIndex[267] = { + { 47, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -11,13 +11,12 @@ static const struct CompactHashIndex processObjectTableIndex[143] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 15, 129 }, { -1, -1 }, { -1, -1 }, - { 18, 139 }, { -1, -1 }, - { 46, -1 }, + { 20, -1 }, { -1, -1 }, + { 49, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -33,37 +32,166 @@ static const struct CompactHashIndex processObjectTableIndex[143] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 3, 142 }, - { 1, 128 }, { -1, -1 }, - { 60, -1 }, { -1, -1 }, - { 10, -1 }, + { 8, -1 }, + { -1, -1 }, + { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 32, -1 }, { -1, -1 }, { -1, -1 }, + { 34, -1 }, { -1, -1 }, { -1, -1 }, - { 53, -1 }, - { 27, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 29, -1 }, + { 13, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 59, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 55, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 43, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 0, -1 }, + { 28, -1 }, + { 37, -1 }, + { 42, -1 }, + { -1, -1 }, + { 25, -1 }, { 12, -1 }, { -1, -1 }, + { -1, -1 }, + { 62, -1 }, + { -1, -1 }, + { -1, -1 }, + { 33, -1 }, + { 44, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 26, -1 }, + { -1, -1 }, + { -1, -1 }, + { 22, -1 }, + { -1, -1 }, + { 5, -1 }, + { -1, -1 }, + { 64, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 27, 261 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 23, 262 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 50, 265 }, + { -1, -1 }, { 19, -1 }, { -1, -1 }, - { 14, 138 }, { -1, -1 }, - { 37, -1 }, { -1, -1 }, - { 39, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 17, 257 }, + { -1, -1 }, + { 14, -1 }, + { 57, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 3, 266 }, + { 1, -1 }, + { -1, -1 }, + { 63, -1 }, + { -1, -1 }, + { 11, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, { 56, -1 }, - { 36, -1 }, - { 6, 140 }, { -1, -1 }, - { 52, -1 }, + { -1, -1 }, + { -1, -1 }, + { 10, 256 }, + { -1, -1 }, + { 16, 263 }, + { -1, -1 }, + { 39, -1 }, + { -1, -1 }, + { 41, -1 }, + { -1, -1 }, + { 38, -1 }, + { 6, 264 }, + { -1, -1 }, + { -1, -1 }, { 4, -1 }, - { 48, -1 }, + { 51, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -75,77 +203,73 @@ static const struct CompactHashIndex processObjectTableIndex[143] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 41, -1 }, { -1, -1 }, - { 29, 133 }, { -1, -1 }, - { 0, -1 }, - { 26, 136 }, - { 16, 130 }, - { 40, -1 }, + { 31, 260 }, + { -1, -1 }, + { -1, -1 }, + { 48, -1 }, + { 18, 258 }, + { -1, -1 }, { -1, -1 }, - { 23, -1 }, - { 11, -1 }, { -1, -1 }, { -1, -1 }, - { 59, -1 }, { -1, -1 }, { -1, -1 }, - { 31, 137 }, { -1, -1 }, - { 30, -1 }, - { 22, -1 }, { -1, -1 }, { -1, -1 }, + { 53, -1 }, + { -1, -1 }, + { 32, -1 }, { 24, -1 }, { -1, -1 }, { -1, -1 }, - { 20, -1 }, { -1, -1 }, - { 5, -1 }, { -1, -1 }, - { 61, -1 }, - { 49, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 13, 131 }, + { -1, -1 }, + { -1, -1 }, + { 52, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 15, 259 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { 9, -1 }, - { 25, 134 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 21, 135 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 47, 141 }, { -1, -1 }, - { 17, -1 }, - { 8, -1 }, - { 28, -1 }, - { 33, 132 }, - { 34, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 21, -1 }, + { 30, -1 }, { 35, -1 }, - { 38, -1 }, - { 42, -1 }, - { 43, -1 }, + { 36, -1 }, + { 40, -1 }, { 45, -1 }, - { 50, -1 }, - { 51, -1 }, + { 46, -1 }, { 54, -1 }, - { 55, -1 }, - { 57, -1 }, { 58, -1 }, + { 60, -1 }, + { 61, -1 }, }; -static const struct HashTableValue processObjectTableValues[62] = { +static const struct HashTableValue processObjectTableValues[65] = { { "abort"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionAbort, 1 } }, { "allowedNodeEnvironmentFlags"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, Process_stubEmptySet } }, { "arch"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructArch } }, @@ -156,9 +280,11 @@ static const struct HashTableValue processObjectTableValues[62] = { { "browser"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructBrowser } }, { "chdir"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionChdir, 1 } }, { "config"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructProcessConfigObject } }, + { "connected"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, processConnected, setProcessConnected } }, { "cpuUsage"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionCpuUsage, 1 } }, { "cwd"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionCwd, 1 } }, { "debugPort"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, processDebugPort, setProcessDebugPort } }, + { "disconnect"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructProcessDisconnect } }, { "dlopen"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionDlopen, 1 } }, { "emitWarning"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_emitWarning, 1 } }, { "env"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructEnv } }, @@ -188,6 +314,7 @@ static const struct HashTableValue processObjectTableValues[62] = { { "release"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructProcessReleaseObject } }, { "revision"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructRevision } }, { "setSourceMapsEnabled"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_stubEmptyFunction, 1 } }, + { "send"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructProcessSend } }, { "stderr"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructStderr } }, { "stdin"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructStdin } }, { "stdout"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructStdout } }, @@ -211,4 +338,4 @@ static const struct HashTableValue processObjectTableValues[62] = { }; static const struct HashTable processObjectTable = - { 62, 127, true, nullptr, processObjectTableValues, processObjectTableIndex }; + { 65, 255, true, nullptr, processObjectTableValues, processObjectTableIndex }; diff --git a/src/bun.js/bindings/Serialization.cpp b/src/bun.js/bindings/Serialization.cpp new file mode 100644 index 000000000..89937ebbb --- /dev/null +++ b/src/bun.js/bindings/Serialization.cpp @@ -0,0 +1,49 @@ +#include "root.h" +#include "headers-handwritten.h" +#include "ExceptionOr.h" +#include "MessagePort.h" +#include "SerializedScriptValue.h" +#include "JSDOMExceptionHandling.h" + +using namespace JSC; +using namespace WebCore; + +/// This is used for Bun.spawn() IPC because otherwise we would have to copy the data once to get it to zig, then write it. +/// Returns `true` on success, `false` on failure + throws a JS error. +extern "C" bool Bun__serializeJSValueForSubprocess(JSGlobalObject* globalObject, EncodedJSValue encodedValue, int fd) +{ + JSValue value = JSValue::decode(encodedValue); + + Vector<JSC::Strong<JSC::JSObject>> transferList; + Vector<RefPtr<MessagePort>> dummyPorts; + ExceptionOr<Ref<SerializedScriptValue>> serialized = SerializedScriptValue::create(*globalObject, value, WTFMove(transferList), + dummyPorts); + + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (serialized.hasException()) { + WebCore::propagateException(*globalObject, scope, + serialized.releaseException()); + RELEASE_AND_RETURN(scope, false); + } + + auto serializedValue = serialized.releaseReturnValue(); + auto bytes = serializedValue.ptr()->wireBytes(); + + uint8_t id = 2; // IPCMessageType.SerializedMessage + write(fd, &id, sizeof(uint8_t)); + uint32_t size = bytes.size(); + write(fd, &size, sizeof(uint32_t)); + write(fd, bytes.data(), size); + + RELEASE_AND_RETURN(scope, true); +} + +extern "C" EncodedJSValue Bun__JSValue__deserialize(JSGlobalObject* globalObject, const uint8_t* bytes, size_t size) +{ + Vector<uint8_t> vector(bytes, size); + /// ?! did i just give ownership of these bytes to JSC? + auto scriptValue = SerializedScriptValue::createFromWireBytes(WTFMove(vector)); + return JSValue::encode(scriptValue->deserialize(*globalObject, globalObject)); +}
\ No newline at end of file diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp index 5a10a05d3..ec2add296 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.cpp +++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp @@ -23215,6 +23215,9 @@ JSC_DECLARE_CUSTOM_GETTER(SubprocessPrototype__readableGetterWrap); extern "C" EncodedJSValue SubprocessPrototype__doRef(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(SubprocessPrototype__refCallback); +extern "C" EncodedJSValue SubprocessPrototype__doSend(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(SubprocessPrototype__sendCallback); + extern "C" JSC::EncodedJSValue SubprocessPrototype__getSignalCode(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(SubprocessPrototype__signalCodeGetterWrap); @@ -23243,6 +23246,7 @@ static const HashTableValue JSSubprocessPrototypeTableValues[] = { { "pid"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, SubprocessPrototype__pidGetterWrap, 0 } }, { "readable"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, SubprocessPrototype__readableGetterWrap, 0 } }, { "ref"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, SubprocessPrototype__refCallback, 0 } }, + { "send"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, SubprocessPrototype__sendCallback, 1 } }, { "signalCode"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, SubprocessPrototype__signalCodeGetterWrap, 0 } }, { "stderr"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, SubprocessPrototype__stderrGetterWrap, 0 } }, { "stdin"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, SubprocessPrototype__stdinGetterWrap, 0 } }, @@ -23400,6 +23404,34 @@ JSC_DEFINE_HOST_FUNCTION(SubprocessPrototype__refCallback, (JSGlobalObject * lex return SubprocessPrototype__doRef(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(SubprocessPrototype__sendCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSSubprocess* thisObject = jsDynamicCast<JSSubprocess*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof Subprocess"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return SubprocessPrototype__doSend(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_CUSTOM_GETTER(SubprocessPrototype__signalCodeGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { auto& vm = lexicalGlobalObject->vm(); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 286084b4d..091cc0b29 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -90,8 +90,6 @@ #include "JSCloseEvent.h" #include "JSFetchHeaders.h" #include "JSStringDecoder.h" -#include "JSReadableState.h" -#include "JSReadableHelper.h" #include "Process.h" #include "AsyncContextFrame.h" @@ -1628,7 +1626,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, switch (callFrame->argumentCount()) { case 0: { - JSC::throwTypeError(globalObject, scope, "lazyLoad needs 1 argument (a string)"_s); + JSC::throwTypeError(globalObject, scope, "$lazy needs 1 argument (a string)"_s); scope.release(); return JSC::JSValue::encode(JSC::JSValue {}); } @@ -1637,7 +1635,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, if (moduleName.isNumber()) { switch (moduleName.toInt32(globalObject)) { case 0: { - JSC::throwTypeError(globalObject, scope, "lazyLoad expects a string"_s); + JSC::throwTypeError(globalObject, scope, "$lazy expects a string"_s); scope.release(); return JSC::JSValue::encode(JSC::JSValue {}); } @@ -1654,7 +1652,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, default: { auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - JSC::throwTypeError(globalObject, scope, "lazyLoad expects a string"_s); + JSC::throwTypeError(globalObject, scope, "$lazy expects a string"_s); scope.release(); return JSC::JSValue::encode(JSC::JSValue {}); } @@ -1663,7 +1661,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, auto string = moduleName.toWTFString(globalObject); if (string.isNull()) { - JSC::throwTypeError(globalObject, scope, "lazyLoad expects a string"_s); + JSC::throwTypeError(globalObject, scope, "$lazy expects a string"_s); scope.release(); return JSC::JSValue::encode(JSC::JSValue {}); } @@ -1673,7 +1671,6 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, } if (string == "worker_threads"_s) { - JSValue workerData = jsUndefined(); JSValue threadId = jsNumber(0); @@ -1708,27 +1705,6 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, JSFunction::create(vm, globalObject, 1, fileURLToPathString, functionFileURLToPath, ImplementationVisibility::Public, NoIntrinsic)); } - if (string == "bun:stream"_s) { - auto* obj = constructEmptyObject(globalObject); - obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "BufferList"_s)), reinterpret_cast<Zig::GlobalObject*>(globalObject)->JSBufferList(), 0); - obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "ReadableState"_s)), reinterpret_cast<Zig::GlobalObject*>(globalObject)->JSReadableState(), 0); - obj->putDirect( - vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "maybeReadMore"_s)), - JSC::JSFunction::create(vm, globalObject, 0, "maybeReadMore"_s, jsReadable_maybeReadMore, ImplementationVisibility::Public), 0); - obj->putDirect( - vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "resume"_s)), - JSC::JSFunction::create(vm, globalObject, 0, "resume"_s, jsReadable_resume, ImplementationVisibility::Public), 0); - obj->putDirect( - vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "emitReadable"_s)), - JSC::JSFunction::create(vm, globalObject, 0, "emitReadable"_s, jsReadable_emitReadable, ImplementationVisibility::Public), 0); - obj->putDirect( - vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "onEofChunk"_s)), - JSC::JSFunction::create(vm, globalObject, 0, "onEofChunk"_s, jsReadable_onEofChunk, ImplementationVisibility::Public), 0); - return JSValue::encode(obj); - } - if (string == "events"_s) { - return JSValue::encode(WebCore::JSEventEmitter::getConstructor(vm, globalObject)); - } if (string == "internal/tls"_s) { auto* obj = constructEmptyObject(globalObject); @@ -1759,9 +1735,9 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, return JSValue::encode(obj); } - if (string == "masqueradesAsUndefined"_s) { - return JSValue::encode(InternalFunction::createFunctionThatMasqueradesAsUndefined(vm, globalObject, 0, String(), functionCallNotImplemented)); - } + // if (string == "masqueradesAsUndefined"_s) { + // return JSValue::encode(InternalFunction::createFunctionThatMasqueradesAsUndefined(vm, globalObject, 0, String(), functionCallNotImplemented)); + // } if (string == "vm"_s) { auto* obj = constructEmptyObject(globalObject); @@ -1818,9 +1794,9 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, return JSC::JSValue::encode(obj); } - return JSC::JSValue::encode(JSC::jsUndefined()); - - break; + JSC::throwTypeError(globalObject, scope, "$lazy expects a string"_s); + scope.release(); + return JSC::JSValue::encode(JSC::JSValue {}); } } } @@ -2360,6 +2336,7 @@ private: functionNoop, ImplementationVisibility::Public, NoIntrinsic, functionNoop, &DOMJITSignatureForPerformanceNow); this->putDirect(vm, JSC::Identifier::fromString(vm, "mark"_s), noopNotImplemented, JSC::PropertyAttribute::DOMJITFunction | JSC::PropertyAttribute::Function); + this->putDirect(vm, JSC::Identifier::fromString(vm, "markResourceTiming"_s), noopNotImplemented, JSC::PropertyAttribute::DOMJITFunction | JSC::PropertyAttribute::Function); this->putDirect(vm, JSC::Identifier::fromString(vm, "measure"_s), noopNotImplemented, JSC::PropertyAttribute::DOMJITFunction | JSC::PropertyAttribute::Function); this->putDirect( @@ -3004,10 +2981,6 @@ void GlobalObject::finishCreation(VM& vm) [](const Initializer<JSFunction>& init) { init.set(JSFunction::create(init.vm, init.owner, 4, "performMicrotask"_s, jsFunctionPerformMicrotask, ImplementationVisibility::Public)); }); - m_emitReadableNextTickFunction.initLater( - [](const Initializer<JSFunction>& init) { - init.set(JSFunction::create(init.vm, init.owner, 4, "emitReadable"_s, WebCore::jsReadable_emitReadable_, ImplementationVisibility::Public)); - }); m_bunSleepThenCallback.initLater( [](const Initializer<JSFunction>& init) { @@ -3322,18 +3295,6 @@ void GlobalObject::finishCreation(VM& vm) init.setConstructor(constructor); }); - m_JSReadableStateClassStructure.initLater( - [](LazyClassStructure::Initializer& init) { - auto* prototype = JSReadableStatePrototype::create( - init.vm, init.global, JSReadableStatePrototype::createStructure(init.vm, init.global, init.global->objectPrototype())); - auto* structure = JSReadableState::createStructure(init.vm, init.global, prototype); - auto* constructor = JSReadableStateConstructor::create( - init.vm, init.global, JSReadableStateConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()), prototype); - init.setPrototype(prototype); - init.setStructure(structure); - init.setConstructor(constructor); - }); - m_JSFFIFunctionStructure.initLater( [](LazyClassStructure::Initializer& init) { init.setStructure(Zig::JSFFIFunction::createStructure(init.vm, init.global, init.global->functionPrototype())); @@ -4091,6 +4052,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(thisObject->m_readableStreamToJSON); visitor.append(thisObject->m_readableStreamToText); visitor.append(thisObject->m_readableStreamToFormData); + visitor.append(thisObject->m_nodeModuleOverriddenResolveFilename); visitor.append(thisObject->m_JSBlobSetterValue); visitor.append(thisObject->m_JSBroadcastChannelSetterValue); @@ -4122,7 +4084,6 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_JSFileSinkClassStructure.visit(visitor); thisObject->m_JSHTTPResponseSinkClassStructure.visit(visitor); thisObject->m_JSHTTPSResponseSinkClassStructure.visit(visitor); - thisObject->m_JSReadableStateClassStructure.visit(visitor); thisObject->m_JSStringDecoderClassStructure.visit(visitor); thisObject->m_NapiClassStructure.visit(visitor); thisObject->m_JSBufferClassStructure.visit(visitor); @@ -4148,7 +4109,6 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_subtleCryptoObject.visit(visitor); thisObject->m_JSHTTPResponseController.visit(visitor); thisObject->m_callSiteStructure.visit(visitor); - thisObject->m_emitReadableNextTickFunction.visit(visitor); thisObject->m_JSBufferSubclassStructure.visit(visitor); thisObject->m_cryptoObject.visit(visitor); thisObject->m_JSDOMFileConstructor.visit(visitor); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index e622016de..7377e6693 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -238,10 +238,6 @@ public: JSC::JSObject* JSStringDecoder() { return m_JSStringDecoderClassStructure.constructorInitializedOnMainThread(this); } JSC::JSValue JSStringDecoderPrototype() { return m_JSStringDecoderClassStructure.prototypeInitializedOnMainThread(this); } - JSC::Structure* JSReadableStateStructure() { return m_JSReadableStateClassStructure.getInitializedOnMainThread(this); } - JSC::JSObject* JSReadableState() { return m_JSReadableStateClassStructure.constructorInitializedOnMainThread(this); } - JSC::JSValue JSReadableStatePrototype() { return m_JSReadableStateClassStructure.prototypeInitializedOnMainThread(this); } - JSC::Structure* NodeVMScriptStructure() { return m_NodeVMScriptClassStructure.getInitializedOnMainThread(this); } JSC::JSObject* NodeVMScript() { return m_NodeVMScriptClassStructure.constructorInitializedOnMainThread(this); } JSC::JSValue NodeVMScriptPrototype() { return m_NodeVMScriptClassStructure.prototypeInitializedOnMainThread(this); } @@ -261,8 +257,6 @@ public: JSC::JSFunction* utilInspectStylizeColorFunction() { return m_utilInspectStylizeColorFunction.getInitializedOnMainThread(this); } JSC::JSFunction* utilInspectStylizeNoColorFunction() { return m_utilInspectStylizeNoColorFunction.getInitializedOnMainThread(this); } - JSC::JSFunction* emitReadableNextTickFunction() { return m_emitReadableNextTickFunction.getInitializedOnMainThread(this); } - JSObject* requireFunctionUnbound() { return m_requireFunctionUnbound.getInitializedOnMainThread(this); } JSObject* requireResolveFunctionUnbound() { return m_requireResolveFunctionUnbound.getInitializedOnMainThread(this); } Bun::InternalModuleRegistry* internalModuleRegistry() { return m_internalModuleRegistry.getInitializedOnMainThread(this); } @@ -385,6 +379,10 @@ public: mutable WriteBarrier<JSFunction> m_readableStreamToText; mutable WriteBarrier<JSFunction> m_readableStreamToFormData; + // This is set when doing `require('module')._resolveFilename = ...` + // a hack used by Next.js to inject their versions of webpack and react + mutable WriteBarrier<JSFunction> m_nodeModuleOverriddenResolveFilename; + mutable WriteBarrier<Unknown> m_nextTickQueue; mutable WriteBarrier<Unknown> m_BunCommonJSModuleValue; mutable WriteBarrier<Unknown> m_JSBroadcastChannelSetterValue; @@ -502,7 +500,6 @@ private: LazyClassStructure m_JSFileSinkClassStructure; LazyClassStructure m_JSHTTPResponseSinkClassStructure; LazyClassStructure m_JSHTTPSResponseSinkClassStructure; - LazyClassStructure m_JSReadableStateClassStructure; LazyClassStructure m_JSStringDecoderClassStructure; LazyClassStructure m_NapiClassStructure; LazyClassStructure m_callSiteStructure; @@ -526,7 +523,7 @@ private: LazyProperty<JSGlobalObject, JSFunction> m_utilInspectFunction; LazyProperty<JSGlobalObject, JSFunction> m_utilInspectStylizeColorFunction; LazyProperty<JSGlobalObject, JSFunction> m_utilInspectStylizeNoColorFunction; - LazyProperty<JSGlobalObject, JSFunction> m_emitReadableNextTickFunction; + LazyProperty<JSGlobalObject, JSMap> m_lazyReadableStreamPrototypeMap; LazyProperty<JSGlobalObject, JSMap> m_requireMap; LazyProperty<JSGlobalObject, Structure> m_encodeIntoObjectStructure; diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 532d2bc68..1a82fc5e6 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -4917,6 +4917,13 @@ pub const JSValue = enum(JSValueReprInt) { JSC.markBinding(@src()); return AsyncContextFrame__withAsyncContextIfNeeded(global, this); } + + extern "c" fn Bun__JSValue__deserialize(global: *JSGlobalObject, data: [*]const u8, len: isize) JSValue; + + /// Deserializes a JSValue from a serialized buffer. Zig version of `import('bun:jsc').deserialize` + pub inline fn deserialize(bytes: []const u8, global: *JSGlobalObject) JSValue { + return Bun__JSValue__deserialize(global, bytes.ptr, @intCast(bytes.len)); + } }; extern "c" fn AsyncContextFrame__withAsyncContextIfNeeded(global: *JSGlobalObject, callback: JSValue) JSValue; diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index e7e16e889..329506718 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -6140,6 +6140,8 @@ pub const JSSubprocess = struct { if (@TypeOf(Subprocess.doRef) != CallbackType) @compileLog("Expected Subprocess.doRef to be a callback but received " ++ @typeName(@TypeOf(Subprocess.doRef))); + if (@TypeOf(Subprocess.doSend) != CallbackType) + @compileLog("Expected Subprocess.doSend to be a callback but received " ++ @typeName(@TypeOf(Subprocess.doSend))); if (@TypeOf(Subprocess.getSignalCode) != GetterType) @compileLog("Expected Subprocess.getSignalCode to be a getter"); @@ -6159,6 +6161,7 @@ pub const JSSubprocess = struct { if (!JSC.is_bindgen) { @export(Subprocess.doRef, .{ .name = "SubprocessPrototype__doRef" }); + @export(Subprocess.doSend, .{ .name = "SubprocessPrototype__doSend" }); @export(Subprocess.doUnref, .{ .name = "SubprocessPrototype__doUnref" }); @export(Subprocess.finalize, .{ .name = "SubprocessClass__finalize" }); @export(Subprocess.getExitCode, .{ .name = "SubprocessPrototype__getExitCode" }); diff --git a/src/bun.js/bindings/webcore/EventEmitter.h b/src/bun.js/bindings/webcore/EventEmitter.h index 8db59c188..23687d43a 100644 --- a/src/bun.js/bindings/webcore/EventEmitter.h +++ b/src/bun.js/bindings/webcore/EventEmitter.h @@ -94,6 +94,8 @@ public: } } + bool m_hasIPCRef { false }; + private: EventEmitter(ScriptExecutionContext& context) : ContextDestructionObserver(&context) |