fix: overriding self.postMessage should not impact worker_threads.parentPort (#10496)

* fix a bug in worker

* remove old
This commit is contained in:
dave caruso
2024-04-24 22:14:37 -07:00
committed by GitHub
parent 685dc02142
commit e792bbdf5f
10 changed files with 220 additions and 262 deletions

View File

@@ -211,11 +211,11 @@ void ScriptExecutionContext::dispatchMessagePortEvents()
void ScriptExecutionContext::checkConsistency() const
{
for (auto* messagePort : m_messagePorts)
ASSERT(messagePort->scriptExecutionContext() == this);
// for (auto* messagePort : m_messagePorts)
// ASSERT(messagePort->scriptExecutionContext() == this);
for (auto* destructionObserver : m_destructionObservers)
ASSERT(destructionObserver->scriptExecutionContext() == this);
// for (auto* destructionObserver : m_destructionObservers)
// ASSERT(destructionObserver->scriptExecutionContext() == this);
// for (auto* activeDOMObject : m_activeDOMObjects) {
// ASSERT(activeDOMObject->scriptExecutionContext() == this);

View File

@@ -1,156 +1,166 @@
#include "root.h"
#include "ZigGlobalObject.h"
#include <JavaScriptCore/GlobalObjectMethodTable.h>
#include "helpers.h"
#include "BunClientData.h"
#include "JavaScriptCore/JSCJSValue.h"
#include "JavaScriptCore/AggregateError.h"
#include "JavaScriptCore/JSObjectInlines.h"
#include "JavaScriptCore/InternalFieldTuple.h"
#include "JavaScriptCore/BytecodeIndex.h"
#include "JavaScriptCore/CallFrameInlines.h"
#include "wtf/text/Base64.h"
#include "JavaScriptCore/BuiltinNames.h"
#include "JavaScriptCore/CallData.h"
#include "JavaScriptCore/CatchScope.h"
#include "JavaScriptCore/ClassInfo.h"
#include "JavaScriptCore/CodeBlock.h"
#include "JavaScriptCore/Completion.h"
#include "JavaScriptCore/DeferredWorkTimer.h"
#include "JavaScriptCore/Error.h"
#include "JavaScriptCore/ErrorInstance.h"
#include "JavaScriptCore/Exception.h"
#include "JavaScriptCore/ExceptionScope.h"
#include "JavaScriptCore/FunctionConstructor.h"
#include "JavaScriptCore/FunctionPrototype.h"
#include "JavaScriptCore/GetterSetter.h"
#include "JavaScriptCore/GlobalObjectMethodTable.h"
#include "JavaScriptCore/HashMapImpl.h"
#include "JavaScriptCore/HashMapImplInlines.h"
#include "JavaScriptCore/Heap.h"
#include "JavaScriptCore/Identifier.h"
#include "JavaScriptCore/InitializeThreading.h"
#include "JavaScriptCore/IteratorOperations.h"
#include "JavaScriptCore/InternalFieldTuple.h"
#include "JavaScriptCore/InternalFunction.h"
#include "JavaScriptCore/JSArray.h"
#include "JavaScriptCore/JSGlobalProxyInlines.h"
#include "JavaScriptCore/JSCallbackConstructor.h"
#include "JavaScriptCore/JSCallbackObject.h"
#include "JavaScriptCore/JSCast.h"
#include "JavaScriptCore/JSClassRef.h"
#include "JavaScriptCore/JSMicrotask.h"
#include "ConsoleObject.h"
// #include "JavaScriptCore/JSContextInternal.h"
#include "JavaScriptCore/CatchScope.h"
#include "JavaScriptCore/DeferredWorkTimer.h"
#include "JavaScriptCore/JSCJSValue.h"
#include "JavaScriptCore/JSGlobalProxyInlines.h"
#include "JavaScriptCore/JSInternalPromise.h"
#include "JavaScriptCore/JSLock.h"
#include "JavaScriptCore/JSMap.h"
#include "JavaScriptCore/JSMicrotask.h"
#include "JavaScriptCore/JSModuleLoader.h"
#include "JavaScriptCore/JSModuleNamespaceObject.h"
#include "JavaScriptCore/JSModuleNamespaceObjectInlines.h"
#include "JavaScriptCore/JSModuleRecord.h"
#include "JavaScriptCore/JSNativeStdFunction.h"
#include "JavaScriptCore/JSObject.h"
#include "JavaScriptCore/JSObjectInlines.h"
#include "JavaScriptCore/JSPromise.h"
#include "JavaScriptCore/JSSet.h"
#include "JavaScriptCore/JSScriptFetchParameters.h"
#include "JavaScriptCore/JSSourceCode.h"
#include "JavaScriptCore/JSString.h"
#include "JavaScriptCore/JSValueInternal.h"
#include "JavaScriptCore/JSVirtualMachineInternal.h"
#include "JavaScriptCore/JSWeakMap.h"
#include "JavaScriptCore/LazyClassStructure.h"
#include "JavaScriptCore/LazyClassStructureInlines.h"
#include "JavaScriptCore/ObjectConstructor.h"
#include "JavaScriptCore/OptionsList.h"
#include "JavaScriptCore/ParserError.h"
#include "JavaScriptCore/ScriptExecutable.h"
#include "JavaScriptCore/ScriptFetchParameters.h"
#include "JavaScriptCore/SourceOrigin.h"
#include "JavaScriptCore/StackFrame.h"
#include "JavaScriptCore/StackVisitor.h"
#include "JavaScriptCore/VM.h"
#include "JavaScriptCore/WasmFaultSignalHandler.h"
#include "wtf/Assertions.h"
#include "wtf/Gigacage.h"
#include "wtf/URL.h"
#include "wtf/text/ExternalStringImpl.h"
#include "wtf/text/StringCommon.h"
#include "wtf/text/StringImpl.h"
#include "wtf/text/StringView.h"
#include "wtf/text/WTFString.h"
#include "JavaScriptCore/JSScriptFetchParameters.h"
#include "JavaScriptCore/ScriptFetchParameters.h"
#include "wtf/text/Base64.h"
// #include "JavaScriptCore/CachedType.h"
#include "JavaScriptCore/JSCallbackObject.h"
#include "JavaScriptCore/JSClassRef.h"
#include "JavaScriptCore/CallData.h"
#include "GCDefferalContext.h"
#include "BunClientData.h"
#include "ZigSourceProvider.h"
#include "JSDOMURL.h"
#include "JSURLSearchParams.h"
#include "JSDOMException.h"
#include "JSEventTarget.h"
#include "JSEventEmitter.h"
#include "EventTargetConcrete.h"
#include "JSAbortSignal.h"
#include "JSCustomEvent.h"
#include "JSAbortController.h"
#include "JSEvent.h"
#include "JSErrorEvent.h"
#include "JSCloseEvent.h"
#include "JSFetchHeaders.h"
#include "JSStringDecoder.h"
#include "JSReadableState.h"
#include "JSReadableHelper.h"
#include "JSPerformance.h"
#include "Performance.h"
#include "JSPerformanceObserver.h"
#include "JSPerformanceObserverEntryList.h"
#include "JSPerformanceEntry.h"
#include "JSPerformanceMeasure.h"
#include "JSPerformanceMark.h"
#include "BunProcess.h"
#include "AddEventListenerOptions.h"
#include "AsyncContextFrame.h"
#include "WebCoreJSBuiltins.h"
#include "BunClientData.h"
#include "BunClientData.h"
#include "BunObject.h"
#include "BunPlugin.h"
#include "BunProcess.h"
#include "BunWorkerGlobalScope.h"
#include "CallSite.h"
#include "CallSitePrototype.h"
#include "CommonJSModuleRecord.h"
#include "ConsoleObject.h"
#include "DOMWrapperWorld-class.h"
#include "ErrorStackTrace.h"
#include "IDLTypes.h"
#include "ImportMetaObject.h"
#include "JS2Native.h"
#include "JSAbortAlgorithm.h"
#include "JSAbortController.h"
#include "JSAbortSignal.h"
#include "JSBroadcastChannel.h"
#include "JSBuffer.h"
#include "JSBufferList.h"
#include "JSFFIFunction.h"
#include "JavaScriptCore/InternalFunction.h"
#include "JavaScriptCore/LazyClassStructure.h"
#include "JavaScriptCore/LazyClassStructureInlines.h"
#include "JavaScriptCore/FunctionPrototype.h"
#include "JavaScriptCore/GetterSetter.h"
#include "napi.h"
#include "JSSQLStatement.h"
#include "ModuleLoader.h"
#include "NodeVM.h"
#include "ProcessIdentifier.h"
#include "SerializedScriptValue.h"
#include "NodeTTYModule.h"
#include "ZigGeneratedClasses.h"
#include "JavaScriptCore/DateInstance.h"
#include "JS2Native.h"
#include "BunPlugin.h"
#include "JSEnvironmentVariableMap.h"
#include "DOMIsoSubspaces.h"
#include "BunWorkerGlobalScope.h"
#include "JSWorker.h"
#include "JSMessageChannel.h"
#include "JSMessagePort.h"
#include "JSBroadcastChannel.h"
#include "JSByteLengthQueuingStrategy.h"
#include "JSCloseEvent.h"
#include "JSCountQueuingStrategy.h"
#include "JSCustomEvent.h"
#include "JSDOMConvertBase.h"
#include "JSDOMConvertUnion.h"
#include "JSDOMException.h"
#include "JSDOMFile.h"
#include "JSDOMFormData.h"
#include "JSDOMURL.h"
#include "JSEnvironmentVariableMap.h"
#include "JSErrorEvent.h"
#include "JSEvent.h"
#include "JSEventEmitter.h"
#include "JSEventListener.h"
#include "JSEventTarget.h"
#include "JSFetchHeaders.h"
#include "JSFFIFunction.h"
#include "JSMessageChannel.h"
#include "JSMessageEvent.h"
#include "JSMessagePort.h"
#include "JSNextTickQueue.h"
#include "JSPerformance.h"
#include "JSPerformanceEntry.h"
#include "JSPerformanceMark.h"
#include "JSPerformanceMeasure.h"
#include "JSPerformanceObserver.h"
#include "JSPerformanceObserverEntryList.h"
#include "JSReadableByteStreamController.h"
#include "JSReadableHelper.h"
#include "JSReadableState.h"
#include "JSReadableStream.h"
#include "JSReadableStreamBYOBReader.h"
#include "JSReadableStreamBYOBRequest.h"
#include "JSReadableStreamDefaultController.h"
#include "JSReadableStreamDefaultReader.h"
#include "JSSink.h"
#include "JSSocketAddress.h"
#include "JSSQLStatement.h"
#include "JSStringDecoder.h"
#include "JSTextEncoder.h"
#include "JSTransformStream.h"
#include "JSTransformStreamDefaultController.h"
#include "JSURLSearchParams.h"
#include "JSWebSocket.h"
#include "JSWorker.h"
#include "JSWritableStream.h"
#include "JSWritableStreamDefaultController.h"
#include "JSWritableStreamDefaultWriter.h"
#include "libusockets.h"
#include "ModuleLoader.h"
#include "napi_external.h"
#include "napi.h"
#include "NodeHTTP.h"
#include "NodeVM.h"
#include "Performance.h"
#include "ProcessBindingConstants.h"
#include "ProcessBindingTTYWrap.h"
#include "ProcessIdentifier.h"
#include "ReadableStream.h"
#include "SerializedScriptValue.h"
#include "StructuredClone.h"
#include "WebCoreJSBuiltins.h"
#include "webcrypto/JSCryptoKey.h"
#include "webcrypto/JSSubtleCrypto.h"
#include "ZigGeneratedClasses.h"
#include "ZigSourceProvider.h"
#if ENABLE(REMOTE_INSPECTOR)
#include "JavaScriptCore/RemoteInspectorServer.h"
#endif
#include "BunObject.h"
#include "JSNextTickQueue.h"
#include "NodeHTTP.h"
#include "napi_external.h"
#if !OS(WINDOWS)
#include <dlfcn.h>
#endif
#ifdef __APPLE__
#include <sys/sysctl.h>
#elif defined(__linux__)
// for sysconf
#include <unistd.h>
#endif
using namespace Bun;
extern "C" JSC__JSValue Bun__NodeUtil__jsParseArgs(JSC::JSGlobalObject*, JSC::CallFrame*);
@@ -172,83 +182,8 @@ using JSObject = JSC::JSObject;
using JSNonFinalObject = JSC::JSNonFinalObject;
namespace JSCastingHelpers = JSC::JSCastingHelpers;
#if !OS(WINDOWS)
#include <dlfcn.h>
#endif
#include "IDLTypes.h"
#include "JSAbortAlgorithm.h"
#include "JSDOMAttribute.h"
#include "JSByteLengthQueuingStrategy.h"
#include "JSCountQueuingStrategy.h"
#include "JSReadableByteStreamController.h"
#include "JSReadableStream.h"
#include "JSReadableStreamBYOBReader.h"
#include "JSReadableStreamBYOBRequest.h"
#include "JSReadableStreamDefaultController.h"
#include "JSReadableStreamDefaultReader.h"
#include "JSTransformStream.h"
#include "JSTransformStreamDefaultController.h"
#include "JSWritableStream.h"
#include "JSWritableStreamDefaultController.h"
#include "JSWritableStreamDefaultWriter.h"
#include "JavaScriptCore/BuiltinNames.h"
#include "JSTextEncoder.h"
#include "StructuredClone.h"
#include "JSWebSocket.h"
#include "JSMessageEvent.h"
#include "JSEventListener.h"
#include "ReadableStream.h"
#include "JSSink.h"
#include "ImportMetaObject.h"
#include <JavaScriptCore/DOMJITAbstractHeap.h>
#include "DOMJITIDLConvert.h"
#include "DOMJITIDLType.h"
#include "DOMJITIDLTypeFilter.h"
#include "DOMJITHelpers.h"
#include <JavaScriptCore/DFGAbstractHeap.h>
#include "JSDOMFormData.h"
#include "JSDOMBinding.h"
#include "JSDOMConstructor.h"
#include "JSDOMConvertBase.h"
#include "JSDOMConvertBoolean.h"
#include "JSDOMConvertDictionary.h"
#include "JSDOMConvertEventListener.h"
#include "JSDOMConvertInterface.h"
#include "JSDOMConvertNullable.h"
#include "JSDOMConvertStrings.h"
#include "JSDOMConvertUnion.h"
#include "AddEventListenerOptions.h"
#include "JSSocketAddress.h"
#include "ErrorStackTrace.h"
#include "CallSite.h"
#include "CallSitePrototype.h"
#include "DOMWrapperWorld-class.h"
#include "CommonJSModuleRecord.h"
#include <wtf/RAMSize.h>
#include <wtf/text/Base64.h>
#include "simdutf.h"
#include "libusockets.h"
#include "KeyObject.h"
#include "webcrypto/JSCryptoKey.h"
#include "webcrypto/JSSubtleCrypto.h"
constexpr size_t DEFAULT_ERROR_STACK_TRACE_LIMIT = 10;
#ifdef __APPLE__
#include <sys/sysctl.h>
#elif defined(__linux__)
// for sysconf
#include <unistd.h>
#endif
#include "ProcessBindingTTYWrap.h"
// #include <iostream>
static bool has_loaded_jsc = false;
@@ -1713,10 +1648,6 @@ JSC_DEFINE_CUSTOM_SETTER(noop_setter,
return true;
}
// If you are looking for $lazy / functionLazyLoad
// it is moved to JS2Native.cpp, and is called $cpp and $zig
// see <todo>.md for more information
static inline JSC::EncodedJSValue jsFunctionAddEventListenerBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, Zig::GlobalObject* castedThis)
{
auto& vm = JSC::getVM(lexicalGlobalObject);
@@ -3038,76 +2969,6 @@ void GlobalObject::finishCreation(VM& vm)
ASSERT(classInfo());
}
JSC_DEFINE_HOST_FUNCTION(jsFunctionPostMessage,
(JSC::JSGlobalObject * leixcalGlobalObject, JSC::CallFrame* callFrame))
{
JSC::VM& vm = leixcalGlobalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
Zig::GlobalObject* globalObject = jsDynamicCast<Zig::GlobalObject*>(leixcalGlobalObject);
if (UNLIKELY(!globalObject))
return JSValue::encode(jsUndefined());
Worker* worker = WebWorker__getParentWorker(globalObject->bunVM());
if (worker == nullptr)
return JSValue::encode(jsUndefined());
ScriptExecutionContext* context = worker->scriptExecutionContext();
if (!context)
return JSValue::encode(jsUndefined());
auto throwScope = DECLARE_THROW_SCOPE(vm);
JSC::JSValue value = callFrame->argument(0);
JSC::JSValue options = callFrame->argument(1);
Vector<JSC::Strong<JSC::JSObject>> transferList;
if (options.isObject()) {
JSC::JSObject* optionsObject = options.getObject();
JSC::JSValue transferListValue = optionsObject->get(globalObject, vm.propertyNames->transfer);
if (transferListValue.isObject()) {
JSC::JSObject* transferListObject = transferListValue.getObject();
if (auto* transferListArray = jsDynamicCast<JSC::JSArray*>(transferListObject)) {
for (unsigned i = 0; i < transferListArray->length(); i++) {
JSC::JSValue transferListValue = transferListArray->get(globalObject, i);
if (transferListValue.isObject()) {
JSC::JSObject* transferListObject = transferListValue.getObject();
transferList.append(JSC::Strong<JSC::JSObject>(vm, transferListObject));
}
}
}
}
}
Vector<RefPtr<MessagePort>> ports;
ExceptionOr<Ref<SerializedScriptValue>> serialized = SerializedScriptValue::create(*globalObject, value, WTFMove(transferList), ports, SerializationForStorage::No, SerializationContext::WorkerPostMessage);
if (serialized.hasException()) {
WebCore::propagateException(*globalObject, throwScope, serialized.releaseException());
return JSValue::encode(jsUndefined());
}
ExceptionOr<Vector<TransferredMessagePort>> disentangledPorts = MessagePort::disentanglePorts(WTFMove(ports));
if (disentangledPorts.hasException()) {
WebCore::propagateException(*globalObject, throwScope, serialized.releaseException());
return JSValue::encode(jsUndefined());
}
MessageWithMessagePorts messageWithMessagePorts { serialized.releaseReturnValue(), disentangledPorts.releaseReturnValue() };
ScriptExecutionContext::postTaskTo(context->identifier(), [message = messageWithMessagePorts, protectedThis = Ref { *worker }, ports](ScriptExecutionContext& context) mutable {
Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(context.jsGlobalObject());
auto ports = MessagePort::entanglePorts(context, WTFMove(message.transferredPorts));
auto event = MessageEvent::create(*globalObject, message.message.releaseNonNull(), std::nullopt, WTFMove(ports));
protectedThis->dispatchEvent(event.event);
});
return JSValue::encode(jsUndefined());
}
JSC_DEFINE_CUSTOM_GETTER(JSDOMFileConstructor_getter, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, PropertyName))
{
Zig::GlobalObject* bunGlobalObject = jsCast<Zig::GlobalObject*>(globalObject);

View File

@@ -41,7 +41,6 @@ class InternalModuleRegistry;
#include "BunPlugin.h"
#include "JSMockFunction.h"
#include "InternalModuleRegistry.h"
#include "ProcessBindingConstants.h"
#include "WebCoreJSBuiltins.h"
#include "headers-handwritten.h"
#include "BunCommonStrings.h"

View File

@@ -286,7 +286,7 @@ void MessagePort::dispatchMessages()
if (!context || !context->jsGlobalObject())
return;
ASSERT(context->isContextThread());
// ASSERT(context->isContextThread());
// bool contextIsWorker = is<WorkerGlobalScope>(*context);
for (auto& message : messages) {

View File

@@ -71,7 +71,7 @@ void MessagePortChannelProviderImpl::takeAllMessagesForPort(const MessagePortIde
{
// It is the responsibility of outerCallback to get itself to the appropriate thread (e.g. WebWorker thread)
auto callback = [outerCallback = WTFMove(outerCallback)](Vector<MessageWithMessagePorts>&& messages, CompletionHandler<void()>&& messageDeliveryCallback) mutable {
ASSERT(isMainThread());
// ASSERT(isMainThread());
outerCallback(WTFMove(messages), WTFMove(messageDeliveryCallback));
};

View File

@@ -488,4 +488,74 @@ JSValue createNodeWorkerThreadsBinding(Zig::GlobalObject* globalObject)
return array;
}
JSC_DEFINE_HOST_FUNCTION(jsFunctionPostMessage,
(JSC::JSGlobalObject * leixcalGlobalObject, JSC::CallFrame* callFrame))
{
JSC::VM& vm = leixcalGlobalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
Zig::GlobalObject* globalObject = jsDynamicCast<Zig::GlobalObject*>(leixcalGlobalObject);
if (UNLIKELY(!globalObject))
return JSValue::encode(jsUndefined());
Worker* worker = WebWorker__getParentWorker(globalObject->bunVM());
if (worker == nullptr)
return JSValue::encode(jsUndefined());
ScriptExecutionContext* context = worker->scriptExecutionContext();
if (!context)
return JSValue::encode(jsUndefined());
auto throwScope = DECLARE_THROW_SCOPE(vm);
JSC::JSValue value = callFrame->argument(0);
JSC::JSValue options = callFrame->argument(1);
Vector<JSC::Strong<JSC::JSObject>> transferList;
if (options.isObject()) {
JSC::JSObject* optionsObject = options.getObject();
JSC::JSValue transferListValue = optionsObject->get(globalObject, vm.propertyNames->transfer);
if (transferListValue.isObject()) {
JSC::JSObject* transferListObject = transferListValue.getObject();
if (auto* transferListArray = jsDynamicCast<JSC::JSArray*>(transferListObject)) {
for (unsigned i = 0; i < transferListArray->length(); i++) {
JSC::JSValue transferListValue = transferListArray->get(globalObject, i);
if (transferListValue.isObject()) {
JSC::JSObject* transferListObject = transferListValue.getObject();
transferList.append(JSC::Strong<JSC::JSObject>(vm, transferListObject));
}
}
}
}
}
Vector<RefPtr<MessagePort>> ports;
ExceptionOr<Ref<SerializedScriptValue>> serialized = SerializedScriptValue::create(*globalObject, value, WTFMove(transferList), ports, SerializationForStorage::No, SerializationContext::WorkerPostMessage);
if (serialized.hasException()) {
WebCore::propagateException(*globalObject, throwScope, serialized.releaseException());
return JSValue::encode(jsUndefined());
}
ExceptionOr<Vector<TransferredMessagePort>> disentangledPorts = MessagePort::disentanglePorts(WTFMove(ports));
if (disentangledPorts.hasException()) {
WebCore::propagateException(*globalObject, throwScope, serialized.releaseException());
return JSValue::encode(jsUndefined());
}
MessageWithMessagePorts messageWithMessagePorts { serialized.releaseReturnValue(), disentangledPorts.releaseReturnValue() };
ScriptExecutionContext::postTaskTo(context->identifier(), [message = messageWithMessagePorts, protectedThis = Ref { *worker }, ports](ScriptExecutionContext& context) mutable {
Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(context.jsGlobalObject());
auto ports = MessagePort::entanglePorts(context, WTFMove(message.transferredPorts));
auto event = MessageEvent::create(*globalObject, message.message.releaseNonNull(), std::nullopt, WTFMove(ports));
protectedThis->dispatchEvent(event.event);
});
return JSValue::encode(jsUndefined());
}
} // namespace WebCore

View File

@@ -142,4 +142,6 @@ private:
JSValue createNodeWorkerThreadsBinding(Zig::GlobalObject* globalObject);
JSC_DECLARE_HOST_FUNCTION(jsFunctionPostMessage);
} // namespace WebCore

View File

@@ -124,9 +124,10 @@ function fakeParentPort() {
},
});
const postMessage = $newCppFunction("ZigGlobalObject.cpp", "jsFunctionPostMessage", 1);
Object.defineProperty(fake, "postMessage", {
value(...args: [any, any]) {
return self.postMessage(...args);
return postMessage(...args);
},
});

View File

@@ -0,0 +1,15 @@
import { isMainThread, parentPort, workerData } from "worker_threads";
if (parentPort === null) throw new Error("worker_threads.parentPort is null");
if (isMainThread) throw new Error("worker_threads.isMainThread is wrong");
Object.assign(global, {
postMessage: message => {
parentPort.postMessage(message);
},
});
parentPort.on("message", m => {
postMessage("Hello from worker!");
});

View File

@@ -176,3 +176,13 @@ test("receiveMessageOnPort works as FIFO", () => {
}).toThrow();
}
});
test("you can override globalThis.postMessage", async () => {
const worker = new Worker(new URL("./worker-override-postMessage.js", import.meta.url).href);
const message = await new Promise(resolve => {
worker.on("message", resolve);
worker.postMessage("Hello from worker!");
});
expect(message).toBe("Hello from worker!");
await worker.terminate();
});