mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 19:08:50 +00:00
Implement Workers (#3645)
* copy files * format * options * Introduce `Worker`, `onmessage`, `onerror`, and `postMessage` globals * Stub `Worker.prototype.ref` & `Worker.prototype.unref` * Update web_worker.zig * Worker works * Add "mini" mode * add wakeup * Partially fix the keep-alive issue * clean up refer behavior * Implement `serialize` & `deserialize` in `bun:jsc` & add polyfill for `node:v8` * Types & docs * Update globals.d.ts * Add mutex * Fixes --------- Co-authored-by: Dylan Conway <dylan.conway567@gmail.com> Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
@@ -74,6 +74,7 @@
|
||||
#include <JavaScriptCore/ExceptionHelpers.h>
|
||||
#include <JavaScriptCore/IterationKind.h>
|
||||
#include <JavaScriptCore/JSArrayBuffer.h>
|
||||
#include <JavaScriptCore/ArrayBuffer.h>
|
||||
#include <JavaScriptCore/JSArrayBufferView.h>
|
||||
#include <JavaScriptCore/JSCInlines.h>
|
||||
#include <JavaScriptCore/JSDataView.h>
|
||||
@@ -2527,7 +2528,7 @@ public:
|
||||
Vector<std::unique_ptr<DetachedRTCDataChannel>>&& detachedRTCDataChannels
|
||||
#endif
|
||||
,
|
||||
ArrayBufferContentsArray* arrayBufferContentsArray, const Vector<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers
|
||||
ArrayBufferContentsArray* arrayBufferContentsArray, const Span<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers
|
||||
#if ENABLE(WEBASSEMBLY)
|
||||
,
|
||||
WasmModuleArray* wasmModules, WasmMemoryHandleArray* wasmMemoryHandles
|
||||
@@ -2540,7 +2541,7 @@ public:
|
||||
{
|
||||
if (!buffer.size())
|
||||
return std::make_pair(jsNull(), SerializationReturnCode::UnspecifiedError);
|
||||
CloneDeserializer deserializer(lexicalGlobalObject, globalObject, arrayBufferContentsArray, buffer, blobURLs, blobFilePaths, sharedBuffers
|
||||
CloneDeserializer deserializer(lexicalGlobalObject, globalObject, arrayBufferContentsArray, Span<uint8_t> { buffer.begin(), buffer.end() }, blobURLs, blobFilePaths, sharedBuffers
|
||||
#if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
|
||||
,
|
||||
WTFMove(detachedOffscreenCanvases)
|
||||
@@ -2660,7 +2661,7 @@ private:
|
||||
// m_version = 0xFFFFFFFF;
|
||||
// }
|
||||
|
||||
CloneDeserializer(JSGlobalObject* lexicalGlobalObject, JSGlobalObject* globalObject, ArrayBufferContentsArray* arrayBufferContents, const Vector<uint8_t>& buffer
|
||||
CloneDeserializer(JSGlobalObject* lexicalGlobalObject, JSGlobalObject* globalObject, ArrayBufferContentsArray* arrayBufferContents, const Span<uint8_t>& buffer
|
||||
#if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
|
||||
,
|
||||
Vector<std::unique_ptr<DetachedOffscreenCanvas>>&& detachedOffscreenCanvases = {}
|
||||
@@ -2766,7 +2767,7 @@ private:
|
||||
// m_version = 0xFFFFFFFF;
|
||||
// }
|
||||
|
||||
CloneDeserializer(JSGlobalObject* lexicalGlobalObject, JSGlobalObject* globalObject, ArrayBufferContentsArray* arrayBufferContents, const Vector<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers
|
||||
CloneDeserializer(JSGlobalObject* lexicalGlobalObject, JSGlobalObject* globalObject, ArrayBufferContentsArray* arrayBufferContents, const Span<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers
|
||||
#if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
|
||||
,
|
||||
Vector<std::unique_ptr<DetachedOffscreenCanvas>>&& detachedOffscreenCanvases
|
||||
@@ -5282,6 +5283,73 @@ String SerializedScriptValue::toString() const
|
||||
return CloneDeserializer::deserializeString(m_data);
|
||||
}
|
||||
|
||||
Ref<JSC::ArrayBuffer> SerializedScriptValue::toArrayBuffer()
|
||||
{
|
||||
if (this->m_data.size() == 0) {
|
||||
return ArrayBuffer::create(static_cast<size_t>(0), static_cast<unsigned>(1));
|
||||
}
|
||||
|
||||
this->ref();
|
||||
auto arrayBuffer = ArrayBuffer::createFromBytes(
|
||||
this->m_data.data(), this->m_data.size(), createSharedTask<void(void*)>([protectedThis = Ref { *this }](void* p) {
|
||||
protectedThis->deref();
|
||||
}));
|
||||
|
||||
// Note: using the SharedArrayBufferContents::create function directly didn't work.
|
||||
arrayBuffer->makeShared();
|
||||
|
||||
return arrayBuffer;
|
||||
}
|
||||
|
||||
JSC::JSValue SerializedScriptValue::fromArrayBuffer(JSC::JSGlobalObject& domGlobal, JSC::JSGlobalObject* globalObject, JSC::ArrayBuffer* arrayBuffer, size_t byteOffset, size_t maxByteLength, SerializationErrorMode throwExceptions, bool* didFail)
|
||||
{
|
||||
auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm());
|
||||
|
||||
if (!arrayBuffer || arrayBuffer->isDetached()) {
|
||||
if (didFail)
|
||||
*didFail = true;
|
||||
|
||||
if (throwExceptions == SerializationErrorMode::Throwing)
|
||||
throwTypeError(globalObject, throwScope, "Cannot deserialize a detached ArrayBuffer"_s);
|
||||
|
||||
return JSC::jsUndefined();
|
||||
}
|
||||
auto blobURLs = Vector<String> {};
|
||||
auto blobFiles = Vector<String> {};
|
||||
|
||||
if (arrayBuffer->isShared()) {
|
||||
// prevent detaching while in-use
|
||||
arrayBuffer->pin();
|
||||
}
|
||||
|
||||
auto* data = static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset;
|
||||
auto size = std::min(arrayBuffer->byteLength(), maxByteLength);
|
||||
auto span = Span<uint8_t> { data, size };
|
||||
|
||||
auto result = CloneDeserializer::deserialize(&domGlobal, globalObject, nullptr, span, blobURLs, blobFiles, nullptr
|
||||
#if ENABLE(WEBASSEMBLY)
|
||||
,
|
||||
nullptr, nullptr
|
||||
#endif
|
||||
#if ENABLE(WEB_CODECS)
|
||||
,
|
||||
WTFMove(m_serializedVideoChunks), WTFMove(m_serializedVideoFrames)
|
||||
#endif
|
||||
);
|
||||
|
||||
if (arrayBuffer->isShared()) {
|
||||
arrayBuffer->unpin();
|
||||
}
|
||||
|
||||
if (didFail) {
|
||||
*didFail = result.second != SerializationReturnCode::SuccessfullyCompleted;
|
||||
}
|
||||
if (throwExceptions == SerializationErrorMode::Throwing)
|
||||
maybeThrowExceptionIfSerializationFailed(*globalObject, result.second);
|
||||
|
||||
return result.first ? result.first : jsNull();
|
||||
}
|
||||
|
||||
// JSValue SerializedScriptValue::deserialize(JSGlobalObject& lexicalGlobalObject, JSGlobalObject* globalObject, SerializationErrorMode throwExceptions, bool* didFail)
|
||||
// {
|
||||
// return deserialize(lexicalGlobalObject, globalObject, {}, throwExceptions, didFail);
|
||||
@@ -5396,7 +5464,8 @@ JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, J
|
||||
return toRef(lexicalGlobalObject, value);
|
||||
}
|
||||
|
||||
Ref<SerializedScriptValue> SerializedScriptValue::nullValue()
|
||||
Ref<SerializedScriptValue>
|
||||
SerializedScriptValue::nullValue()
|
||||
{
|
||||
return adoptRef(*new SerializedScriptValue(Vector<uint8_t>()));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user