From 209dc981c0ef52de5c80eab5d24ec8a8eba765e8 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sun, 16 Jul 2023 21:15:24 -0700 Subject: 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 Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> --- src/bun.js/bindings/BunJSCModule.cpp | 74 ++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'src/bun.js/bindings/BunJSCModule.cpp') diff --git a/src/bun.js/bindings/BunJSCModule.cpp b/src/bun.js/bindings/BunJSCModule.cpp index 5809a9813..a145f51c5 100644 --- a/src/bun.js/bindings/BunJSCModule.cpp +++ b/src/bun.js/bindings/BunJSCModule.cpp @@ -24,15 +24,19 @@ #include "JavaScriptCore/DeferTermination.h" #include "JavaScriptCore/SamplingProfiler.h" #include "JavaScriptCore/VMTrapsInlines.h" +#include "SerializedScriptValue.h" +#include "ExceptionOr.h" #if ENABLE(REMOTE_INSPECTOR) #include "JavaScriptCore/RemoteInspectorServer.h" #endif #include "mimalloc.h" +#include "JSDOMConvertBase.h" using namespace JSC; using namespace WTF; +using namespace WebCore; JSC_DECLARE_HOST_FUNCTION(functionStartRemoteDebugger); JSC_DEFINE_HOST_FUNCTION(functionStartRemoteDebugger, (JSGlobalObject * globalObject, CallFrame* callFrame)) @@ -525,6 +529,74 @@ JSC_DEFINE_HOST_FUNCTION(functionGenerateHeapSnapshotForDebugging, (JSGlobalObje return JSValue::encode(JSONParse(globalObject, WTFMove(jsonString))); } +JSC_DEFINE_HOST_FUNCTION(functionSerialize, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto* globalObject = jsCast(lexicalGlobalObject); + JSC::VM& vm = globalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + JSValue value = callFrame->argument(0); + JSValue optionsObject = callFrame->argument(1); + bool asNodeBuffer = false; + if (optionsObject.isObject()) { + JSC::JSObject* options = optionsObject.getObject(); + if (JSC::JSValue binaryTypeValue = options->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "binaryType"_s))) { + if (!binaryTypeValue.isString()) { + throwTypeError(globalObject, throwScope, "binaryType must be a string"_s); + return JSValue::encode(jsUndefined()); + } + + asNodeBuffer = binaryTypeValue.toWTFString(globalObject) == "nodebuffer"_s; + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + } + } + + Vector> transferList; + + ExceptionOr> serialized = SerializedScriptValue::create(*globalObject, value, WTFMove(transferList)); + + if (serialized.hasException()) { + WebCore::propagateException(*globalObject, throwScope, serialized.releaseException()); + return JSValue::encode(jsUndefined()); + } + + auto serializedValue = serialized.releaseReturnValue(); + auto arrayBuffer = serializedValue->toArrayBuffer(); + + if (asNodeBuffer) { + size_t byteLength = arrayBuffer->byteLength(); + JSC::JSUint8Array* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, globalObject->JSBufferSubclassStructure(), WTFMove(arrayBuffer), 0, byteLength); + return JSValue::encode(uint8Array); + } + + if (arrayBuffer->isShared()) { + return JSValue::encode(JSArrayBuffer::create(vm, globalObject->arrayBufferStructureWithSharingMode(), WTFMove(arrayBuffer))); + } + + return JSValue::encode(JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(), WTFMove(arrayBuffer))); +} +JSC_DEFINE_HOST_FUNCTION(functionDeserialize, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + JSC::VM& vm = globalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSValue value = callFrame->argument(0); + + JSValue result; + + if (auto* jsArrayBuffer = jsDynamicCast(value)) { + result = SerializedScriptValue::fromArrayBuffer(*globalObject, globalObject, jsArrayBuffer->impl(), 0, jsArrayBuffer->impl()->byteLength()); + } else if (auto* view = jsDynamicCast(value)) { + auto arrayBuffer = view->possiblySharedImpl()->possiblySharedBuffer(); + result = SerializedScriptValue::fromArrayBuffer(*globalObject, globalObject, arrayBuffer.get(), view->byteOffset(), view->byteLength()); + } else { + throwTypeError(globalObject, throwScope, "First argument must be an ArrayBuffer"_s); + return JSValue::encode(jsUndefined()); + } + + RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + JSC::JSObject* createJSCModule(JSC::JSGlobalObject* globalObject) { VM& vm = globalObject->vm(); @@ -561,6 +633,8 @@ JSC::JSObject* createJSCModule(JSC::JSGlobalObject* globalObject) object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "generateHeapSnapshotForDebugging"_s), 0, functionGenerateHeapSnapshotForDebugging, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "profile"_s), 0, functionRunProfiler, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "setTimeZone"_s), 0, functionSetTimeZone, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); + object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "serialize"_s), 0, functionSerialize, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); + object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "deserialize"_s), 0, functionDeserialize, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); } return object; -- cgit v1.2.3