aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Dylan Conway <35280289+dylan-conway@users.noreply.github.com> 2023-08-01 18:40:02 -0700
committerGravatar GitHub <noreply@github.com> 2023-08-01 18:40:02 -0700
commit6c40d6f2f51474c6a38d509417db903385f48f2b (patch)
treed441b10de162e443d572b47ca9c278e3cd345f26 /src
parent0ced5520e6ae8061b2acaab2cbc26431e10182a6 (diff)
downloadbun-6c40d6f2f51474c6a38d509417db903385f48f2b.tar.gz
bun-6c40d6f2f51474c6a38d509417db903385f48f2b.tar.zst
bun-6c40d6f2f51474c6a38d509417db903385f48f2b.zip
add `BroadcastChannel` (#3922)
* copy and format * update `SerializedScriptValue.cpp` * use `expect().fail()` in message channel tests * rename `BroadcastChannelIdentifier.h` * copy registries * progress and tests * cleanup * worker and broadcast channel test * `BroadcastChannel` ref and unref * `MessagePort` ref, unref, and hasRef * remove `SecurityContext.cpp/h` * add types
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/bindings/ScriptExecutionContext.h6
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp8
-rw-r--r--src/bun.js/bindings/webcore/BroadcastChannel.cpp330
-rw-r--r--src/bun.js/bindings/webcore/BroadcastChannel.h109
-rw-r--r--src/bun.js/bindings/webcore/BroadcastChannelIdentifier.h35
-rw-r--r--src/bun.js/bindings/webcore/BroadcastChannelRegistry.h45
-rw-r--r--src/bun.js/bindings/webcore/BunBroadcastChannelRegistry.cpp52
-rw-r--r--src/bun.js/bindings/webcore/BunBroadcastChannelRegistry.h33
-rw-r--r--src/bun.js/bindings/webcore/EventTargetFactory.cpp4
-rw-r--r--src/bun.js/bindings/webcore/EventTargetHeaders.h4
-rw-r--r--src/bun.js/bindings/webcore/JSBroadcastChannel.cpp426
-rw-r--r--src/bun.js/bindings/webcore/JSBroadcastChannel.h99
-rw-r--r--src/bun.js/bindings/webcore/JSMessageEvent.cpp2
-rw-r--r--src/bun.js/bindings/webcore/JSMessagePort.cpp56
-rw-r--r--src/bun.js/bindings/webcore/MessagePort.cpp19
-rw-r--r--src/bun.js/bindings/webcore/MessagePort.h6
-rw-r--r--src/bun.js/bindings/webcore/SerializedScriptValue.cpp375
17 files changed, 1566 insertions, 43 deletions
diff --git a/src/bun.js/bindings/ScriptExecutionContext.h b/src/bun.js/bindings/ScriptExecutionContext.h
index 271c7e205..b32435240 100644
--- a/src/bun.js/bindings/ScriptExecutionContext.h
+++ b/src/bun.js/bindings/ScriptExecutionContext.h
@@ -3,6 +3,7 @@
#include "root.h"
#include "ActiveDOMObject.h"
#include "ContextDestructionObserver.h"
+#include "BunBroadcastChannelRegistry.h"
#include <wtf/CrossThreadTask.h>
#include <wtf/Function.h>
#include <wtf/HashSet.h>
@@ -81,6 +82,7 @@ public:
: m_vm(vm)
, m_globalObject(globalObject)
, m_identifier(0)
+ , m_broadcastChannelRegistry(BunBroadcastChannelRegistry::create())
{
regenerateIdentifier();
}
@@ -89,6 +91,7 @@ public:
: m_vm(vm)
, m_globalObject(globalObject)
, m_identifier(identifier)
+ , m_broadcastChannelRegistry(BunBroadcastChannelRegistry::create())
{
addToContextsMap();
}
@@ -210,6 +213,8 @@ public:
m_vm = &globalObject->vm();
}
+ BunBroadcastChannelRegistry& broadcastChannelRegistry() { return m_broadcastChannelRegistry; }
+
private:
JSC::VM* m_vm = nullptr;
JSC::JSGlobalObject* m_globalObject = nullptr;
@@ -219,6 +224,7 @@ private:
HashSet<MessagePort*> m_messagePorts;
HashSet<ContextDestructionObserver*> m_destructionObservers;
Vector<CompletionHandler<void()>> m_processMessageWithMessagePortsSoonHandlers;
+ Ref<BunBroadcastChannelRegistry> m_broadcastChannelRegistry;
bool m_willProcessMessageWithMessagePortsSoon { false };
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index 3776adb2b..7c1181921 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -121,7 +121,7 @@
#include "JSWorker.h"
#include "JSMessageChannel.h"
#include "JSMessagePort.h"
-// #include "JSBroadcastChannel.h"
+#include "JSBroadcastChannel.h"
#if ENABLE(REMOTE_INSPECTOR)
#include "JavaScriptCore/RemoteInspectorServer.h"
@@ -942,8 +942,8 @@ WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSMessageChannel);
WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSMessagePort);
WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSMessagePort);
-// WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSBroadcastChannel);
-// WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSBroadcastChannel);
+WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSBroadcastChannel);
+WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSBroadcastChannel);
JSC_DECLARE_CUSTOM_GETTER(JSEvent_getter);
@@ -4253,7 +4253,7 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm)
PUT_WEBCORE_GENERATED_CONSTRUCTOR("Worker"_s, JSWorker);
PUT_WEBCORE_GENERATED_CONSTRUCTOR("MessageChannel"_s, JSMessageChannel);
PUT_WEBCORE_GENERATED_CONSTRUCTOR("MessagePort"_s, JSMessagePort);
- // PUT_WEBCORE_GENERATED_CONSTRUCTOR("BroadcastChannel"_s, JSBroadcastChannel);
+ PUT_WEBCORE_GENERATED_CONSTRUCTOR("BroadcastChannel"_s, JSBroadcastChannel);
putDirectCustomAccessor(vm, builtinNames.TransformStreamPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_TransformStreamConstructor, nullptr), attributesForStructure(static_cast<unsigned>(JSC::PropertyAttribute::DontEnum)));
putDirectCustomAccessor(vm, builtinNames.TransformStreamPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_TransformStreamConstructor, nullptr), attributesForStructure(static_cast<unsigned>(JSC::PropertyAttribute::DontEnum)));
diff --git a/src/bun.js/bindings/webcore/BroadcastChannel.cpp b/src/bun.js/bindings/webcore/BroadcastChannel.cpp
new file mode 100644
index 000000000..74ff150e6
--- /dev/null
+++ b/src/bun.js/bindings/webcore/BroadcastChannel.cpp
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BroadcastChannel.h"
+
+#include "BunClientData.h"
+#include "BroadcastChannelRegistry.h"
+#include "EventNames.h"
+#include "EventTarget.h"
+#include "MessageEvent.h"
+// #include "Page.h"
+// #include "PartitionedSecurityOrigin.h"
+// #include "SecurityOrigin.h"
+#include "SerializedScriptValue.h"
+// #include "WorkerGlobalScope.h"
+#include "BunWorkerGlobalScope.h"
+// #include "WorkerLoaderProxy.h"
+// #include "WorkerThread.h"
+#include <wtf/CallbackAggregator.h>
+#include <wtf/HashMap.h>
+#include <wtf/IsoMallocInlines.h>
+#include <wtf/MainThread.h>
+#include <wtf/Scope.h>
+
+extern "C" void Bun__eventLoop__incrementRefConcurrently(void* bunVM, int delta);
+
+namespace WebCore {
+
+WTF_MAKE_ISO_ALLOCATED_IMPL(BroadcastChannel);
+
+static Lock allBroadcastChannelsLock;
+static HashMap<BroadcastChannelIdentifier, BroadcastChannel*>& allBroadcastChannels() WTF_REQUIRES_LOCK(allBroadcastChannelsLock)
+{
+ static NeverDestroyed<HashMap<BroadcastChannelIdentifier, BroadcastChannel*>> map;
+ return map;
+}
+
+static Lock channelToContextIdentifierLock;
+static HashMap<BroadcastChannelIdentifier, ScriptExecutionContextIdentifier>& channelToContextIdentifier()
+{
+ ASSERT(isMainThread());
+ static NeverDestroyed<HashMap<BroadcastChannelIdentifier, ScriptExecutionContextIdentifier>> map;
+ return map;
+}
+
+// static PartitionedSecurityOrigin partitionedSecurityOriginFromContext(ScriptExecutionContext& context)
+// {
+// Ref securityOrigin { *context.securityOrigin() };
+// Ref topOrigin { context.settingsValues().broadcastChannelOriginPartitioningEnabled ? context.topOrigin() : securityOrigin.get() };
+// return { WTFMove(topOrigin), WTFMove(securityOrigin) };
+// }
+
+class BroadcastChannel::MainThreadBridge : public ThreadSafeRefCounted<MainThreadBridge, WTF::DestructionThread::Main> {
+public:
+ static Ref<MainThreadBridge> create(BroadcastChannel& channel, const String& name, ScriptExecutionContext& context)
+ {
+ return adoptRef(*new MainThreadBridge(channel, name, context));
+ }
+
+ void registerChannel(ScriptExecutionContext&);
+ void unregisterChannel();
+ void postMessage(Ref<SerializedScriptValue>&&);
+
+ String name() const { return m_name.isolatedCopy(); }
+ BroadcastChannelIdentifier identifier() const { return m_identifier; }
+ ScriptExecutionContextIdentifier contextId() const { return m_contextId; }
+
+private:
+ MainThreadBridge(BroadcastChannel&, const String& name, ScriptExecutionContext&);
+
+ void ensureOnMainThread(Function<void(void*)>&&);
+
+ // WeakPtr<BroadcastChannel, WeakPtrImplWithEventTargetData> m_broadcastChannel;
+ WeakPtr<BroadcastChannel> m_broadcastChannel;
+ const BroadcastChannelIdentifier m_identifier;
+ const String m_name; // Main thread only.
+ ScriptExecutionContextIdentifier m_contextId;
+ // PartitionedSecurityOrigin m_origin; // Main thread only.
+};
+
+BroadcastChannel::MainThreadBridge::MainThreadBridge(BroadcastChannel& channel, const String& name, ScriptExecutionContext& context)
+ : m_broadcastChannel(channel)
+ , m_identifier(BroadcastChannelIdentifier::generate())
+ , m_name(name.isolatedCopy())
+ , m_contextId(context.identifier())
+// , m_origin(partitionedSecurityOriginFromContext(*channel.scriptExecutionContext()).isolatedCopy())
+{
+}
+
+void BroadcastChannel::MainThreadBridge::ensureOnMainThread(Function<void(void*)>&& task)
+{
+ ASSERT(m_broadcastChannel);
+ if (!m_broadcastChannel)
+ return;
+
+ auto* context = m_broadcastChannel->scriptExecutionContext();
+ if (!context)
+ return;
+ ASSERT(context->isContextThread());
+
+ Ref protectedThis { *this };
+
+ ScriptExecutionContext::ensureOnMainThread([protectedThis = WTFMove(protectedThis), task = WTFMove(task)](auto& context) {
+ task(nullptr);
+ });
+}
+
+void BroadcastChannel::MainThreadBridge::registerChannel(ScriptExecutionContext& context)
+{
+ Ref protectedThis { *this };
+
+ ScriptExecutionContext::ensureOnMainThread([protectedThis = WTFMove(protectedThis), contextId = context.identifier()](auto& context) mutable {
+ context.broadcastChannelRegistry().registerChannel(protectedThis->m_name, protectedThis->m_identifier);
+ channelToContextIdentifier().add(protectedThis->m_identifier, contextId);
+ });
+}
+
+void BroadcastChannel::MainThreadBridge::unregisterChannel()
+{
+ Ref protectedThis { *this };
+
+ ScriptExecutionContext::ensureOnMainThread([protectedThis = WTFMove(protectedThis)](auto& context) {
+ context.broadcastChannelRegistry().unregisterChannel(protectedThis->m_name, protectedThis->m_identifier);
+ channelToContextIdentifier().remove(protectedThis->m_identifier);
+ });
+}
+
+void BroadcastChannel::MainThreadBridge::postMessage(Ref<SerializedScriptValue>&& message)
+{
+ Ref protectedThis { *this };
+
+ ScriptExecutionContext::ensureOnMainThread([protectedThis = WTFMove(protectedThis), message = WTFMove(message)](auto& context) mutable {
+ context.broadcastChannelRegistry().postMessage(protectedThis->m_name, protectedThis->m_identifier, WTFMove(message));
+ });
+}
+
+BroadcastChannel::BroadcastChannel(ScriptExecutionContext& context, const String& name)
+ // : ActiveDOMObject(&context)
+ : ContextDestructionObserver(&context)
+ , m_mainThreadBridge(MainThreadBridge::create(*this, name, context))
+ , m_contextId(context.identifier())
+{
+ {
+ Locker locker { allBroadcastChannelsLock };
+ allBroadcastChannels().add(m_mainThreadBridge->identifier(), this);
+ }
+ m_mainThreadBridge->registerChannel(context);
+ jsRef(context.jsGlobalObject());
+}
+
+BroadcastChannel::~BroadcastChannel()
+{
+ close();
+ {
+ Locker locker { allBroadcastChannelsLock };
+ allBroadcastChannels().remove(m_mainThreadBridge->identifier());
+ }
+}
+
+BroadcastChannelIdentifier BroadcastChannel::identifier() const
+{
+ return m_mainThreadBridge->identifier();
+}
+
+String BroadcastChannel::name() const
+{
+ return m_mainThreadBridge->name();
+}
+
+ScriptExecutionContextIdentifier BroadcastChannel::contextIdForBroadcastChannelId(BroadcastChannelIdentifier identifier)
+{
+ Locker locker { channelToContextIdentifierLock };
+ return channelToContextIdentifier().get(identifier);
+}
+
+ScriptExecutionContext* BroadcastChannel::scriptExecutionContext() const
+{
+ return ScriptExecutionContext::getScriptExecutionContext(m_mainThreadBridge->contextId());
+}
+
+ExceptionOr<void> BroadcastChannel::postMessage(JSC::JSGlobalObject& globalObject, JSC::JSValue message)
+{
+ if (!isEligibleForMessaging())
+ return {};
+
+ if (m_isClosed)
+ return Exception { InvalidStateError, "This BroadcastChannel is closed"_s };
+
+ Vector<RefPtr<MessagePort>> ports;
+ auto messageData = SerializedScriptValue::create(globalObject, message, {}, ports, SerializationForStorage::No, SerializationContext::WorkerPostMessage);
+ if (messageData.hasException())
+ return messageData.releaseException();
+ ASSERT(ports.isEmpty());
+
+ m_mainThreadBridge->postMessage(messageData.releaseReturnValue());
+ return {};
+}
+
+void BroadcastChannel::close()
+{
+ if (m_isClosed)
+ return;
+
+ m_isClosed = true;
+ m_mainThreadBridge->unregisterChannel();
+}
+
+void BroadcastChannel::dispatchMessageTo(BroadcastChannelIdentifier channelIdentifier, Ref<SerializedScriptValue>&& message)
+{
+ ASSERT(isMainThread());
+
+ auto contextIdentifier = channelToContextIdentifier().get(channelIdentifier);
+ if (!contextIdentifier)
+ return;
+
+ ScriptExecutionContext::ensureOnContextThread(contextIdentifier, [channelIdentifier, message = WTFMove(message)](auto&) mutable {
+ RefPtr<BroadcastChannel> channel;
+ {
+ Locker locker { allBroadcastChannelsLock };
+ channel = allBroadcastChannels().get(channelIdentifier);
+ }
+ if (channel)
+ channel->dispatchMessage(WTFMove(message));
+ });
+}
+
+void BroadcastChannel::dispatchMessage(Ref<SerializedScriptValue>&& message)
+{
+ if (!isEligibleForMessaging())
+ return;
+
+ if (m_isClosed)
+ return;
+
+ ScriptExecutionContext::postTaskTo(contextIdForBroadcastChannelId(m_mainThreadBridge->identifier()), [this, message = WTFMove(message)](ScriptExecutionContext& context) mutable {
+ if (m_isClosed)
+ return;
+
+ auto* globalObject = context.jsGlobalObject();
+ if (!globalObject)
+ return;
+
+ auto& vm = globalObject->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ Vector<RefPtr<MessagePort>> dummyPorts;
+ auto event = MessageEvent::create(*globalObject, WTFMove(message), {}, {}, std::nullopt, WTFMove(dummyPorts));
+ if (UNLIKELY(scope.exception())) {
+ // Currently, we assume that the only way we can get here is if we have a termination.
+ RELEASE_ASSERT(vm.hasPendingTerminationException());
+ return;
+ }
+
+ dispatchEvent(event.event);
+ });
+}
+
+// const char* BroadcastChannel::activeDOMObjectName() const
+// {
+// return "BroadcastChannel";
+// }
+
+void BroadcastChannel::eventListenersDidChange()
+{
+ m_hasRelevantEventListener = hasEventListeners(eventNames().messageEvent);
+}
+
+// bool BroadcastChannel::virtualHasPendingActivity() const
+// {
+// return !m_isClosed && m_hasRelevantEventListener;
+// }
+
+bool BroadcastChannel::hasPendingActivity() const
+{
+ return !m_isClosed && m_hasRelevantEventListener;
+}
+
+// https://html.spec.whatwg.org/#eligible-for-messaging
+bool BroadcastChannel::isEligibleForMessaging() const
+{
+ auto* context = scriptExecutionContext();
+ if (!context)
+ return false;
+
+ // if (auto document = dynamicDowncast<Document>(*context))
+ // return document->isFullyActive();
+
+ return true;
+ // return !downcast<GlobalScope>(*context).isClosing();
+}
+
+void BroadcastChannel::jsRef(JSGlobalObject* lexicalGlobalObject)
+{
+ if (!m_hasRef) {
+ m_hasRef = true;
+ Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(lexicalGlobalObject->vm())->bunVM, 1);
+ }
+}
+
+void BroadcastChannel::jsUnref(JSGlobalObject* lexicalGlobalObject)
+{
+ if (m_hasRef) {
+ m_hasRef = false;
+ Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(lexicalGlobalObject->vm())->bunVM, -1);
+ }
+}
+
+} // namespace WebCore
diff --git a/src/bun.js/bindings/webcore/BroadcastChannel.h b/src/bun.js/bindings/webcore/BroadcastChannel.h
new file mode 100644
index 000000000..764f3db93
--- /dev/null
+++ b/src/bun.js/bindings/webcore/BroadcastChannel.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ActiveDOMObject.h"
+#include "ContextDestructionObserver.h"
+#include "BroadcastChannelIdentifier.h"
+// #include "ClientOrigin.h"
+#include "EventTarget.h"
+#include "ExceptionOr.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+class JSGlobalObject;
+class JSValue;
+}
+
+namespace WebCore {
+
+class SerializedScriptValue;
+
+class BroadcastChannel : public RefCounted<BroadcastChannel>, public EventTarget /*, public ActiveDOMObject*/, public ContextDestructionObserver {
+ WTF_MAKE_ISO_ALLOCATED(BroadcastChannel);
+
+public:
+ static Ref<BroadcastChannel> create(ScriptExecutionContext& context, const String& name)
+ {
+ auto channel = adoptRef(*new BroadcastChannel(context, name));
+ // channel->suspendIfNeeded();
+ return channel;
+ }
+ ~BroadcastChannel();
+
+ using RefCounted<BroadcastChannel>::ref;
+ using RefCounted<BroadcastChannel>::deref;
+
+ BroadcastChannelIdentifier identifier() const;
+ String name() const;
+
+ ExceptionOr<void> postMessage(JSC::JSGlobalObject&, JSC::JSValue message);
+ void close();
+
+ WEBCORE_EXPORT static void dispatchMessageTo(BroadcastChannelIdentifier, Ref<SerializedScriptValue>&&);
+
+ static ScriptExecutionContextIdentifier contextIdForBroadcastChannelId(BroadcastChannelIdentifier);
+
+ bool hasPendingActivity() const;
+
+ void jsRef(JSGlobalObject*);
+ void jsUnref(JSGlobalObject*);
+
+private:
+ BroadcastChannel(ScriptExecutionContext&, const String& name);
+
+ void dispatchMessage(Ref<SerializedScriptValue>&&);
+
+ bool isEligibleForMessaging() const;
+
+ // EventTarget
+ EventTargetInterface eventTargetInterface() const final { return BroadcastChannelEventTargetInterfaceType; }
+ ScriptExecutionContext* scriptExecutionContext() const;
+ void refEventTarget() final { RefCounted<BroadcastChannel>::ref(); }
+ void derefEventTarget() final { RefCounted<BroadcastChannel>::deref(); }
+ void eventListenersDidChange() final;
+
+ EventTargetData* eventTargetData() final { return &m_eventTargetData; }
+ EventTargetData* eventTargetDataConcurrently() final { return &m_eventTargetData; }
+ EventTargetData& ensureEventTargetData() final { return m_eventTargetData; }
+
+ EventTargetData m_eventTargetData;
+
+ // ActiveDOMObject
+ // const char* activeDOMObjectName() const final;
+ // bool virtualHasPendingActivity() const final;
+ // void stop() final { close(); }
+
+ class MainThreadBridge;
+ Ref<MainThreadBridge> m_mainThreadBridge;
+ bool m_isClosed { false };
+ bool m_hasRelevantEventListener { false };
+ bool m_hasRef { false };
+ ScriptExecutionContextIdentifier m_contextId;
+};
+
+} // namespace WebCore
diff --git a/src/bun.js/bindings/webcore/BroadcastChannelIdentifier.h b/src/bun.js/bindings/webcore/BroadcastChannelIdentifier.h
new file mode 100644
index 000000000..acddb06d5
--- /dev/null
+++ b/src/bun.js/bindings/webcore/BroadcastChannelIdentifier.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/ObjectIdentifier.h>
+
+namespace WebCore {
+
+enum BroadcastChannelIdentifierType {};
+using BroadcastChannelIdentifier = AtomicObjectIdentifier<BroadcastChannelIdentifierType>;
+
+} // namespace WebCore
diff --git a/src/bun.js/bindings/webcore/BroadcastChannelRegistry.h b/src/bun.js/bindings/webcore/BroadcastChannelRegistry.h
new file mode 100644
index 000000000..70abf842a
--- /dev/null
+++ b/src/bun.js/bindings/webcore/BroadcastChannelRegistry.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "BroadcastChannelIdentifier.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+struct PartitionedSecurityOrigin;
+class SerializedScriptValue;
+
+class BroadcastChannelRegistry : public RefCounted<BroadcastChannelRegistry> {
+public:
+ virtual ~BroadcastChannelRegistry() {}
+ virtual void registerChannel(const String& name, BroadcastChannelIdentifier) = 0;
+ virtual void unregisterChannel(const String& name, BroadcastChannelIdentifier) = 0;
+ virtual void postMessage(const String& name, BroadcastChannelIdentifier source, Ref<SerializedScriptValue>&&) = 0;
+};
+
+} // namespace WebCore
diff --git a/src/bun.js/bindings/webcore/BunBroadcastChannelRegistry.cpp b/src/bun.js/bindings/webcore/BunBroadcastChannelRegistry.cpp
new file mode 100644
index 000000000..258d29717
--- /dev/null
+++ b/src/bun.js/bindings/webcore/BunBroadcastChannelRegistry.cpp
@@ -0,0 +1,52 @@
+#include "config.h"
+
+#include "BunBroadcastChannelRegistry.h"
+#include "webcore/BroadcastChannel.h"
+#include "webcore/MessageWithMessagePorts.h"
+#include <wtf/CallbackAggregator.h>
+
+namespace WebCore {
+
+void BunBroadcastChannelRegistry::registerChannel(const String& name, BroadcastChannelIdentifier identifier)
+{
+ auto& channels = m_channelsForName.ensure(name, [] { return Vector<BroadcastChannelIdentifier> {}; }).iterator->value;
+ channels.append(identifier);
+}
+
+void BunBroadcastChannelRegistry::unregisterChannel(const String& name, BroadcastChannelIdentifier identifier)
+{
+ auto channels = m_channelsForName.find(name);
+ if (channels == m_channelsForName.end())
+ return;
+
+ auto& channelIds = channels->value;
+ channelIds.removeFirst(identifier);
+}
+
+void BunBroadcastChannelRegistry::postMessage(const String& name, BroadcastChannelIdentifier source, Ref<SerializedScriptValue>&& message)
+{
+ postMessageLocally(name, source, message.copyRef());
+}
+
+void BunBroadcastChannelRegistry::postMessageLocally(const String& name, BroadcastChannelIdentifier sourceInProcess, Ref<SerializedScriptValue>&& message)
+{
+ auto channels = m_channelsForName.find(name);
+ if (channels == m_channelsForName.end())
+ return;
+
+ auto& channelIds = channels->value;
+ for (auto& channelId : channelIds) {
+ if (channelId == sourceInProcess)
+ continue;
+
+ BroadcastChannel::dispatchMessageTo(channelId, message.copyRef());
+ }
+}
+
+void BunBroadcastChannelRegistry::postMessageToRemote(const String& name, MessageWithMessagePorts&& message)
+{
+ // auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
+ // PartitionedSecurityOrigin origin { clientOrigin.topOrigin.securityOrigin(), clientOrigin.clientOrigin.securityOrigin() };
+ // postMessageLocally(origin, name, std::nullopt, *message.message, callbackAggregator.copyRef());
+}
+}
diff --git a/src/bun.js/bindings/webcore/BunBroadcastChannelRegistry.h b/src/bun.js/bindings/webcore/BunBroadcastChannelRegistry.h
new file mode 100644
index 000000000..5576b732e
--- /dev/null
+++ b/src/bun.js/bindings/webcore/BunBroadcastChannelRegistry.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "BroadcastChannelRegistry.h"
+#include "wtf/CallbackAggregator.h"
+#include "wtf/Vector.h"
+#include "wtf/HashMap.h"
+
+namespace WebCore {
+
+struct MessageWithMessagePorts;
+
+class BunBroadcastChannelRegistry final : public BroadcastChannelRegistry {
+public:
+ BunBroadcastChannelRegistry() = default;
+ static Ref<BunBroadcastChannelRegistry> create()
+ {
+ return adoptRef(*new BunBroadcastChannelRegistry);
+ }
+
+ void registerChannel(const String& name, BroadcastChannelIdentifier) final;
+ void unregisterChannel(const String& name, BroadcastChannelIdentifier) final;
+ void postMessage(const String& name, BroadcastChannelIdentifier source, Ref<SerializedScriptValue>&&) final;
+
+ // void didReceivedMessage(IPC::Connection&, IPC::Decoder&);
+
+ HashMap<String, Vector<BroadcastChannelIdentifier>> m_channelsForName;
+
+private:
+ void postMessageToRemote(const String& name, MessageWithMessagePorts&&);
+ void postMessageLocally(const String& name, BroadcastChannelIdentifier sourceInProgress, Ref<SerializedScriptValue>&&);
+};
+
+}
diff --git a/src/bun.js/bindings/webcore/EventTargetFactory.cpp b/src/bun.js/bindings/webcore/EventTargetFactory.cpp
index 867d007be..809cceda9 100644
--- a/src/bun.js/bindings/webcore/EventTargetFactory.cpp
+++ b/src/bun.js/bindings/webcore/EventTargetFactory.cpp
@@ -57,8 +57,8 @@ JSC::JSValue toJS(JSC::JSGlobalObject* state, JSDOMGlobalObject* globalObject, E
// case BaseAudioContextEventTargetInterfaceType:
// return toJS(state, globalObject, static_cast<BaseAudioContext&>(impl));
// #endif
- // case BroadcastChannelEventTargetInterfaceType:
- // return toJS(state, globalObject, static_cast<BroadcastChannel&>(impl));
+ case BroadcastChannelEventTargetInterfaceType:
+ return toJS(state, globalObject, static_cast<BroadcastChannel&>(impl));
// case ClipboardEventTargetInterfaceType:
// return toJS(state, globalObject, static_cast<Clipboard&>(impl));
// case DOMApplicationCacheEventTargetInterfaceType:
diff --git a/src/bun.js/bindings/webcore/EventTargetHeaders.h b/src/bun.js/bindings/webcore/EventTargetHeaders.h
index 89c1f2393..6c81e59fd 100644
--- a/src/bun.js/bindings/webcore/EventTargetHeaders.h
+++ b/src/bun.js/bindings/webcore/EventTargetHeaders.h
@@ -46,7 +46,7 @@
// #include "BaseAudioContext.h"
// #include "JSBaseAudioContext.h"
// #endif
-// #include "BroadcastChannel.h"
+#include "BroadcastChannel.h"
// #include "Clipboard.h"
// #include "DOMApplicationCache.h"
// #include "DOMWindow.h"
@@ -59,7 +59,7 @@
// #include "IDBOpenDBRequest.h"
// #include "IDBRequest.h"
// #include "IDBTransaction.h"
-// #include "JSBroadcastChannel.h"
+#include "JSBroadcastChannel.h"
// #include "JSClipboard.h"
// #include "JSDOMApplicationCache.h"
// #include "JSDOMWindow.h"
diff --git a/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp b/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp
new file mode 100644
index 000000000..694044cca
--- /dev/null
+++ b/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp
@@ -0,0 +1,426 @@
+/*
+ This file is part of the WebKit open source project.
+ This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "JSBroadcastChannel.h"
+
+#include "ActiveDOMObject.h"
+#include "EventNames.h"
+#include "ExtendedDOMClientIsoSubspaces.h"
+#include "ExtendedDOMIsoSubspaces.h"
+#include "IDLTypes.h"
+#include "JSDOMAttribute.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructor.h"
+#include "JSDOMConvertAny.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMConvertInterface.h"
+#include "JSDOMConvertStrings.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMGlobalObjectInlines.h"
+#include "JSDOMOperation.h"
+#include "JSDOMWrapperCache.h"
+#include "JSEventListener.h"
+#include "ScriptExecutionContext.h"
+#include "WebCoreJSClientData.h"
+#include <JavaScriptCore/HeapAnalyzer.h>
+#include <JavaScriptCore/JSCInlines.h>
+#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h>
+#include <JavaScriptCore/SlotVisitorMacros.h>
+#include <JavaScriptCore/SubspaceInlines.h>
+#include <wtf/GetPtr.h>
+#include <wtf/PointerPreparations.h>
+#include <wtf/URL.h>
+
+namespace WebCore {
+using namespace JSC;
+
+// Functions
+
+static JSC_DECLARE_HOST_FUNCTION(jsBroadcastChannelPrototypeFunction_postMessage);
+static JSC_DECLARE_HOST_FUNCTION(jsBroadcastChannelPrototypeFunction_close);
+static JSC_DECLARE_HOST_FUNCTION(jsBroadcastChannelPrototypeFunction_ref);
+static JSC_DECLARE_HOST_FUNCTION(jsBroadcastChannelPrototypeFunction_unref);
+
+// Attributes
+
+static JSC_DECLARE_CUSTOM_GETTER(jsBroadcastChannelConstructor);
+static JSC_DECLARE_CUSTOM_GETTER(jsBroadcastChannel_name);
+static JSC_DECLARE_CUSTOM_GETTER(jsBroadcastChannel_onmessage);
+static JSC_DECLARE_CUSTOM_SETTER(setJSBroadcastChannel_onmessage);
+static JSC_DECLARE_CUSTOM_GETTER(jsBroadcastChannel_onmessageerror);
+static JSC_DECLARE_CUSTOM_SETTER(setJSBroadcastChannel_onmessageerror);
+
+class JSBroadcastChannelPrototype final : public JSC::JSNonFinalObject {
+public:
+ using Base = JSC::JSNonFinalObject;
+ static JSBroadcastChannelPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure)
+ {
+ JSBroadcastChannelPrototype* ptr = new (NotNull, JSC::allocateCell<JSBroadcastChannelPrototype>(vm)) JSBroadcastChannelPrototype(vm, globalObject, structure);
+ ptr->finishCreation(vm);
+ return ptr;
+ }
+
+ DECLARE_INFO;
+ template<typename CellType, JSC::SubspaceAccess>
+ static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
+ {
+ STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBroadcastChannelPrototype, Base);
+ return &vm.plainObjectSpace();
+ }
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+private:
+ JSBroadcastChannelPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)
+ : JSC::JSNonFinalObject(vm, structure)
+ {
+ }
+
+ void finishCreation(JSC::VM&);
+};
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBroadcastChannelPrototype, JSBroadcastChannelPrototype::Base);
+
+using JSBroadcastChannelDOMConstructor = JSDOMConstructor<JSBroadcastChannel>;
+
+template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSBroadcastChannelDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)
+{
+ VM& vm = lexicalGlobalObject->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto* castedThis = jsCast<JSBroadcastChannelDOMConstructor*>(callFrame->jsCallee());
+ ASSERT(castedThis);
+ if (UNLIKELY(callFrame->argumentCount() < 1))
+ return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
+ auto* context = castedThis->scriptExecutionContext();
+ if (UNLIKELY(!context))
+ return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "BroadcastChannel");
+ EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
+ auto name = convert<IDLDOMString>(*lexicalGlobalObject, argument0.value());
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ auto object = BroadcastChannel::create(*context, WTFMove(name));
+ if constexpr (IsExceptionOr<decltype(object)>)
+ RETURN_IF_EXCEPTION(throwScope, {});
+ static_assert(TypeOrExceptionOrUnderlyingType<decltype(object)>::isRef);
+ auto jsValue = toJSNewlyCreated<IDLInterface<BroadcastChannel>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object));
+ if constexpr (IsExceptionOr<decltype(object)>)
+ RETURN_IF_EXCEPTION(throwScope, {});
+ setSubclassStructureIfNeeded<BroadcastChannel>(lexicalGlobalObject, callFrame, asObject(jsValue));
+ RETURN_IF_EXCEPTION(throwScope, {});
+ return JSValue::encode(jsValue);
+}
+JSC_ANNOTATE_HOST_FUNCTION(JSBroadcastChannelDOMConstructorConstruct, JSBroadcastChannelDOMConstructor::construct);
+
+template<> const ClassInfo JSBroadcastChannelDOMConstructor::s_info = { "BroadcastChannel"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBroadcastChannelDOMConstructor) };
+
+template<> JSValue JSBroadcastChannelDOMConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
+{
+ return JSEventTarget::getConstructor(vm, &globalObject);
+}
+
+template<> void JSBroadcastChannelDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)
+{
+ putDirect(vm, vm.propertyNames->length, jsNumber(1), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
+ JSString* nameString = jsNontrivialString(vm, "BroadcastChannel"_s);
+ m_originalName.set(vm, this, nameString);
+ putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
+ putDirect(vm, vm.propertyNames->prototype, JSBroadcastChannel::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete);
+}
+
+/* Hash table for prototype */
+
+static const HashTableValue JSBroadcastChannelPrototypeTableValues[] = {
+ { "constructor"_s, static_cast<unsigned>(PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsBroadcastChannelConstructor, 0 } },
+ { "name"_s, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute, NoIntrinsic, { HashTableValue::GetterSetterType, jsBroadcastChannel_name, 0 } },
+ { "onmessage"_s, JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute, NoIntrinsic, { HashTableValue::GetterSetterType, jsBroadcastChannel_onmessage, setJSBroadcastChannel_onmessage } },
+ { "onmessageerror"_s, JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute, NoIntrinsic, { HashTableValue::GetterSetterType, jsBroadcastChannel_onmessageerror, setJSBroadcastChannel_onmessageerror } },
+ { "postMessage"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBroadcastChannelPrototypeFunction_postMessage, 1 } },
+ { "close"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBroadcastChannelPrototypeFunction_close, 0 } },
+ { "ref"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBroadcastChannelPrototypeFunction_ref, 0 } },
+ { "unref"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBroadcastChannelPrototypeFunction_unref, 0 } },
+};
+
+const ClassInfo JSBroadcastChannelPrototype::s_info = { "BroadcastChannel"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBroadcastChannelPrototype) };
+
+void JSBroadcastChannelPrototype::finishCreation(VM& vm)
+{
+ Base::finishCreation(vm);
+ reifyStaticProperties(vm, JSBroadcastChannel::info(), JSBroadcastChannelPrototypeTableValues, *this);
+ JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+}
+
+const ClassInfo JSBroadcastChannel::s_info = { "BroadcastChannel"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBroadcastChannel) };
+
+JSBroadcastChannel::JSBroadcastChannel(Structure* structure, JSDOMGlobalObject& globalObject, Ref<BroadcastChannel>&& impl)
+ : JSEventTarget(structure, globalObject, WTFMove(impl))
+{
+}
+
+// static_assert(std::is_base_of<ActiveDOMObject, BroadcastChannel>::value, "Interface is marked as [ActiveDOMObject] but implementation class does not subclass ActiveDOMObject.");
+
+JSObject* JSBroadcastChannel::createPrototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+ auto* structure = JSBroadcastChannelPrototype::createStructure(vm, &globalObject, JSEventTarget::prototype(vm, globalObject));
+ structure->setMayBePrototype(true);
+ return JSBroadcastChannelPrototype::create(vm, &globalObject, structure);
+}
+
+JSObject* JSBroadcastChannel::prototype(VM& vm, JSDOMGlobalObject& globalObject)
+{
+ return getDOMPrototype<JSBroadcastChannel>(vm, globalObject);
+}
+
+JSValue JSBroadcastChannel::getConstructor(VM& vm, const JSGlobalObject* globalObject)
+{
+ return getDOMConstructor<JSBroadcastChannelDOMConstructor, DOMConstructorID::BroadcastChannel>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
+}
+
+JSC_DEFINE_CUSTOM_GETTER(jsBroadcastChannelConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName))
+{
+ VM& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto* prototype = jsDynamicCast<JSBroadcastChannelPrototype*>(JSValue::decode(thisValue));
+ if (UNLIKELY(!prototype))
+ return throwVMTypeError(lexicalGlobalObject, throwScope);
+ return JSValue::encode(JSBroadcastChannel::getConstructor(JSC::getVM(lexicalGlobalObject), prototype->globalObject()));
+}
+
+static inline JSValue jsBroadcastChannel_nameGetter(JSGlobalObject& lexicalGlobalObject, JSBroadcastChannel& thisObject)
+{
+ auto& vm = JSC::getVM(&lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto& impl = thisObject.wrapped();
+ RELEASE_AND_RETURN(throwScope, (toJS<IDLDOMString>(lexicalGlobalObject, throwScope, impl.name())));
+}
+
+JSC_DEFINE_CUSTOM_GETTER(jsBroadcastChannel_name, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ return IDLAttribute<JSBroadcastChannel>::get<jsBroadcastChannel_nameGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName);
+}
+
+static inline JSValue jsBroadcastChannel_onmessageGetter(JSGlobalObject& lexicalGlobalObject, JSBroadcastChannel& thisObject)
+{
+ UNUSED_PARAM(lexicalGlobalObject);
+ return eventHandlerAttribute(thisObject.wrapped(), eventNames().messageEvent, worldForDOMObject(thisObject));
+}
+
+JSC_DEFINE_CUSTOM_GETTER(jsBroadcastChannel_onmessage, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ return IDLAttribute<JSBroadcastChannel>::get<jsBroadcastChannel_onmessageGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName);
+}
+
+static inline bool setJSBroadcastChannel_onmessageSetter(JSGlobalObject& lexicalGlobalObject, JSBroadcastChannel& thisObject, JSValue value)
+{
+ auto& vm = JSC::getVM(&lexicalGlobalObject);
+ UNUSED_PARAM(vm);
+ setEventHandlerAttribute<JSEventListener>(thisObject.wrapped(), eventNames().messageEvent, value, thisObject);
+ vm.writeBarrier(&thisObject, value);
+ ensureStillAliveHere(value);
+
+ return true;
+}
+
+JSC_DEFINE_CUSTOM_SETTER(setJSBroadcastChannel_onmessage, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName))
+{
+ return IDLAttribute<JSBroadcastChannel>::set<setJSBroadcastChannel_onmessageSetter>(*lexicalGlobalObject, thisValue, encodedValue, attributeName);
+}
+
+static inline JSValue jsBroadcastChannel_onmessageerrorGetter(JSGlobalObject& lexicalGlobalObject, JSBroadcastChannel& thisObject)
+{
+ UNUSED_PARAM(lexicalGlobalObject);
+ return eventHandlerAttribute(thisObject.wrapped(), eventNames().messageerrorEvent, worldForDOMObject(thisObject));
+}
+
+JSC_DEFINE_CUSTOM_GETTER(jsBroadcastChannel_onmessageerror, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ return IDLAttribute<JSBroadcastChannel>::get<jsBroadcastChannel_onmessageerrorGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName);
+}
+
+static inline bool setJSBroadcastChannel_onmessageerrorSetter(JSGlobalObject& lexicalGlobalObject, JSBroadcastChannel& thisObject, JSValue value)
+{
+ auto& vm = JSC::getVM(&lexicalGlobalObject);
+ UNUSED_PARAM(vm);
+ setEventHandlerAttribute<JSEventListener>(thisObject.wrapped(), eventNames().messageerrorEvent, value, thisObject);
+ vm.writeBarrier(&thisObject, value);
+ ensureStillAliveHere(value);
+
+ return true;
+}
+
+JSC_DEFINE_CUSTOM_SETTER(setJSBroadcastChannel_onmessageerror, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName))
+{
+ return IDLAttribute<JSBroadcastChannel>::set<setJSBroadcastChannel_onmessageerrorSetter>(*lexicalGlobalObject, thisValue, encodedValue, attributeName);
+}
+
+static inline JSC::EncodedJSValue jsBroadcastChannelPrototypeFunction_postMessageBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBroadcastChannel>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->wrapped();
+ if (UNLIKELY(callFrame->argumentCount() < 1))
+ return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
+ EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
+ auto message = convert<IDLAny>(*lexicalGlobalObject, argument0.value());
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.postMessage(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(message)); })));
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsBroadcastChannelPrototypeFunction_postMessage, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return IDLOperation<JSBroadcastChannel>::call<jsBroadcastChannelPrototypeFunction_postMessageBody>(*lexicalGlobalObject, *callFrame, "postMessage");
+}
+
+static inline JSC::EncodedJSValue jsBroadcastChannelPrototypeFunction_closeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBroadcastChannel>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->wrapped();
+ impl.jsUnref(lexicalGlobalObject);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.close(); })));
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsBroadcastChannelPrototypeFunction_close, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return IDLOperation<JSBroadcastChannel>::call<jsBroadcastChannelPrototypeFunction_closeBody>(*lexicalGlobalObject, *callFrame, "close");
+}
+
+static inline JSC::EncodedJSValue jsBroadcastChannelPrototypeFunction_refBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBroadcastChannel>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->wrapped();
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.jsRef(lexicalGlobalObject); })));
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsBroadcastChannelPrototypeFunction_ref, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return IDLOperation<JSBroadcastChannel>::call<jsBroadcastChannelPrototypeFunction_refBody>(*lexicalGlobalObject, *callFrame, "ref");
+}
+
+static inline JSC::EncodedJSValue jsBroadcastChannelPrototypeFunction_unrefBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBroadcastChannel>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->wrapped();
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.jsUnref(lexicalGlobalObject); })));
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsBroadcastChannelPrototypeFunction_unref, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return IDLOperation<JSBroadcastChannel>::call<jsBroadcastChannelPrototypeFunction_unrefBody>(*lexicalGlobalObject, *callFrame, "unref");
+}
+
+JSC::GCClient::IsoSubspace* JSBroadcastChannel::subspaceForImpl(JSC::VM& vm)
+{
+ return WebCore::subspaceForImpl<JSBroadcastChannel, UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForBroadcastChannel.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForBroadcastChannel = std::forward<decltype(space)>(space); },
+ [](auto& spaces) { return spaces.m_subspaceForBroadcastChannel.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForBroadcastChannel = std::forward<decltype(space)>(space); });
+}
+
+void JSBroadcastChannel::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
+{
+ auto* thisObject = jsCast<JSBroadcastChannel*>(cell);
+ analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped());
+ if (thisObject->scriptExecutionContext())
+ analyzer.setLabelForCell(cell, "url "_s + thisObject->scriptExecutionContext()->url().string());
+ Base::analyzeHeap(cell, analyzer);
+}
+
+bool JSBroadcastChannelOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, AbstractSlotVisitor& visitor, const char** reason)
+{
+ auto* jsBroadcastChannel = jsCast<JSBroadcastChannel*>(handle.slot()->asCell());
+ auto& wrapped = jsBroadcastChannel->wrapped();
+ if (/*!wrapped.isContextStopped() && */ wrapped.hasPendingActivity()) {
+ if (UNLIKELY(reason))
+ *reason = "ActiveDOMObject with pending activity";
+ return true;
+ }
+ UNUSED_PARAM(visitor);
+ UNUSED_PARAM(reason);
+ return false;
+}
+
+void JSBroadcastChannelOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+{
+ auto* jsBroadcastChannel = static_cast<JSBroadcastChannel*>(handle.slot()->asCell());
+ auto& world = *static_cast<DOMWrapperWorld*>(context);
+ uncacheWrapper(world, &jsBroadcastChannel->wrapped(), jsBroadcastChannel);
+}
+
+#if ENABLE(BINDING_INTEGRITY)
+#if PLATFORM(WIN)
+#pragma warning(disable : 4483)
+extern "C" {
+extern void (*const __identifier("??_7BroadcastChannel@WebCore@@6B@")[])();
+}
+#else
+extern "C" {
+extern void* _ZTVN7WebCore16BroadcastChannelE[];
+}
+#endif
+#endif
+
+JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<BroadcastChannel>&& impl)
+{
+
+ if constexpr (std::is_polymorphic_v<BroadcastChannel>) {
+#if ENABLE(BINDING_INTEGRITY)
+ const void* actualVTablePointer = getVTablePointer(impl.ptr());
+#if PLATFORM(WIN)
+ void* expectedVTablePointer = __identifier("??_7BroadcastChannel@WebCore@@6B@");
+#else
+ void* expectedVTablePointer = &_ZTVN7WebCore16BroadcastChannelE[2];
+#endif
+
+ // If you hit this assertion you either have a use after free bug, or
+ // BroadcastChannel has subclasses. If BroadcastChannel has subclasses that get passed
+ // to toJS() we currently require BroadcastChannel you to opt out of binding hardening
+ // by adding the SkipVTableValidation attribute to the interface IDL definition
+ RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer);
+#endif
+ }
+ return createWrapper<BroadcastChannel>(globalObject, WTFMove(impl));
+}
+
+JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, BroadcastChannel& impl)
+{
+ return wrap(lexicalGlobalObject, globalObject, impl);
+}
+
+BroadcastChannel* JSBroadcastChannel::toWrapped(JSC::VM&, JSC::JSValue value)
+{
+ if (auto* wrapper = jsDynamicCast<JSBroadcastChannel*>(value))
+ return &wrapper->wrapped();
+ return nullptr;
+}
+
+}
diff --git a/src/bun.js/bindings/webcore/JSBroadcastChannel.h b/src/bun.js/bindings/webcore/JSBroadcastChannel.h
new file mode 100644
index 000000000..9154d4991
--- /dev/null
+++ b/src/bun.js/bindings/webcore/JSBroadcastChannel.h
@@ -0,0 +1,99 @@
+/*
+ This file is part of the WebKit open source project.
+ This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#pragma once
+
+#include "BroadcastChannel.h"
+#include "JSDOMWrapper.h"
+#include "JSEventTarget.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+class JSBroadcastChannel : public JSEventTarget {
+public:
+ using Base = JSEventTarget;
+ using DOMWrapped = BroadcastChannel;
+ static JSBroadcastChannel* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<BroadcastChannel>&& impl)
+ {
+ JSBroadcastChannel* ptr = new (NotNull, JSC::allocateCell<JSBroadcastChannel>(globalObject->vm())) JSBroadcastChannel(structure, *globalObject, WTFMove(impl));
+ ptr->finishCreation(globalObject->vm());
+ return ptr;
+ }
+
+ static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&);
+ static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&);
+ static BroadcastChannel* toWrapped(JSC::VM&, JSC::JSValue);
+
+ DECLARE_INFO;
+
+ 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(), JSC::NonArray);
+ }
+
+ static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
+ 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 void analyzeHeap(JSCell*, JSC::HeapAnalyzer&);
+ BroadcastChannel& wrapped() const
+ {
+ return static_cast<BroadcastChannel&>(Base::wrapped());
+ }
+
+protected:
+ JSBroadcastChannel(JSC::Structure*, JSDOMGlobalObject&, Ref<BroadcastChannel>&&);
+
+ DECLARE_DEFAULT_FINISH_CREATION;
+};
+
+class JSBroadcastChannelOwner final : public JSC::WeakHandleOwner {
+public:
+ bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::AbstractSlotVisitor&, const char**) final;
+ void finalize(JSC::Handle<JSC::Unknown>, void* context) final;
+};
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, BroadcastChannel*)
+{
+ static NeverDestroyed<JSBroadcastChannelOwner> owner;
+ return &owner.get();
+}
+
+inline void* wrapperKey(BroadcastChannel* wrappableObject)
+{
+ return wrappableObject;
+}
+
+JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, BroadcastChannel&);
+inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, BroadcastChannel* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); }
+JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<BroadcastChannel>&&);
+inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<BroadcastChannel>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); }
+
+template<> struct JSDOMWrapperConverterTraits<BroadcastChannel> {
+ using WrapperClass = JSBroadcastChannel;
+ using ToWrappedReturnType = BroadcastChannel*;
+};
+
+} // namespace WebCore
diff --git a/src/bun.js/bindings/webcore/JSMessageEvent.cpp b/src/bun.js/bindings/webcore/JSMessageEvent.cpp
index f6090bd91..68414fe46 100644
--- a/src/bun.js/bindings/webcore/JSMessageEvent.cpp
+++ b/src/bun.js/bindings/webcore/JSMessageEvent.cpp
@@ -352,7 +352,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsMessageEvent_lastEventId, (JSGlobalObject * lexicalGl
static inline JSValue jsMessageEvent_sourceGetter(JSGlobalObject& lexicalGlobalObject, JSMessageEvent& thisObject)
{
auto& vm = JSC::getVM(&lexicalGlobalObject);
- return lexicalGlobalObject.globalThis();
+ return jsNull();
// auto throwScope = DECLARE_THROW_SCOPE(vm);
// auto& impl = thisObject.wrapped();
// RELEASE_AND_RETURN(throwScope, (toJS<IDLNullable<IDLUnion<IDLInterface<WindowProxy>, IDLInterface<MessagePort>, IDLInterface<ServiceWorker>>>>(lexicalGlobalObject, *thisObject.globalObject(), throwScope, impl.source())));
diff --git a/src/bun.js/bindings/webcore/JSMessagePort.cpp b/src/bun.js/bindings/webcore/JSMessagePort.cpp
index d957e32ce..b70167e55 100644
--- a/src/bun.js/bindings/webcore/JSMessagePort.cpp
+++ b/src/bun.js/bindings/webcore/JSMessagePort.cpp
@@ -62,6 +62,9 @@ using namespace JSC;
static JSC_DECLARE_HOST_FUNCTION(jsMessagePortPrototypeFunction_postMessage);
static JSC_DECLARE_HOST_FUNCTION(jsMessagePortPrototypeFunction_start);
static JSC_DECLARE_HOST_FUNCTION(jsMessagePortPrototypeFunction_close);
+static JSC_DECLARE_HOST_FUNCTION(jsMessagePortPrototypeFunction_ref);
+static JSC_DECLARE_HOST_FUNCTION(jsMessagePortPrototypeFunction_unref);
+static JSC_DECLARE_HOST_FUNCTION(jsMessagePortPrototypeFunction_hasRef);
// Attributes
@@ -130,6 +133,9 @@ static const HashTableValue JSMessagePortPrototypeTableValues[] = {
{ "postMessage"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMessagePortPrototypeFunction_postMessage, 1 } },
{ "start"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMessagePortPrototypeFunction_start, 0 } },
{ "close"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMessagePortPrototypeFunction_close, 0 } },
+ { "ref"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMessagePortPrototypeFunction_ref, 0 } },
+ { "unref"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMessagePortPrototypeFunction_unref, 0 } },
+ { "hasRef"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsMessagePortPrototypeFunction_hasRef, 0 } },
};
const ClassInfo JSMessagePortPrototype::s_info = { "MessagePort"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSMessagePortPrototype) };
@@ -196,6 +202,8 @@ static inline bool setJSMessagePort_onmessageSetter(JSGlobalObject& lexicalGloba
vm.writeBarrier(&thisObject, value);
ensureStillAliveHere(value);
+ thisObject.wrapped().jsRef(&lexicalGlobalObject);
+
return true;
}
@@ -223,6 +231,8 @@ static inline bool setJSMessagePort_onmessageerrorSetter(JSGlobalObject& lexical
vm.writeBarrier(&thisObject, value);
ensureStillAliveHere(value);
+ thisObject.wrapped().jsRef(&lexicalGlobalObject);
+
return true;
}
@@ -318,6 +328,7 @@ static inline JSC::EncodedJSValue jsMessagePortPrototypeFunction_closeBody(JSC::
UNUSED_PARAM(throwScope);
UNUSED_PARAM(callFrame);
auto& impl = castedThis->wrapped();
+ impl.jsUnref(lexicalGlobalObject);
RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.close(); })));
}
@@ -326,6 +337,51 @@ JSC_DEFINE_HOST_FUNCTION(jsMessagePortPrototypeFunction_close, (JSGlobalObject *
return IDLOperation<JSMessagePort>::call<jsMessagePortPrototypeFunction_closeBody>(*lexicalGlobalObject, *callFrame, "close");
}
+static inline JSC::EncodedJSValue jsMessagePortPrototypeFunction_refBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSMessagePort>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->wrapped();
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.jsRef(lexicalGlobalObject); })));
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsMessagePortPrototypeFunction_ref, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return IDLOperation<JSMessagePort>::call<jsMessagePortPrototypeFunction_refBody>(*lexicalGlobalObject, *callFrame, "ref");
+}
+
+static inline JSC::EncodedJSValue jsMessagePortPrototypeFunction_unrefBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSMessagePort>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->wrapped();
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.jsUnref(lexicalGlobalObject); })));
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsMessagePortPrototypeFunction_unref, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return IDLOperation<JSMessagePort>::call<jsMessagePortPrototypeFunction_unrefBody>(*lexicalGlobalObject, *callFrame, "unref");
+}
+
+static inline JSC::EncodedJSValue jsMessagePortPrototypeFunction_hasRefBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSMessagePort>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->wrapped();
+ return JSValue::encode(jsBoolean(impl.jsHasRef()));
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsMessagePortPrototypeFunction_hasRef, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return IDLOperation<JSMessagePort>::call<jsMessagePortPrototypeFunction_hasRefBody>(*lexicalGlobalObject, *callFrame, "hasRef");
+}
+
JSC::GCClient::IsoSubspace* JSMessagePort::subspaceForImpl(JSC::VM& vm)
{
return WebCore::subspaceForImpl<JSMessagePort, UseCustomHeapCellType::No>(
diff --git a/src/bun.js/bindings/webcore/MessagePort.cpp b/src/bun.js/bindings/webcore/MessagePort.cpp
index 956143c80..cdb3ea365 100644
--- a/src/bun.js/bindings/webcore/MessagePort.cpp
+++ b/src/bun.js/bindings/webcore/MessagePort.cpp
@@ -27,6 +27,7 @@
#include "config.h"
#include "MessagePort.h"
+#include "BunClientData.h"
// #include "Document.h"
#include "EventNames.h"
// #include "Logging.h"
@@ -44,6 +45,8 @@
#include <wtf/Lock.h>
#include <wtf/Scope.h>
+extern "C" void Bun__eventLoop__incrementRefConcurrently(void* bunVM, int delta);
+
namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(MessagePort);
@@ -416,4 +419,20 @@ WebCoreOpaqueRoot root(MessagePort* port)
return WebCoreOpaqueRoot { port };
}
+void MessagePort::jsRef(JSGlobalObject* lexicalGlobalObject)
+{
+ if (!m_hasRef) {
+ m_hasRef = true;
+ Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(lexicalGlobalObject->vm())->bunVM, 1);
+ }
+}
+
+void MessagePort::jsUnref(JSGlobalObject* lexicalGlobalObject)
+{
+ if (m_hasRef) {
+ m_hasRef = false;
+ Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(lexicalGlobalObject->vm())->bunVM, -1);
+ }
+}
+
} // namespace WebCore
diff --git a/src/bun.js/bindings/webcore/MessagePort.h b/src/bun.js/bindings/webcore/MessagePort.h
index 18f0ba212..6a4e599be 100644
--- a/src/bun.js/bindings/webcore/MessagePort.h
+++ b/src/bun.js/bindings/webcore/MessagePort.h
@@ -103,6 +103,10 @@ public:
static ScriptExecutionContextIdentifier contextIdForMessagePortId(MessagePortIdentifier);
+ void jsRef(JSGlobalObject*);
+ void jsUnref(JSGlobalObject*);
+ bool jsHasRef() { return m_hasRef; }
+
private:
explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier& local, const MessagePortIdentifier& remote);
@@ -133,6 +137,8 @@ private:
MessagePortIdentifier m_remoteIdentifier;
mutable std::atomic<unsigned> m_refCount { 1 };
+
+ bool m_hasRef { false };
};
WebCoreOpaqueRoot root(MessagePort*);
diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp
index 9eeee155a..9b9f04aa8 100644
--- a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp
+++ b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp
@@ -38,6 +38,7 @@
#include "CryptoKeyRaw.h"
// #include "IDBValue.h"
// #include "ImageBitmapBacking.h"
+// #include "JSAudioWorkletGlobalScope.h"
// #include "JSBlob.h"
#include "JSCryptoKey.h"
#include "JSDOMBinding.h"
@@ -70,6 +71,7 @@
#include <JavaScriptCore/CatchScope.h>
#include <JavaScriptCore/DateInstance.h>
#include <JavaScriptCore/Error.h>
+#include <JavaScriptCore/ErrorInstance.h>
#include <JavaScriptCore/Exception.h>
#include <JavaScriptCore/ExceptionHelpers.h>
#include <JavaScriptCore/IterationKind.h>
@@ -227,6 +229,7 @@ enum SerializationTag {
WebCodecsVideoFrameTag = 53,
#endif
ResizableArrayBufferTag = 54,
+ ErrorInstanceTag = 55,
Bun__BlobTag = 254,
// bun types start at 254 and decrease with each addition
@@ -249,6 +252,95 @@ enum ArrayBufferViewSubtag {
BigUint64ArrayTag = 11,
};
+// static bool isTypeExposedToGlobalObject(JSC::JSGlobalObject& globalObject, SerializationTag tag)
+// {
+// #if ENABLE(WEB_AUDIO)
+// if (!jsDynamicCast<JSAudioWorkletGlobalScope*>(&globalObject))
+// return true;
+
+// // Only built-in JS types are exposed to audio worklets.
+// switch (tag) {
+// case ArrayTag:
+// case ObjectTag:
+// case UndefinedTag:
+// case NullTag:
+// case IntTag:
+// case ZeroTag:
+// case OneTag:
+// case FalseTag:
+// case TrueTag:
+// case DoubleTag:
+// case DateTag:
+// case StringTag:
+// case EmptyStringTag:
+// case RegExpTag:
+// case ObjectReferenceTag:
+// case ArrayBufferTag:
+// case ArrayBufferViewTag:
+// case ArrayBufferTransferTag:
+// case TrueObjectTag:
+// case FalseObjectTag:
+// case StringObjectTag:
+// case EmptyStringObjectTag:
+// case NumberObjectTag:
+// case SetObjectTag:
+// case MapObjectTag:
+// case NonMapPropertiesTag:
+// case NonSetPropertiesTag:
+// case SharedArrayBufferTag:
+// #if ENABLE(WEBASSEMBLY)
+// case WasmModuleTag:
+// #endif
+// case BigIntTag:
+// case BigIntObjectTag:
+// #if ENABLE(WEBASSEMBLY)
+// case WasmMemoryTag:
+// #endif
+// case ResizableArrayBufferTag:
+// case ErrorInstanceTag:
+// case ErrorTag:
+// case MessagePortReferenceTag:
+// return true;
+// case FileTag:
+// case FileListTag:
+// case ImageDataTag:
+// case BlobTag:
+// #if ENABLE(WEB_CRYPTO)
+// case CryptoKeyTag:
+// #endif
+// case DOMPointReadOnlyTag:
+// case DOMPointTag:
+// case DOMRectReadOnlyTag:
+// case DOMRectTag:
+// case DOMMatrixReadOnlyTag:
+// case DOMMatrixTag:
+// case DOMQuadTag:
+// case ImageBitmapTransferTag:
+// #if ENABLE(WEB_RTC)
+// case RTCCertificateTag:
+// #endif
+// case ImageBitmapTag:
+// #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
+// case OffscreenCanvasTransferTag:
+// #endif
+// #if ENABLE(WEB_RTC)
+// case RTCDataChannelTransferTag:
+// #endif
+// case DOMExceptionTag:
+// #if ENABLE(WEB_CODECS)
+// case WebCodecsEncodedVideoChunkTag:
+// case WebCodecsVideoFrameTag:
+// #endif
+// break;
+// }
+// return false;
+// #else
+// UNUSED_PARAM(globalObject);
+// UNUSED_PARAM(tag);
+// return true;
+// #endif
+// }
+
static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
{
switch (tag) {
@@ -273,6 +365,55 @@ static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
}
}
+enum class SerializableErrorType : uint8_t {
+ Error,
+ EvalError,
+ RangeError,
+ ReferenceError,
+ SyntaxError,
+ TypeError,
+ URIError,
+ Last = URIError
+};
+
+static SerializableErrorType errorNameToSerializableErrorType(const String& name)
+{
+ if (equalLettersIgnoringASCIICase(name, "evalerror"_s))
+ return SerializableErrorType::EvalError;
+ if (equalLettersIgnoringASCIICase(name, "rangeerror"_s))
+ return SerializableErrorType::RangeError;
+ if (equalLettersIgnoringASCIICase(name, "referenceerror"_s))
+ return SerializableErrorType::ReferenceError;
+ if (equalLettersIgnoringASCIICase(name, "syntaxerror"_s))
+ return SerializableErrorType::SyntaxError;
+ if (equalLettersIgnoringASCIICase(name, "typeerror"_s))
+ return SerializableErrorType::TypeError;
+ if (equalLettersIgnoringASCIICase(name, "urierror"_s))
+ return SerializableErrorType::URIError;
+ return SerializableErrorType::Error;
+}
+
+static ErrorType toErrorType(SerializableErrorType value)
+{
+ switch (value) {
+ case SerializableErrorType::Error:
+ return ErrorType::Error;
+ case SerializableErrorType::EvalError:
+ return ErrorType::EvalError;
+ case SerializableErrorType::RangeError:
+ return ErrorType::RangeError;
+ case SerializableErrorType::ReferenceError:
+ return ErrorType::ReferenceError;
+ case SerializableErrorType::SyntaxError:
+ return ErrorType::SyntaxError;
+ case SerializableErrorType::TypeError:
+ return ErrorType::TypeError;
+ case SerializableErrorType::URIError:
+ return ErrorType::URIError;
+ }
+ return ErrorType::Error;
+}
+
enum class PredefinedColorSpaceTag : uint8_t {
SRGB = 0
#if ENABLE(PREDEFINED_COLOR_SPACE_DISPLAY_P3)
@@ -396,14 +537,16 @@ const uint8_t cryptoKeyOKPOpNameTagMaximumValue = 1;
* Version 10. changed the length (and offsets) of ArrayBuffers (and ArrayBufferViews) from 32 to 64 bits.
* Version 11. added support for Blob's memory cost.
* Version 12. added support for agent cluster ID.
+ * Version 13. added support for ErrorInstance objects.
*/
-static const unsigned CurrentVersion = 12;
-static const unsigned TerminatorTag = 0xFFFFFFFF;
-static const unsigned StringPoolTag = 0xFFFFFFFE;
-static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
+static constexpr unsigned CurrentVersion = 13;
+static constexpr unsigned TerminatorTag = 0xFFFFFFFF;
+static constexpr unsigned StringPoolTag = 0xFFFFFFFE;
+static constexpr unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
+static constexpr uint32_t ImageDataPoolTag = 0xFFFFFFFE;
// The high bit of a StringData's length determines the character size.
-static const unsigned StringDataIs8BitFlag = 0x80000000;
+static constexpr unsigned StringDataIs8BitFlag = 0x80000000;
/*
* Object serialization is performed according to the following grammar, all tags
@@ -1484,8 +1627,14 @@ private:
// }
// if (auto* data = JSImageData::toWrapped(vm, obj)) {
// write(ImageDataTag);
- // write(data->width());
- // write(data->height());
+ // auto addResult = m_imageDataPool.add(*data, m_imageDataPool.size());
+ // if (!addResult.isNewEntry) {
+ // write(ImageDataPoolTag);
+ // writeImageDataIndex(addResult.iterator->value);
+ // return true;
+ // }
+ // write(static_cast<uint32_t>(data->width()));
+ // write(static_cast<uint32_t>(data->height()));
// CheckedUint32 dataLength = data->data().length();
// if (dataLength.hasOverflowed()) {
// code = SerializationReturnCode::DataCloneError;
@@ -1502,6 +1651,63 @@ private:
write(String::fromLatin1(JSC::Yarr::flagsString(regExp->regExp()->flags()).data()));
return true;
}
+ if (auto* errorInstance = jsDynamicCast<ErrorInstance*>(obj)) {
+ auto& vm = m_lexicalGlobalObject->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ auto errorTypeValue = errorInstance->get(m_lexicalGlobalObject, vm.propertyNames->name);
+ RETURN_IF_EXCEPTION(scope, false);
+ auto errorTypeString = errorTypeValue.toWTFString(m_lexicalGlobalObject);
+ RETURN_IF_EXCEPTION(scope, false);
+
+ String message;
+ PropertyDescriptor messageDescriptor;
+ if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->message, messageDescriptor) && messageDescriptor.isDataDescriptor()) {
+ EXCEPTION_ASSERT(!scope.exception());
+ message = messageDescriptor.value().toWTFString(m_lexicalGlobalObject);
+ }
+ RETURN_IF_EXCEPTION(scope, false);
+
+ unsigned line = 0;
+ PropertyDescriptor lineDescriptor;
+ if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->line, lineDescriptor) && lineDescriptor.isDataDescriptor()) {
+ EXCEPTION_ASSERT(!scope.exception());
+ line = lineDescriptor.value().toNumber(m_lexicalGlobalObject);
+ }
+ RETURN_IF_EXCEPTION(scope, false);
+
+ unsigned column = 0;
+ PropertyDescriptor columnDescriptor;
+ if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->column, columnDescriptor) && columnDescriptor.isDataDescriptor()) {
+ EXCEPTION_ASSERT(!scope.exception());
+ column = columnDescriptor.value().toNumber(m_lexicalGlobalObject);
+ }
+ RETURN_IF_EXCEPTION(scope, false);
+
+ String sourceURL;
+ PropertyDescriptor sourceURLDescriptor;
+ if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->sourceURL, sourceURLDescriptor) && sourceURLDescriptor.isDataDescriptor()) {
+ EXCEPTION_ASSERT(!scope.exception());
+ sourceURL = sourceURLDescriptor.value().toWTFString(m_lexicalGlobalObject);
+ }
+ RETURN_IF_EXCEPTION(scope, false);
+
+ String stack;
+ PropertyDescriptor stackDescriptor;
+ if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->stack, stackDescriptor) && stackDescriptor.isDataDescriptor()) {
+ EXCEPTION_ASSERT(!scope.exception());
+ stack = stackDescriptor.value().toWTFString(m_lexicalGlobalObject);
+ }
+ RETURN_IF_EXCEPTION(scope, false);
+
+ write(ErrorInstanceTag);
+ write(errorNameToSerializableErrorType(errorTypeString));
+ writeNullableString(message);
+ write(line);
+ write(column);
+ writeNullableString(sourceURL);
+ writeNullableString(stack);
+ return true;
+ }
if (obj->inherits<JSMessagePort>()) {
auto index = m_transferredMessagePorts.find(obj);
if (index != m_transferredMessagePorts.end()) {
@@ -1765,6 +1971,11 @@ private:
}
#endif
+ void write(bool b)
+ {
+ writeLittleEndian(m_buffer, static_cast<int32_t>(b));
+ }
+
void write(uint8_t c)
{
writeLittleEndian(m_buffer, c);
@@ -1805,6 +2016,11 @@ private:
writeConstantPoolIndex(m_constantPool, i);
}
+ // void writeImageDataIndex(unsigned i)
+ // {
+ // writeConstantPoolIndex(m_imageDataPool, i);
+ // }
+
void writeObjectIndex(unsigned i)
{
writeConstantPoolIndex(m_objectPool, i);
@@ -1863,6 +2079,14 @@ private:
write(Identifier::fromString(m_lexicalGlobalObject->vm(), str));
}
+ void writeNullableString(const String& str)
+ {
+ bool isNull = str.isNull();
+ write(isNull);
+ if (!isNull)
+ write(Identifier::fromString(m_lexicalGlobalObject->vm(), str));
+ }
+
void write(const Vector<uint8_t>& vector)
{
uint32_t size = vector.size();
@@ -2074,6 +2298,11 @@ private:
}
}
+ void write(SerializableErrorType errorType)
+ {
+ write(enumToUnderlyingType(errorType));
+ }
+
void write(const CryptoKey* key)
{
write(currentKeyFormatVersion);
@@ -2172,6 +2401,8 @@ private:
#endif
typedef HashMap<RefPtr<UniquedStringImpl>, uint32_t, IdentifierRepHash> StringConstantPool;
StringConstantPool m_constantPool;
+ // using ImageDataPool = HashMap<Ref<ImageData>, uint32_t>;
+ // ImageDataPool m_imageDataPool;
Identifier m_emptyIdentifier;
SerializationContext m_context;
ArrayBufferContentsArray& m_sharedBuffers;
@@ -2880,6 +3111,15 @@ private:
}
#endif
+ bool read(bool& b)
+ {
+ int32_t integer;
+ if (!readLittleEndian(integer) || integer > 1)
+ return false;
+ b = !!integer;
+ return true;
+ }
+
bool read(uint32_t& i)
{
return readLittleEndian(i);
@@ -2917,28 +3157,34 @@ private:
return readLittleEndian(i);
}
- bool readStringIndex(uint32_t& i)
+ std::optional<uint32_t> readStringIndex()
{
- return readConstantPoolIndex(m_constantPool, i);
+ return readConstantPoolIndex(m_constantPool);
}
- template<class T> bool readConstantPoolIndex(const T& constantPool, uint32_t& i)
+ // std::optional<uint32_t> readImageDataIndex()
+ // {
+ // return readConstantPoolIndex(m_imageDataPool);
+ // }
+
+ template<typename T> std::optional<uint32_t> readConstantPoolIndex(const T& constantPool)
{
if (constantPool.size() <= 0xFF) {
uint8_t i8;
if (!read(i8))
- return false;
- i = i8;
- return true;
+ return std::nullopt;
+ return i8;
}
if (constantPool.size() <= 0xFFFF) {
uint16_t i16;
if (!read(i16))
- return false;
- i = i16;
- return true;
+ return std::nullopt;
+ return i16;
}
- return read(i);
+ uint32_t i;
+ if (!read(i))
+ return std::nullopt;
+ return i;
}
static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length, bool is8Bit)
@@ -2973,6 +3219,20 @@ private:
return true;
}
+ bool readNullableString(String& nullableString)
+ {
+ bool isNull;
+ if (!read(isNull))
+ return false;
+ if (isNull)
+ return true;
+ CachedStringRef stringData;
+ if (!readStringData(stringData))
+ return false;
+ nullableString = stringData->string();
+ return true;
+ }
+
static bool readIdentifier(JSC::VM& vm, const uint8_t*& ptr, const uint8_t* end, Identifier& str, unsigned length, bool is8Bit)
{
if (length >= std::numeric_limits<int32_t>::max() / sizeof(UChar))
@@ -3023,16 +3283,12 @@ private:
return false;
}
if (length == StringPoolTag) {
- unsigned index = 0;
- if (!readStringIndex(index)) {
+ auto index = readStringIndex();
+ if (!index || *index >= m_constantPool.size()) {
fail();
return false;
}
- if (index >= m_constantPool.size()) {
- fail();
- return false;
- }
- cachedString = CachedStringRef(&m_constantPool, index);
+ cachedString = CachedStringRef(&m_constantPool, *index);
return true;
}
bool is8Bit = length & StringDataIs8BitFlag;
@@ -3059,16 +3315,12 @@ private:
return false;
}
if (length == StringPoolTag) {
- unsigned index = 0;
- if (!readStringIndex(index)) {
- fail();
- return false;
- }
- if (index >= m_constantPool.size()) {
+ auto index = readStringIndex();
+ if (!index || *index >= m_constantPool.size()) {
fail();
return false;
}
- cachedString = CachedStringRef(&m_constantPool, index);
+ cachedString = CachedStringRef(&m_constantPool, *index);
return true;
}
bool is8Bit = length & StringDataIs8BitFlag;
@@ -3759,6 +4011,16 @@ private:
}
#endif
+ bool read(SerializableErrorType& errorType)
+ {
+ std::underlying_type_t<SerializableErrorType> errorTypeInt;
+ if (!read(errorTypeInt) || errorTypeInt > enumToUnderlyingType(SerializableErrorType::Last))
+ return false;
+
+ errorType = static_cast<SerializableErrorType>(errorTypeInt);
+ return true;
+ }
+
template<class T>
JSValue getJSValue(T&& nativeObj)
{
@@ -4194,6 +4456,8 @@ private:
JSValue readTerminal()
{
SerializationTag tag = readTag();
+ // if (!isTypeExposedToGlobalObject(*m_globalObject, tag))
+ // return JSValue();
// read bun types
if (auto value = StructuredCloneableDeserialize::fromTagDeserialize(tag, m_lexicalGlobalObject, m_ptr, m_end)) {
@@ -4296,6 +4560,14 @@ private:
// uint32_t width;
// if (!read(width))
// return JSValue();
+ // if (width == ImageDataPoolTag) {
+ // auto index = readImageDataIndex();
+ // if (!index || *index >= m_imageDataPool.size()) {
+ // fail();
+ // return JSValue();
+ // }
+ // return getJSValue(m_imageDataPool[*index]);
+ // }
// uint32_t height;
// if (!read(height))
// return JSValue();
@@ -4332,6 +4604,7 @@ private:
// memcpy(result.returnValue()->data().data(), bufferStart, length);
// else
// result.returnValue()->data().zeroFill();
+ // m_imageDataPool.append(result.returnValue().copyRef());
// return getJSValue(result.releaseReturnValue());
// }
// case BlobTag: {
@@ -4386,13 +4659,46 @@ private:
RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags.value());
return RegExpObject::create(vm, m_globalObject->regExpStructure(), regExp);
}
+ case ErrorInstanceTag: {
+ SerializableErrorType serializedErrorType;
+ if (!read(serializedErrorType)) {
+ fail();
+ return JSValue();
+ }
+ String message;
+ if (!readNullableString(message)) {
+ fail();
+ return JSValue();
+ }
+ uint32_t line;
+ if (!read(line)) {
+ fail();
+ return JSValue();
+ }
+ uint32_t column;
+ if (!read(column)) {
+ fail();
+ return JSValue();
+ }
+ String sourceURL;
+ if (!readNullableString(sourceURL)) {
+ fail();
+ return JSValue();
+ }
+ String stackString;
+ if (!readNullableString(stackString)) {
+ fail();
+ return JSValue();
+ }
+ return ErrorInstance::create(m_lexicalGlobalObject, WTFMove(message), toErrorType(serializedErrorType), line, column, WTFMove(sourceURL), WTFMove(stackString));
+ }
case ObjectReferenceTag: {
- unsigned index = 0;
- if (!readConstantPoolIndex(m_gcBuffer, index)) {
+ auto index = readConstantPoolIndex(m_gcBuffer);
+ if (!index) {
fail();
return JSValue();
}
- return m_gcBuffer.at(index);
+ return m_gcBuffer.at(*index);
}
case MessagePortReferenceTag: {
uint32_t index;
@@ -4628,6 +4934,7 @@ private:
const uint8_t* const m_end;
unsigned m_version;
Vector<CachedString> m_constantPool;
+ // Vector<Ref<ImageData>> m_imageDataPool;
const Vector<RefPtr<MessagePort>>& m_messagePorts;
ArrayBufferContentsArray* m_arrayBufferContents;
Vector<RefPtr<JSC::ArrayBuffer>> m_arrayBuffers;