Diff
Modified: trunk/Source/WebCore/ChangeLog (226335 => 226336)
--- trunk/Source/WebCore/ChangeLog 2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/ChangeLog 2018-01-02 22:42:16 UTC (rev 226336)
@@ -1,3 +1,59 @@
+2018-01-02 Brady Eidson <beid...@apple.com>
+
+ Identify MessagePorts by a globally unique MessagePortIdentifier.
+ https://bugs.webkit.org/show_bug.cgi?id=181172
+
+ Reviewed by Alex Christensen.
+
+ No new tests (Behavior change covered by all existing tests).
+
+ This cleans up the abstract MessagePortChannel interface to be in terms of identifiers
+ instead of actual MessagePort objects.
+
+ The identifiers are compounded with the current ProcessIdentifier meaning they are global
+ across all processes for the running UI process, enabling easy cross-process communication.
+
+ (Actual cross-process communication comes in a followup)
+
+ * WebCore.xcodeproj/project.pbxproj:
+
+ * dom/InProcessMessagePortChannel.cpp:
+ (WebCore::InProcessMessagePortChannel::createChannelBetweenPorts):
+ (WebCore::InProcessMessagePortChannel::isConnectedTo):
+ (WebCore::InProcessMessagePortChannel::entangleWithRemoteIfOpen):
+ (WebCore::InProcessMessagePortChannel::entangleIfOpen): Deleted.
+ * dom/InProcessMessagePortChannel.h:
+
+ * dom/MessageChannel.cpp:
+ (WebCore::MessageChannel::MessageChannel):
+ (WebCore::m_port2):
+
+ * dom/MessagePort.cpp:
+ (WebCore::allMessagePortsLock):
+ (WebCore::MessagePort::ref const):
+ (WebCore::MessagePort::deref const):
+ (WebCore::MessagePort::existingMessagePortForIdentifier):
+ (WebCore::MessagePort::MessagePort):
+ (WebCore::MessagePort::~MessagePort):
+ (WebCore::MessagePort::postMessage):
+ (WebCore::MessagePort::entangleWithRemote):
+ (WebCore::MessagePort::entanglePorts):
+ (WebCore::MessagePort::entangle): Deleted.
+ * dom/MessagePort.h:
+
+ * dom/MessagePortChannel.h:
+
+ * dom/MessagePortIdentifier.h: Added.
+ (WebCore::operator==):
+ (WebCore::MessagePortIdentifier::encode const):
+ (WebCore::MessagePortIdentifier::decode):
+ (WebCore::MessagePortIdentifier::hash const):
+ (WTF::MessagePortIdentifierHash::hash):
+ (WTF::MessagePortIdentifierHash::equal):
+ (WTF::HashTraits<WebCore::MessagePortIdentifier>::emptyValue):
+ (WTF::HashTraits<WebCore::MessagePortIdentifier>::constructDeletedValue):
+ (WTF::HashTraits<WebCore::MessagePortIdentifier>::isDeletedValue):
+
2018-01-02 Youenn Fablet <you...@apple.com>
Memory cache should not reuse resources with different credential fetch option
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (226335 => 226336)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-01-02 22:42:16 UTC (rev 226336)
@@ -1456,6 +1456,7 @@
51F6456A1F4539C000B54DED /* ServiceWorkerJobType.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645651F45399F00B54DED /* ServiceWorkerJobType.h */; settings = {ATTRIBUTES = (Private, ); }; };
51F645971F4A686F00B54DED /* SWServerRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645941F4A684F00B54DED /* SWServerRegistration.h */; settings = {ATTRIBUTES = (Private, ); }; };
51F645D51FECDBCE00B54DED /* Process.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645D31FECDBC800B54DED /* Process.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 51F645E01FF4594E00B54DED /* MessagePortIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
51F798F01BE880E7008AE491 /* IDBIndexInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F798EC1BE880D3008AE491 /* IDBIndexInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
51F886C01F32923100C193EF /* JSNavigatorServiceWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F886BF1F32920700C193EF /* JSNavigatorServiceWorker.h */; };
51FA2D78152132B300C1BA0B /* DOMWindowExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 517FBA18151AA71B00B57959 /* DOMWindowExtension.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -7926,6 +7927,7 @@
51F645A31F4C000C00B54DED /* ExceptionData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExceptionData.cpp; sourceTree = "<group>"; };
51F645D21FECDBC800B54DED /* Process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Process.cpp; sourceTree = "<group>"; };
51F645D31FECDBC800B54DED /* Process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Process.h; sourceTree = "<group>"; };
+ 51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortIdentifier.h; sourceTree = "<group>"; };
51F6A3D50663BF04004D2919 /* HTMLCanvasElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLCanvasElement.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
51F6A3D60663BF04004D2919 /* HTMLCanvasElement.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HTMLCanvasElement.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
51F798EB1BE880D3008AE491 /* IDBIndexInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBIndexInfo.cpp; sourceTree = "<group>"; };
@@ -25513,6 +25515,7 @@
E1ADECC60E76AD1F004A1A5E /* MessagePort.idl */,
512B57BE1FE9902D000A1E5E /* MessagePortChannel.cpp */,
41BF700A0FE86F49005E8DEC /* MessagePortChannel.h */,
+ 51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */,
CB8CF0151A934B43000D510B /* Microtasks.cpp */,
53B895AD19DC7C37009CAA93 /* Microtasks.h */,
E38D06091F8E811900649CF2 /* ModuleFetchParameters.h */,
@@ -28530,6 +28533,7 @@
75793E840D0CE0B3007FC0AC /* MessageEvent.h in Headers */,
E1ADECBF0E76ACF1004A1A5E /* MessagePort.h in Headers */,
41BF700C0FE86F49005E8DEC /* MessagePortChannel.h in Headers */,
+ 51F645E01FF4594E00B54DED /* MessagePortIdentifier.h in Headers */,
53B895AF19DC7ED9009CAA93 /* Microtasks.h in Headers */,
BC772C4F0C4EB3040083285F /* MIMETypeRegistry.h in Headers */,
52F10866162B6DA8009AC81E /* MixedContentChecker.h in Headers */,
Modified: trunk/Source/WebCore/dom/InProcessMessagePortChannel.cpp (226335 => 226336)
--- trunk/Source/WebCore/dom/InProcessMessagePortChannel.cpp 2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/InProcessMessagePortChannel.cpp 2018-01-02 22:42:16 UTC (rev 226336)
@@ -42,8 +42,8 @@
channel1->m_entangledChannel = channel2.ptr();
channel2->m_entangledChannel = channel1.ptr();
- port1.entangle(WTFMove(channel2));
- port2.entangle(WTFMove(channel1));
+ port1.entangleWithRemote(WTFMove(channel2));
+ port2.entangleWithRemote(WTFMove(channel1));
}
Ref<InProcessMessagePortChannel> InProcessMessagePortChannel::create(MessagePortQueue& incoming, MessagePortQueue& outgoing)
@@ -81,14 +81,14 @@
return m_incomingQueue->takeAllMessages();
}
-bool InProcessMessagePortChannel::isConnectedTo(MessagePort& port)
+bool InProcessMessagePortChannel::isConnectedTo(const MessagePortIdentifier& identifier)
{
// FIXME: What guarantees that the result remains the same after we release the lock?
Locker<Lock> locker(m_lock);
- return m_remotePort == &port;
+ return m_remotePort && m_remotePort->identifier() == identifier;
}
-bool InProcessMessagePortChannel::entangleIfOpen(MessagePort& port)
+bool InProcessMessagePortChannel::entangleWithRemoteIfOpen(const MessagePortIdentifier& identifier)
{
// We can't call member functions on our remote pair while holding our mutex or we'll deadlock,
// but we need to guard against the remote port getting closed/freed, so create a standalone reference.
@@ -101,8 +101,11 @@
if (!remote)
return false;
- remote->setRemotePort(&port);
+ auto entangledPort = MessagePort::existingMessagePortForIdentifier(identifier);
+ ASSERT(entangledPort);
+ remote->setRemotePort(entangledPort.get());
+
return true;
}
Modified: trunk/Source/WebCore/dom/InProcessMessagePortChannel.h (226335 => 226336)
--- trunk/Source/WebCore/dom/InProcessMessagePortChannel.h 2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/InProcessMessagePortChannel.h 2018-01-02 22:42:16 UTC (rev 226336)
@@ -38,8 +38,8 @@
void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) final;
Deque<std::unique_ptr<EventData>> takeAllMessagesFromRemote() final;
- bool isConnectedTo(MessagePort&) final;
- bool entangleIfOpen(MessagePort&) final;
+ bool isConnectedTo(const MessagePortIdentifier&) final;
+ bool entangleWithRemoteIfOpen(const MessagePortIdentifier&) final;
void disentangle() final;
bool hasPendingActivity() final;
MessagePort* locallyEntangledPort(const ScriptExecutionContext*) final;
Modified: trunk/Source/WebCore/dom/MessageChannel.cpp (226335 => 226336)
--- trunk/Source/WebCore/dom/MessageChannel.cpp 2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/MessageChannel.cpp 2018-01-02 22:42:16 UTC (rev 226336)
@@ -33,8 +33,8 @@
namespace WebCore {
MessageChannel::MessageChannel(ScriptExecutionContext& context)
- : m_port1(MessagePort::create(context))
- , m_port2(MessagePort::create(context))
+ : m_port1(MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() }))
+ , m_port2(MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() }))
{
MessagePortChannel::createChannelBetweenPorts(*m_port1, *m_port2);
}
Modified: trunk/Source/WebCore/dom/MessagePort.cpp (226335 => 226336)
--- trunk/Source/WebCore/dom/MessagePort.cpp 2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/MessagePort.cpp 2018-01-02 22:42:16 UTC (rev 226336)
@@ -34,9 +34,57 @@
namespace WebCore {
-MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext)
+static HashMap<MessagePortIdentifier, MessagePort*>& allMessagePorts()
+{
+ static NeverDestroyed<HashMap<MessagePortIdentifier, MessagePort*>> map;
+ return map;
+}
+
+static Lock& allMessagePortsLock()
+{
+ static NeverDestroyed<Lock> lock;
+ return lock;
+}
+
+void MessagePort::ref() const
+{
+ ++m_refCount;
+}
+
+void MessagePort::deref() const
+{
+ // MessagePort::existingMessagePortForIdentifier() is unique in that it holds a raw pointer to a MessagePort
+ // but might create a RefPtr from it.
+ // If that happens on one thread at the same time that a MessagePort is being deref'ed and destroyed on a
+ // different thread then Bad Things could happen.
+ // This custom deref() function is designed to handle that contention by guaranteeing that nobody can be
+ // creating a RefPtr inside existingMessagePortForIdentifier while the object is mid-deletion.
+
+ if (!--m_refCount) {
+ Locker<Lock> locker(allMessagePortsLock());
+
+ if (m_refCount)
+ return;
+
+ allMessagePorts().remove(m_identifier);
+ delete this;
+ }
+}
+
+RefPtr<MessagePort> MessagePort::existingMessagePortForIdentifier(const MessagePortIdentifier& identifier)
+{
+ Locker<Lock> locker(allMessagePortsLock());
+
+ return allMessagePorts().get(identifier);
+}
+
+MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier)
: ActiveDOMObject(&scriptExecutionContext)
+ , m_identifier(identifier)
{
+ Locker<Lock> locker(allMessagePortsLock());
+ allMessagePorts().set(m_identifier, this);
+
m_scriptExecutionContext->createdMessagePort(*this);
suspendIfNeeded();
@@ -45,6 +93,8 @@
MessagePort::~MessagePort()
{
+ ASSERT(allMessagePortsLock().isLocked());
+
close();
if (m_scriptExecutionContext)
m_scriptExecutionContext->destroyedMessagePort(*this);
@@ -65,9 +115,10 @@
// Make sure we aren't connected to any of the passed-in ports.
if (!ports.isEmpty()) {
for (auto& dataPort : ports) {
- if (dataPort == this || m_entangledChannel->isConnectedTo(*dataPort))
+ if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort->identifier()))
return Exception { DataCloneError };
}
+
auto disentangleResult = MessagePort::disentanglePorts(WTFMove(ports));
if (disentangleResult.hasException())
return disentangleResult.releaseException();
@@ -123,7 +174,7 @@
m_closed = true;
}
-void MessagePort::entangle(RefPtr<MessagePortChannel>&& remote)
+void MessagePort::entangleWithRemote(RefPtr<MessagePortChannel>&& remote)
{
// Only invoked to set our initial entanglement.
ASSERT(!m_entangledChannel);
@@ -130,7 +181,7 @@
ASSERT(m_scriptExecutionContext);
// Don't entangle the ports if the channel is closed.
- if (remote->entangleIfOpen(*this))
+ if (remote->entangleWithRemoteIfOpen(m_identifier))
m_entangledChannel = WTFMove(remote);
}
@@ -210,8 +261,8 @@
Vector<RefPtr<MessagePort>> portArray;
portArray.reserveInitialCapacity(channels->size());
for (unsigned int i = 0; i < channels->size(); ++i) {
- auto port = MessagePort::create(context);
- port->entangle(WTFMove((*channels)[i]));
+ auto port = MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() });
+ port->entangleWithRemote(WTFMove((*channels)[i]));
portArray.uncheckedAppend(WTFMove(port));
}
return portArray;
Modified: trunk/Source/WebCore/dom/MessagePort.h (226335 => 226336)
--- trunk/Source/WebCore/dom/MessagePort.h 2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/MessagePort.h 2018-01-02 22:42:16 UTC (rev 226336)
@@ -30,6 +30,7 @@
#include "EventTarget.h"
#include "ExceptionOr.h"
#include "MessagePortChannel.h"
+#include "MessagePortIdentifier.h"
namespace JSC {
class ExecState;
@@ -41,9 +42,9 @@
class Frame;
-class MessagePort final : public ThreadSafeRefCounted<MessagePort>, public ActiveDOMObject, public EventTargetWithInlineData {
+class MessagePort final : public ActiveDOMObject, public EventTargetWithInlineData {
public:
- static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(*new MessagePort(scriptExecutionContext)); }
+ static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier) { return adoptRef(*new MessagePort(scriptExecutionContext, identifier)); }
virtual ~MessagePort();
ExceptionOr<void> postMessage(JSC::ExecState&, JSC::JSValue message, Vector<JSC::Strong<JSC::JSObject>>&&);
@@ -51,12 +52,12 @@
void start();
void close();
- void entangle(RefPtr<MessagePortChannel>&&);
+ void entangleWithRemote(RefPtr<MessagePortChannel>&&);
// Returns nullptr if the passed-in vector is empty.
static ExceptionOr<std::unique_ptr<MessagePortChannelArray>> disentanglePorts(Vector<RefPtr<MessagePort>>&&);
-
static Vector<RefPtr<MessagePort>> entanglePorts(ScriptExecutionContext&, std::unique_ptr<MessagePortChannelArray>&&);
+ static RefPtr<MessagePort> existingMessagePortForIdentifier(const MessagePortIdentifier&);
void messageAvailable();
bool started() const { return m_started; }
@@ -68,9 +69,11 @@
// of the remote port (since it may live cross-process) - those platforms may always return null.
MessagePort* locallyEntangledPort() const;
- using ThreadSafeRefCounted::ref;
- using ThreadSafeRefCounted::deref;
+ const MessagePortIdentifier& identifier() const { return m_identifier; }
+ void ref() const;
+ void deref() const;
+
// ActiveDOMObject
const char* activeDOMObjectName() const final;
bool canSuspendForDocumentSuspension() const final;
@@ -85,7 +88,7 @@
void derefEventTarget() final { deref(); }
private:
- explicit MessagePort(ScriptExecutionContext&);
+ explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier&);
bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final;
@@ -101,6 +104,10 @@
RefPtr<MessagePort> m_messageProtector;
bool m_started { false };
bool m_closed { false };
+
+ MessagePortIdentifier m_identifier;
+
+ mutable std::atomic<unsigned> m_refCount { 1 };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/MessagePortChannel.h (226335 => 226336)
--- trunk/Source/WebCore/dom/MessagePortChannel.h 2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/MessagePortChannel.h 2018-01-02 22:42:16 UTC (rev 226336)
@@ -43,6 +43,8 @@
class MessagePortChannel;
class ScriptExecutionContext;
+struct MessagePortIdentifier;
+
// The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1.
typedef Vector<RefPtr<MessagePortChannel>, 1> MessagePortChannelArray;
@@ -64,12 +66,10 @@
static void createChannelBetweenPorts(MessagePort&, MessagePort&);
- void setRemotePort(MessagePort*);
-
virtual void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) = 0;
virtual Deque<std::unique_ptr<EventData>> takeAllMessagesFromRemote() = 0;
- virtual bool isConnectedTo(MessagePort&) = 0;
- virtual bool entangleIfOpen(MessagePort&) = 0;
+ virtual bool isConnectedTo(const MessagePortIdentifier&) = 0;
+ virtual bool entangleWithRemoteIfOpen(const MessagePortIdentifier&) = 0;
virtual void disentangle() = 0;
virtual bool hasPendingActivity() = 0;
virtual MessagePort* locallyEntangledPort(const ScriptExecutionContext*) = 0;
Added: trunk/Source/WebCore/dom/MessagePortIdentifier.h (0 => 226336)
--- trunk/Source/WebCore/dom/MessagePortIdentifier.h (rev 0)
+++ trunk/Source/WebCore/dom/MessagePortIdentifier.h 2018-01-02 22:42:16 UTC (rev 226336)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 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. AND ITS CONTRIBUTORS ``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 ITS 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 "Process.h"
+#include <wtf/Hasher.h>
+
+namespace WebCore {
+
+struct MessagePortIdentifier {
+ ProcessIdentifier processIdentifier;
+ enum PortIdentifierType { };
+ ObjectIdentifier<PortIdentifierType> portIdentifier;
+
+ unsigned hash() const;
+
+ template<class Encoder> void encode(Encoder&) const;
+ template<class Decoder> static std::optional<MessagePortIdentifier> decode(Decoder&);
+};
+
+inline bool operator==(const MessagePortIdentifier& a, const MessagePortIdentifier& b)
+{
+ return a.processIdentifier == b.processIdentifier && a.portIdentifier == b.portIdentifier;
+}
+
+template<class Encoder>
+void MessagePortIdentifier::encode(Encoder& encoder) const
+{
+ encoder << processIdentifier << portIdentifier;
+}
+
+template<class Decoder>
+std::optional<MessagePortIdentifier> MessagePortIdentifier::decode(Decoder& decoder)
+{
+ std::optional<ProcessIdentifier> processIdentifier;
+ decoder >> processIdentifier;
+ if (!processIdentifier)
+ return std::nullopt;
+
+ std::optional<ObjectIdentifier<PortIdentifierType>> portIdentifier;
+ decoder >> portIdentifier;
+ if (!portIdentifier)
+ return std::nullopt;
+
+ return { { WTFMove(*processIdentifier), WTFMove(*portIdentifier) } };
+}
+
+inline unsigned MessagePortIdentifier::hash() const
+{
+ return computeHash(processIdentifier.toUInt64(), portIdentifier.toUInt64());
+}
+
+} // namespace WebCore
+
+namespace WTF {
+
+struct MessagePortIdentifierHash {
+ static unsigned hash(const WebCore::MessagePortIdentifier& key) { return key.hash(); }
+ static bool equal(const WebCore::MessagePortIdentifier& a, const WebCore::MessagePortIdentifier& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+template<> struct HashTraits<WebCore::MessagePortIdentifier> : GenericHashTraits<WebCore::MessagePortIdentifier> {
+ static WebCore::MessagePortIdentifier emptyValue() { return { }; }
+
+ static void constructDeletedValue(WebCore::MessagePortIdentifier& slot) { slot.processIdentifier = makeObjectIdentifier<WebCore::ProcessIdentifierType>(std::numeric_limits<uint64_t>::max()); }
+
+ static bool isDeletedValue(const WebCore::MessagePortIdentifier& slot) { return slot.processIdentifier.toUInt64() == std::numeric_limits<uint64_t>::max(); }
+};
+
+template<> struct DefaultHash<WebCore::MessagePortIdentifier> {
+ typedef MessagePortIdentifierHash Hash;
+};
+
+} // namespace WTF