Revert "[WGPUFuture] Move the EventManager in the wire to appear in the Instance."

This reverts commit 6ecbeedd4e016dfa304082bc7e3639b54d179ce1.

Reason for revert: Likely breaking compilation on  linux-libfuzzer-asan-rel 

Original change's description:
> [WGPUFuture] Move the EventManager in the wire to appear in the Instance.
>
> - Note that the EventManager only appears to be in the Instance because
>   it may need to outlive the Instance, and so actually lives on the
>   Client.
>
> Bug: dawn:2061
> Change-Id: I601a27cd7ee90e4dcb53fd9e45144a6059c00054
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/167840
> Commit-Queue: Loko Kung <lokokung@google.com>
> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
> Reviewed-by: Austin Eng <enga@chromium.org>
> Kokoro: Kokoro <noreply+kokoro@google.com>

TBR=kainino@chromium.org,enga@chromium.org,noreply+kokoro@google.com,dawn-scoped@luci-project-accounts.iam.gserviceaccount.com,lokokung@google.com

Change-Id: If7b5143ef8d7d1ece1fac29a7a10e2dd388e2826
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: dawn:2061
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/168648
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/generator/templates/dawn/wire/client/ApiProcs.cpp b/generator/templates/dawn/wire/client/ApiProcs.cpp
index 6f27e18..c1cff6d 100644
--- a/generator/templates/dawn/wire/client/ApiProcs.cpp
+++ b/generator/templates/dawn/wire/client/ApiProcs.cpp
@@ -36,18 +36,6 @@
 
 namespace dawn::wire::client {
 
-    // Template function for constexpr branching when creating new objects.
-    template <typename Parent, typename Child, typename... Args>
-    Child* Create(Parent p, Args... args) {
-        if constexpr (std::is_constructible_v<Child, const ObjectBaseParams&, decltype(args)...>) {
-            return p->GetClient()->template Make<Child>(args...);
-        } else if constexpr (std::is_constructible_v<Child, const ObjectBaseParams&, const ObjectHandle&, decltype(args)...>) {
-            return p->GetClient()->template Make<Child>(p->GetEventManagerHandle(), args...);
-        } else {
-            return p->GetClient()->template Make<Child>();
-        }
-    }
-
     //* Outputs an rvalue that's the number of elements a pointer member points to.
     {% macro member_length(member, accessor) -%}
         {%- if member.length == "constant" -%}
@@ -85,11 +73,22 @@
                     //* For object creation, store the object ID the client will use for the result.
                     {% if method.return_type.category == "object" %}
                         {% set ReturnObj = method.return_type.name.CamelCase() %}
-                        {{ReturnObj}}* returnObject = Create<{{as_wireType(type)}}, {{ReturnObj}}>(self
+
+                        {{ReturnObj}}* returnObject;
+                        if constexpr (std::is_constructible_v<
+                            {{- ReturnObj}}, const ObjectBaseParams&
                             {%- for arg in method.arguments -%}
-                                    , {{as_varName(arg.name)}}
+                                , decltype({{as_varName(arg.name)}})
                             {%- endfor -%}
-                        );
+                        >) {
+                            returnObject = self->GetClient()->Make<{{ReturnObj}}>(
+                                {%- for arg in method.arguments -%}
+                                    {% if not loop.first %}, {% endif %}{{as_varName(arg.name)}}
+                                {%- endfor -%}
+                            );
+                        } else {
+                            returnObject = self->GetClient()->Make<{{ReturnObj}}>();
+                        }
                         cmd.result = returnObject->GetWireHandle();
                     {% endif %}
 
diff --git a/include/dawn/wire/WireClient.h b/include/dawn/wire/WireClient.h
index 5b0a3fa..448318f 100644
--- a/include/dawn/wire/WireClient.h
+++ b/include/dawn/wire/WireClient.h
@@ -86,7 +86,7 @@
     ReservedTexture ReserveTexture(WGPUDevice device, const WGPUTextureDescriptor* descriptor);
     ReservedSwapChain ReserveSwapChain(WGPUDevice device,
                                        const WGPUSwapChainDescriptor* descriptor);
-    ReservedDevice ReserveDevice(WGPUInstance instance);
+    ReservedDevice ReserveDevice();
     ReservedInstance ReserveInstance(const WGPUInstanceDescriptor* descriptor = nullptr);
 
     void ReclaimTextureReservation(const ReservedTexture& reservation);
diff --git a/src/dawn/dawn_wire.json b/src/dawn/dawn_wire.json
index d0ded98..09f0fad 100644
--- a/src/dawn/dawn_wire.json
+++ b/src/dawn/dawn_wire.json
@@ -33,7 +33,6 @@
     "commands": {
         "buffer map async": [
             { "name": "buffer id", "type": "ObjectId", "id_type": "buffer" },
-            { "name": "event manager handle", "type": "ObjectHandle" },
             { "name": "future", "type": "future" },
             { "name": "mode", "type": "map mode" },
             { "name": "offset", "type": "uint64_t"},
@@ -77,7 +76,6 @@
         ],
         "queue on submitted work done": [
             { "name": "queue id", "type": "ObjectId", "id_type": "queue" },
-            { "name": "event manager handle", "type": "ObjectHandle" },
             { "name": "future", "type": "future" }
         ],
         "queue write buffer": [
@@ -101,7 +99,6 @@
         ],
         "instance request adapter": [
             { "name": "instance id", "type": "ObjectId", "id_type": "instance" },
-            { "name": "event manager handle", "type": "ObjectHandle" },
             { "name": "future", "type": "future" },
             { "name": "adapter object handle", "type": "ObjectHandle", "handle_type": "adapter"},
             { "name": "options", "type": "request adapter options", "annotation": "const*", "optional": true }
@@ -115,8 +112,7 @@
     },
     "return commands": {
         "buffer map async callback": [
-            { "name": "buffer", "type": "ObjectHandle", "handle_type": "buffer", "_comment": "TODO(dawn:2061) Remove this field once mapping is updated." },
-            { "name": "event manager", "type": "ObjectHandle" },
+            { "name": "buffer", "type": "ObjectHandle", "handle_type": "buffer" },
             { "name": "future", "type": "future" },
             { "name": "status", "type": "uint32_t" },
             { "name": "read data update info length", "type": "uint64_t" },
@@ -156,8 +152,8 @@
             { "name": "message", "type": "char", "annotation": "const*", "length": "strlen" }
         ],
         "queue work done callback": [
-            { "name": "event manager", "type": "ObjectHandle" },
-            { "name": "future", "type": "future" },
+            { "name": "queue", "type": "ObjectHandle", "handle_type": "queue" },
+	    { "name": "future", "type": "future" },
             { "name": "status", "type": "queue work done status" }
         ],
         "shader module get compilation info callback": [
@@ -167,7 +163,7 @@
             { "name": "info", "type": "compilation info", "annotation": "const*", "optional": true }
         ],
         "instance request adapter callback": [
-            { "name": "event manager", "type": "ObjectHandle" },
+            { "name": "instance", "type": "ObjectHandle", "handle_type": "instance" },
             { "name": "future", "type": "future" },
             { "name": "status", "type": "request adapter status" },
             { "name": "message", "type": "char", "annotation": "const*", "length": "strlen", "optional": true },
diff --git a/src/dawn/samples/SampleUtils.cpp b/src/dawn/samples/SampleUtils.cpp
index f1aa2a9..7c48112 100644
--- a/src/dawn/samples/SampleUtils.cpp
+++ b/src/dawn/samples/SampleUtils.cpp
@@ -236,11 +236,7 @@
             procs = dawn::wire::client::GetProcs();
             s2cBuf->SetHandler(wireClient);
 
-            auto instanceReservation = wireClient->ReserveInstance();
-            wireServer->InjectInstance(instance->Get(), instanceReservation.id,
-                                       instanceReservation.generation);
-
-            auto deviceReservation = wireClient->ReserveDevice(instanceReservation.instance);
+            auto deviceReservation = wireClient->ReserveDevice();
             wireServer->InjectDevice(backendDevice, deviceReservation.id,
                                      deviceReservation.generation);
             cDevice = deviceReservation.device;
diff --git a/src/dawn/tests/unittests/GetProcAddressTests.cpp b/src/dawn/tests/unittests/GetProcAddressTests.cpp
index 1f8dabc..b3ea500 100644
--- a/src/dawn/tests/unittests/GetProcAddressTests.cpp
+++ b/src/dawn/tests/unittests/GetProcAddressTests.cpp
@@ -91,8 +91,7 @@
                 clientDesc.serializer = mC2sBuf.get();
                 mWireClient = std::make_unique<wire::WireClient>(clientDesc);
 
-                mDevice = wgpu::Device::Acquire(
-                    mWireClient->ReserveDevice(ToAPI(mNativeInstance.Get())).device);
+                mDevice = wgpu::Device::Acquire(mWireClient->ReserveDevice().device);
                 mProcs = wire::client::GetProcs();
                 break;
             }
diff --git a/src/dawn/tests/unittests/wire/WireAdapterTests.cpp b/src/dawn/tests/unittests/wire/WireAdapterTests.cpp
index 469ef93..d3c8af7 100644
--- a/src/dawn/tests/unittests/wire/WireAdapterTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireAdapterTests.cpp
@@ -55,9 +55,18 @@
     void SetUp() override {
         WireTest::SetUp();
 
-        WGPURequestAdapterOptions options = {};
+        auto reservation = GetWireClient()->ReserveInstance();
+        instance = wgpu::Instance::Acquire(reservation.instance);
+
+        WGPUInstance apiInstance = api.GetNewInstance();
+        EXPECT_CALL(api, InstanceReference(apiInstance));
+        EXPECT_TRUE(
+            GetWireServer()->InjectInstance(apiInstance, reservation.id, reservation.generation));
+
+        wgpu::RequestAdapterOptions options = {};
         MockCallback<WGPURequestAdapterCallback> cb;
-        wgpuInstanceRequestAdapter(instance, &options, cb.Callback(), cb.MakeUserdata(this));
+        auto* userdata = cb.MakeUserdata(this);
+        instance.RequestAdapter(&options, cb.Callback(), userdata);
 
         // Expect the server to receive the message. Then, mock a fake reply.
         apiAdapter = api.GetNewAdapter();
@@ -102,10 +111,12 @@
 
     void TearDown() override {
         adapter = nullptr;
+        instance = nullptr;
         WireTest::TearDown();
     }
 
     WGPUAdapter apiAdapter;
+    wgpu::Instance instance;
     wgpu::Adapter adapter;
 };
 
diff --git a/src/dawn/tests/unittests/wire/WireDisconnectTests.cpp b/src/dawn/tests/unittests/wire/WireDisconnectTests.cpp
index 889b52f..d9c96b9 100644
--- a/src/dawn/tests/unittests/wire/WireDisconnectTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireDisconnectTests.cpp
@@ -173,7 +173,7 @@
     // Expect release on all objects created by the client. Note: the device
     // should be deleted first because it may free its reference to the default queue
     // on deletion.
-    Sequence s1, s2, s3, s4;
+    Sequence s1, s2, s3;
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(apiDevice, nullptr, nullptr))
         .Times(1)
         .InSequence(s1, s2);
@@ -183,11 +183,10 @@
     EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(apiDevice, nullptr, nullptr))
         .Times(1)
         .InSequence(s1, s2);
-    EXPECT_CALL(api, DeviceRelease(apiDevice)).Times(1).InSequence(s1, s2, s3, s4);
+    EXPECT_CALL(api, DeviceRelease(apiDevice)).Times(1).InSequence(s1, s2, s3);
     EXPECT_CALL(api, QueueRelease(apiQueue)).Times(1).InSequence(s1);
     EXPECT_CALL(api, CommandEncoderRelease(apiCommandEncoder)).Times(1).InSequence(s2);
     EXPECT_CALL(api, SamplerRelease(apiSampler)).Times(1).InSequence(s3);
-    EXPECT_CALL(api, InstanceRelease(apiInstance)).Times(1).InSequence(s4);
     FlushClient();
 
     // Signal that we already released and cleared callbacks for |apiDevice|
diff --git a/src/dawn/tests/unittests/wire/WireFutureTest.h b/src/dawn/tests/unittests/wire/WireFutureTest.h
index 042db62..b065ddd 100644
--- a/src/dawn/tests/unittests/wire/WireFutureTest.h
+++ b/src/dawn/tests/unittests/wire/WireFutureTest.h
@@ -96,6 +96,20 @@
   protected:
     using testing::WithParamInterface<Params>::GetParam;
 
+    void SetUp() override {
+        WireTest::SetUp();
+
+        auto reservation = GetWireClient()->ReserveInstance();
+        instance = reservation.instance;
+
+        apiInstance = api.GetNewInstance();
+        EXPECT_CALL(api, InstanceReference(apiInstance));
+        EXPECT_TRUE(
+            GetWireServer()->InjectInstance(apiInstance, reservation.id, reservation.generation));
+    }
+
+    void TearDown() override { WireTest::TearDown(); }
+
     // Calls the actual API that the test suite is exercising given the callback mode. This should
     // be used in favor of directly calling the API because the Async mode actually calls a
     // different entry point.
@@ -189,6 +203,9 @@
         }
     }
 
+    WGPUInstance instance;
+    WGPUInstance apiInstance;
+
   private:
     AsyncFT mAsyncF = AsyncF;
     FutureFT mFutureF = FutureF;
diff --git a/src/dawn/tests/unittests/wire/WireInjectDeviceTests.cpp b/src/dawn/tests/unittests/wire/WireInjectDeviceTests.cpp
index 5b0a92f..2e129ae 100644
--- a/src/dawn/tests/unittests/wire/WireInjectDeviceTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInjectDeviceTests.cpp
@@ -47,7 +47,7 @@
 // Test that reserving and injecting a device makes calls on the client object forward to the
 // server object correctly.
 TEST_F(WireInjectDeviceTests, CallAfterReserveInject) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    ReservedDevice reservation = GetWireClient()->ReserveDevice();
 
     WGPUDevice serverDevice = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice));
@@ -73,8 +73,8 @@
 
 // Test that reserve correctly returns different IDs each time.
 TEST_F(WireInjectDeviceTests, ReserveDifferentIDs) {
-    ReservedDevice reservation1 = GetWireClient()->ReserveDevice(instance);
-    ReservedDevice reservation2 = GetWireClient()->ReserveDevice(instance);
+    ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
+    ReservedDevice reservation2 = GetWireClient()->ReserveDevice();
 
     ASSERT_NE(reservation1.id, reservation2.id);
     ASSERT_NE(reservation1.device, reservation2.device);
@@ -82,7 +82,7 @@
 
 // Test that injecting the same id without a destroy first fails.
 TEST_F(WireInjectDeviceTests, InjectExistingID) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    ReservedDevice reservation = GetWireClient()->ReserveDevice();
 
     WGPUDevice serverDevice = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice));
@@ -106,7 +106,7 @@
 
 // Test that the server only borrows the device and does a single reference-release
 TEST_F(WireInjectDeviceTests, InjectedDeviceLifetime) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    ReservedDevice reservation = GetWireClient()->ReserveDevice();
 
     // Injecting the device adds a reference
     WGPUDevice serverDevice = api.GetNewDevice();
@@ -133,7 +133,7 @@
 // Test that it is an error to get the primary queue of a device before it has been
 // injected on the server.
 TEST_F(WireInjectDeviceTests, GetQueueBeforeInject) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    ReservedDevice reservation = GetWireClient()->ReserveDevice();
 
     wgpuDeviceGetQueue(reservation.device);
     FlushClient(false);
@@ -142,7 +142,7 @@
 // Test that it is valid to get the primary queue of a device after it has been
 // injected on the server.
 TEST_F(WireInjectDeviceTests, GetQueueAfterInject) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    ReservedDevice reservation = GetWireClient()->ReserveDevice();
 
     WGPUDevice serverDevice = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice));
@@ -169,8 +169,8 @@
 // Test that the list of live devices can be reflected using GetDevice.
 TEST_F(WireInjectDeviceTests, ReflectLiveDevices) {
     // Reserve two devices.
-    ReservedDevice reservation1 = GetWireClient()->ReserveDevice(instance);
-    ReservedDevice reservation2 = GetWireClient()->ReserveDevice(instance);
+    ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
+    ReservedDevice reservation2 = GetWireClient()->ReserveDevice();
 
     // Inject both devices.
 
@@ -217,7 +217,7 @@
 // objects instead.
 TEST_F(WireInjectDeviceTests, TrackChildObjectsWithTwoReservedDevices) {
     // Reserve one device, inject it, and get the primary queue.
-    ReservedDevice reservation1 = GetWireClient()->ReserveDevice(instance);
+    ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
 
     WGPUDevice serverDevice1 = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice1));
@@ -236,7 +236,7 @@
     FlushClient();
 
     // Reserve a second device, and inject it.
-    ReservedDevice reservation2 = GetWireClient()->ReserveDevice(instance);
+    ReservedDevice reservation2 = GetWireClient()->ReserveDevice();
 
     WGPUDevice serverDevice2 = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice2));
@@ -267,17 +267,17 @@
 TEST_F(WireInjectDeviceTests, ReclaimDeviceReservation) {
     // Test that doing a reservation and full release is an error.
     {
-        ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+        ReservedDevice reservation = GetWireClient()->ReserveDevice();
         wgpuDeviceRelease(reservation.device);
         FlushClient(false);
     }
 
     // Test that doing a reservation and then reclaiming it recycles the ID.
     {
-        ReservedDevice reservation1 = GetWireClient()->ReserveDevice(instance);
+        ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
         GetWireClient()->ReclaimDeviceReservation(reservation1);
 
-        ReservedDevice reservation2 = GetWireClient()->ReserveDevice(instance);
+        ReservedDevice reservation2 = GetWireClient()->ReserveDevice();
 
         // The ID is the same, but the generation is still different.
         ASSERT_EQ(reservation1.id, reservation2.id);
diff --git a/src/dawn/tests/unittests/wire/WireTest.cpp b/src/dawn/tests/unittests/wire/WireTest.cpp
index 479ebcc..c268bbd 100644
--- a/src/dawn/tests/unittests/wire/WireTest.cpp
+++ b/src/dawn/tests/unittests/wire/WireTest.cpp
@@ -53,6 +53,7 @@
 void WireTest::SetUp() {
     DawnProcTable mockProcs;
     api.GetProcTable(&mockProcs);
+    WGPUDevice mockDevice = api.GetNewDevice();
 
     // This SetCallback call cannot be ignored because it is done as soon as we start the server
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(_, _, _)).Times(Exactly(1));
@@ -80,18 +81,12 @@
 
     dawnProcSetProcs(&dawn::wire::client::GetProcs());
 
-    auto instanceReservation = GetWireClient()->ReserveInstance();
-    instance = instanceReservation.instance;
-    apiInstance = api.GetNewInstance();
-    EXPECT_CALL(api, InstanceReference(apiInstance));
-    EXPECT_TRUE(GetWireServer()->InjectInstance(apiInstance, instanceReservation.id,
-                                                instanceReservation.generation));
+    auto deviceReservation = mWireClient->ReserveDevice();
+    EXPECT_CALL(api, DeviceReference(mockDevice));
+    mWireServer->InjectDevice(mockDevice, deviceReservation.id, deviceReservation.generation);
 
-    auto deviceReservation = mWireClient->ReserveDevice(instance);
     device = deviceReservation.device;
-    apiDevice = api.GetNewDevice();
-    EXPECT_CALL(api, DeviceReference(apiDevice));
-    mWireServer->InjectDevice(apiDevice, deviceReservation.id, deviceReservation.generation);
+    apiDevice = mockDevice;
 
     // The GetQueue is done on WireClient startup so we expect it now.
     queue = wgpuDeviceGetQueue(device);
@@ -150,7 +145,6 @@
 void WireTest::DeleteServer() {
     EXPECT_CALL(api, QueueRelease(apiQueue)).Times(1);
     EXPECT_CALL(api, DeviceRelease(apiDevice)).Times(1);
-    EXPECT_CALL(api, InstanceRelease(apiInstance)).Times(1);
 
     if (mWireServer) {
         // These are called on server destruction to clear the callbacks. They must not be
diff --git a/src/dawn/tests/unittests/wire/WireTest.h b/src/dawn/tests/unittests/wire/WireTest.h
index a45c651..e7d6710 100644
--- a/src/dawn/tests/unittests/wire/WireTest.h
+++ b/src/dawn/tests/unittests/wire/WireTest.h
@@ -145,8 +145,6 @@
     void DefaultApiDeviceWasReleased();
 
     testing::StrictMock<MockProcTable> api;
-    WGPUInstance instance;
-    WGPUInstance apiInstance;
     WGPUDevice apiDevice;
     WGPUQueue apiQueue;
     WGPUDevice device;
diff --git a/src/dawn/wire/ObjectHandle.cpp b/src/dawn/wire/ObjectHandle.cpp
index 813dcd2..436901c 100644
--- a/src/dawn/wire/ObjectHandle.cpp
+++ b/src/dawn/wire/ObjectHandle.cpp
@@ -59,10 +59,6 @@
     return *this;
 }
 
-bool ObjectHandle::operator==(const ObjectHandle& other) const {
-    return id == other.id && generation == other.generation;
-}
-
 bool ObjectHandle::IsValid() const {
     return id > 0;
 }
diff --git a/src/dawn/wire/ObjectHandle.h b/src/dawn/wire/ObjectHandle.h
index 117a43a..443df72 100644
--- a/src/dawn/wire/ObjectHandle.h
+++ b/src/dawn/wire/ObjectHandle.h
@@ -28,11 +28,8 @@
 #ifndef DAWN_WIRE_OBJECTHANDLE_H_
 #define DAWN_WIRE_OBJECTHANDLE_H_
 
-#include <cstddef>
 #include <cstdint>
 
-#include "dawn/common/HashUtils.h"
-
 namespace dawn::wire {
 
 using ObjectId = uint32_t;
@@ -62,20 +59,9 @@
     ObjectHandle& AssignFrom(const ObjectHandle& rhs);
     ObjectHandle& AssignFrom(const volatile ObjectHandle& rhs);
 
-    bool operator==(const ObjectHandle& other) const;
-
     bool IsValid() const;
 };
 
 }  // namespace dawn::wire
 
-template <>
-struct std::hash<dawn::wire::ObjectHandle> {
-    size_t operator()(const dawn::wire::ObjectHandle& value) const {
-        size_t hash = dawn::Hash(value.id);
-        dawn::HashCombine(&hash, value.generation);
-        return hash;
-    }
-};
-
 #endif  // DAWN_WIRE_OBJECTHANDLE_H_
diff --git a/src/dawn/wire/WireClient.cpp b/src/dawn/wire/WireClient.cpp
index 313073f..21f62d5 100644
--- a/src/dawn/wire/WireClient.cpp
+++ b/src/dawn/wire/WireClient.cpp
@@ -51,8 +51,8 @@
     return mImpl->ReserveSwapChain(device, descriptor);
 }
 
-ReservedDevice WireClient::ReserveDevice(WGPUInstance instance) {
-    return mImpl->ReserveDevice(instance);
+ReservedDevice WireClient::ReserveDevice() {
+    return mImpl->ReserveDevice();
 }
 
 ReservedInstance WireClient::ReserveInstance(const WGPUInstanceDescriptor* descriptor) {
diff --git a/src/dawn/wire/client/Adapter.cpp b/src/dawn/wire/client/Adapter.cpp
index 3a85769..c98cc93 100644
--- a/src/dawn/wire/client/Adapter.cpp
+++ b/src/dawn/wire/client/Adapter.cpp
@@ -163,7 +163,7 @@
 
     // The descriptor is passed so that the deviceLostCallback can be tracked client-side and called
     // when the device is lost.
-    Device* device = client->Make<Device>(GetEventManagerHandle(), descriptor);
+    Device* device = client->Make<Device>(descriptor);
     uint64_t serial = mRequestDeviceRequests.Add({callback, device->GetWireId(), userdata});
 
     // Ensure the device lost callback isn't serialized as part of the command, as it cannot be
diff --git a/src/dawn/wire/client/Adapter.h b/src/dawn/wire/client/Adapter.h
index dd88635..b7cf683 100644
--- a/src/dawn/wire/client/Adapter.h
+++ b/src/dawn/wire/client/Adapter.h
@@ -39,9 +39,9 @@
 
 namespace dawn::wire::client {
 
-class Adapter final : public ObjectWithEventsBase {
+class Adapter final : public ObjectBase {
   public:
-    using ObjectWithEventsBase::ObjectWithEventsBase;
+    using ObjectBase::ObjectBase;
     ~Adapter() override;
 
     void CancelCallbacksForDisconnect() override;
diff --git a/src/dawn/wire/client/Buffer.cpp b/src/dawn/wire/client/Buffer.cpp
index d5e44c8..974d2c5 100644
--- a/src/dawn/wire/client/Buffer.cpp
+++ b/src/dawn/wire/client/Buffer.cpp
@@ -159,7 +159,7 @@
     // Create the buffer and send the creation command.
     // This must happen after any potential error buffer creation
     // as server expects allocating ids to be monotonically increasing
-    Buffer* buffer = wireClient->Make<Buffer>(device->GetEventManagerHandle(), descriptor);
+    Buffer* buffer = wireClient->Make<Buffer>(descriptor);
     buffer->mDestructWriteHandleOnUnmap = false;
 
     if (descriptor->mappedAtCreation) {
@@ -205,10 +205,8 @@
     return ToAPI(buffer);
 }
 
-Buffer::Buffer(const ObjectBaseParams& params,
-               const ObjectHandle& eventManagerHandle,
-               const WGPUBufferDescriptor* descriptor)
-    : ObjectWithEventsBase(params, eventManagerHandle),
+Buffer::Buffer(const ObjectBaseParams& params, const WGPUBufferDescriptor* descriptor)
+    : ObjectBase(params),
       mMapStateData(AcquireRef(new MapStateData{})),
       mSize(descriptor->size),
       mUsage(static_cast<WGPUBufferUsage>(descriptor->usage)) {}
@@ -220,8 +218,8 @@
 
 bool Buffer::SetFutureStatus(WGPUBufferMapAsyncStatus status) {
     DAWN_ASSERT(mMapStateData->pendingRequest);
-    return GetEventManager().SetFutureReady<MapAsyncEvent>(mMapStateData->pendingRequest->futureID,
-                                                           status) == WireResult::Success;
+    return GetClient()->GetEventManager()->SetFutureReady<MapAsyncEvent>(
+               mMapStateData->pendingRequest->futureID, status) == WireResult::Success;
 }
 
 void Buffer::SetFutureStatusAndClearPending(WGPUBufferMapAsyncStatus status) {
@@ -233,7 +231,7 @@
 
     FutureID futureID = mMapStateData->pendingRequest->futureID;
     mMapStateData->pendingRequest = std::nullopt;
-    DAWN_UNUSED(GetEventManager().SetFutureReady<MapAsyncEvent>(futureID, status));
+    DAWN_UNUSED(GetClient()->GetEventManager()->SetFutureReady<MapAsyncEvent>(futureID, status));
     return;
 }
 
@@ -256,14 +254,14 @@
     DAWN_ASSERT(GetRefcount() != 0);
 
     Client* client = GetClient();
-    auto [futureIDInternal, tracked] =
-        GetEventManager().TrackEvent(std::make_unique<MapAsyncEvent>(callbackInfo, mMapStateData));
+    auto [futureIDInternal, tracked] = client->GetEventManager()->TrackEvent(
+        std::make_unique<MapAsyncEvent>(callbackInfo, mMapStateData));
     if (!tracked) {
         return {futureIDInternal};
     }
 
     if (mMapStateData->pendingRequest) {
-        DAWN_UNUSED(GetEventManager().SetFutureReady<MapAsyncEvent>(
+        DAWN_UNUSED(client->GetEventManager()->SetFutureReady<MapAsyncEvent>(
             futureIDInternal, WGPUBufferMapAsyncStatus_MappingAlreadyPending));
         return {futureIDInternal};
     }
@@ -286,7 +284,6 @@
     // Serialize the command to send to the server.
     BufferMapAsyncCmd cmd;
     cmd.bufferId = GetWireId();
-    cmd.eventManagerHandle = GetEventManagerHandle();
     cmd.future = {futureIDInternal};
     cmd.mode = mode;
     cmd.offset = offset;
diff --git a/src/dawn/wire/client/Buffer.h b/src/dawn/wire/client/Buffer.h
index f86c918..5cf4c6a 100644
--- a/src/dawn/wire/client/Buffer.h
+++ b/src/dawn/wire/client/Buffer.h
@@ -64,13 +64,11 @@
     MapState mapState = MapState::Unmapped;
 };
 
-class Buffer final : public ObjectWithEventsBase {
+class Buffer final : public ObjectBase {
   public:
     static WGPUBuffer Create(Device* device, const WGPUBufferDescriptor* descriptor);
 
-    Buffer(const ObjectBaseParams& params,
-           const ObjectHandle& eventManagerHandle,
-           const WGPUBufferDescriptor* descriptor);
+    Buffer(const ObjectBaseParams& params, const WGPUBufferDescriptor* descriptor);
     ~Buffer() override;
 
     bool OnMapAsyncCallback(WGPUFuture future,
diff --git a/src/dawn/wire/client/Client.cpp b/src/dawn/wire/client/Client.cpp
index 32d78d2..569976b 100644
--- a/src/dawn/wire/client/Client.cpp
+++ b/src/dawn/wire/client/Client.cpp
@@ -52,6 +52,7 @@
 
 Client::Client(CommandSerializer* serializer, MemoryTransferService* memoryTransferService)
     : ClientBase(), mSerializer(serializer), mMemoryTransferService(memoryTransferService) {
+    mEventManager = std::make_unique<EventManager>(this);
     if (mMemoryTransferService == nullptr) {
         // If a MemoryTransferService is not provided, fall back to inline memory.
         mOwnedMemoryTransferService = CreateInlineMemoryTransferService();
@@ -60,6 +61,7 @@
 }
 
 Client::~Client() {
+    mEventManager->ShutDown();
     DestroyAllObjects();
 }
 
@@ -119,8 +121,8 @@
     return result;
 }
 
-ReservedDevice Client::ReserveDevice(WGPUInstance instance) {
-    Device* device = Make<Device>(FromAPI(instance)->GetEventManagerHandle(), nullptr);
+ReservedDevice Client::ReserveDevice() {
+    Device* device = Make<Device>(nullptr);
 
     ReservedDevice result;
     result.device = ToAPI(device);
@@ -137,10 +139,6 @@
         return {nullptr, 0, 0};
     }
 
-    // Reserve an EventManager for the given instance and make the association in the map.
-    mEventManagers[ObjectHandle(instance->GetWireId(), instance->GetWireGeneration())] =
-        std::make_unique<EventManager>();
-
     ReservedInstance result;
     result.instance = ToAPI(instance);
     result.id = instance->GetWireId();
@@ -164,10 +162,8 @@
     Free(FromAPI(reservation.instance));
 }
 
-EventManager& Client::GetEventManager(const ObjectHandle& instance) {
-    auto it = mEventManagers.find(instance);
-    DAWN_ASSERT(it != mEventManagers.end());
-    return *it->second;
+EventManager* Client::GetEventManager() {
+    return mEventManager.get();
 }
 
 void Client::Disconnect() {
@@ -188,11 +184,7 @@
             object->value()->CancelCallbacksForDisconnect();
         }
     }
-
-    // Transition all event managers to ClientDropped state.
-    for (auto& [_, eventManager] : mEventManagers) {
-        eventManager->TransitionTo(EventManager::State::ClientDropped);
-    }
+    mEventManager->ShutDown();
 }
 
 bool Client::IsDisconnected() const {
diff --git a/src/dawn/wire/client/Client.h b/src/dawn/wire/client/Client.h
index 833cdba..2e112f9 100644
--- a/src/dawn/wire/client/Client.h
+++ b/src/dawn/wire/client/Client.h
@@ -29,7 +29,6 @@
 #define SRC_DAWN_WIRE_CLIENT_CLIENT_H_
 
 #include <memory>
-#include <unordered_map>
 #include <utility>
 
 #include "dawn/common/LinkedList.h"
@@ -89,7 +88,7 @@
     ReservedTexture ReserveTexture(WGPUDevice device, const WGPUTextureDescriptor* descriptor);
     ReservedSwapChain ReserveSwapChain(WGPUDevice device,
                                        const WGPUSwapChainDescriptor* descriptor);
-    ReservedDevice ReserveDevice(WGPUInstance instance);
+    ReservedDevice ReserveDevice();
     ReservedInstance ReserveInstance(const WGPUInstanceDescriptor* descriptor);
 
     void ReclaimTextureReservation(const ReservedTexture& reservation);
@@ -107,7 +106,7 @@
         mSerializer.SerializeCommand(cmd, *this, std::forward<Extensions>(es)...);
     }
 
-    EventManager& GetEventManager(const ObjectHandle& instance);
+    EventManager* GetEventManager();
 
     void Disconnect();
     bool IsDisconnected() const;
@@ -123,14 +122,8 @@
     MemoryTransferService* mMemoryTransferService = nullptr;
     std::unique_ptr<MemoryTransferService> mOwnedMemoryTransferService = nullptr;
     PerObjectType<LinkedList<ObjectBase>> mObjects;
-    // Map of instance object handles to a corresponding event manager. Note that for now because we
-    // do not have an internal refcount on the instances, i.e. we don't know when the last object
-    // associated with a particular instance is destroyed, this map is not cleaned up until the
-    // client is destroyed. This should only be a problem for users that are creating many
-    // instances. We also cannot currently store the EventManger on the Instance because
-    // spontaneous mode callbacks outlive the instance. We also can't reuse the ObjectStore for the
-    // EventManagers because we need to track old instance handles even after they are reclaimed.
-    std::unordered_map<ObjectHandle, std::unique_ptr<EventManager>> mEventManagers;
+    // TODO(crbug.com/dawn/2061) Eventually we want an EventManager per instance not per client.
+    std::unique_ptr<EventManager> mEventManager = nullptr;
     bool mDisconnected = false;
 };
 
diff --git a/src/dawn/wire/client/ClientDoers.cpp b/src/dawn/wire/client/ClientDoers.cpp
index 210cc53..57602d9 100644
--- a/src/dawn/wire/client/ClientDoers.cpp
+++ b/src/dawn/wire/client/ClientDoers.cpp
@@ -88,9 +88,7 @@
     return device->OnPopErrorScopeCallback(requestSerial, errorType, message);
 }
 
-// TODO(dawn:2061) May be able to move this to Buffer.cpp once we move all mapping logic.
 bool Client::DoBufferMapAsyncCallback(Buffer* buffer,
-                                      ObjectHandle eventManager,
                                       WGPUFuture future,
                                       uint32_t status,
                                       uint64_t readDataUpdateInfoLength,
@@ -102,6 +100,16 @@
     return buffer->OnMapAsyncCallback(future, status, readDataUpdateInfoLength, readDataUpdateInfo);
 }
 
+bool Client::DoQueueWorkDoneCallback(Queue* queue,
+                                     WGPUFuture future,
+                                     WGPUQueueWorkDoneStatus status) {
+    // The queue might have been deleted or recreated so this isn't an error.
+    if (queue == nullptr) {
+        return true;
+    }
+    return queue->OnWorkDoneCallback(future, status);
+}
+
 bool Client::DoDeviceCreateComputePipelineAsyncCallback(Device* device,
                                                         uint64_t requestSerial,
                                                         WGPUCreatePipelineAsyncStatus status,
diff --git a/src/dawn/wire/client/Device.cpp b/src/dawn/wire/client/Device.cpp
index c87800c..5000fd3 100644
--- a/src/dawn/wire/client/Device.cpp
+++ b/src/dawn/wire/client/Device.cpp
@@ -36,10 +36,8 @@
 
 namespace dawn::wire::client {
 
-Device::Device(const ObjectBaseParams& params,
-               const ObjectHandle& eventManagerHandle,
-               const WGPUDeviceDescriptor* descriptor)
-    : ObjectWithEventsBase(params, eventManagerHandle), mIsAlive(std::make_shared<bool>()) {
+Device::Device(const ObjectBaseParams& params, const WGPUDeviceDescriptor* descriptor)
+    : ObjectBase(params), mIsAlive(std::make_shared<bool>()) {
     if (descriptor && descriptor->deviceLostCallback) {
         mDeviceLostCallback = descriptor->deviceLostCallback;
         mDeviceLostUserdata = descriptor->deviceLostUserdata;
@@ -234,7 +232,7 @@
     if (mQueue == nullptr) {
         // Get the primary queue for this device.
         Client* client = GetClient();
-        mQueue = client->Make<Queue>(GetEventManagerHandle());
+        mQueue = client->Make<Queue>();
 
         DeviceGetQueueCmd cmd;
         cmd.self = ToAPI(this);
diff --git a/src/dawn/wire/client/Device.h b/src/dawn/wire/client/Device.h
index 12aca84..0ecbb02 100644
--- a/src/dawn/wire/client/Device.h
+++ b/src/dawn/wire/client/Device.h
@@ -43,11 +43,9 @@
 class Client;
 class Queue;
 
-class Device final : public ObjectWithEventsBase {
+class Device final : public ObjectBase {
   public:
-    explicit Device(const ObjectBaseParams& params,
-                    const ObjectHandle& eventManagerHandle,
-                    const WGPUDeviceDescriptor* descriptor);
+    explicit Device(const ObjectBaseParams& params, const WGPUDeviceDescriptor* descriptor);
     ~Device() override;
 
     void SetUncapturedErrorCallback(WGPUErrorCallback errorCallback, void* errorUserdata);
diff --git a/src/dawn/wire/client/EventManager.cpp b/src/dawn/wire/client/EventManager.cpp
index 130a64e..1614515 100644
--- a/src/dawn/wire/client/EventManager.cpp
+++ b/src/dawn/wire/client/EventManager.cpp
@@ -65,27 +65,14 @@
 
 // EventManager
 
-EventManager::~EventManager() {
-    TransitionTo(State::ClientDropped);
-}
+EventManager::EventManager(Client* client) : mClient(client) {}
 
 std::pair<FutureID, bool> EventManager::TrackEvent(std::unique_ptr<TrackedEvent> event) {
     FutureID futureID = mNextFutureID++;
 
-    switch (mState) {
-        case State::InstanceDropped: {
-            if (event->GetCallbackMode() != WGPUCallbackMode_AllowSpontaneous) {
-                event->Complete(futureID, EventCompletionType::Shutdown);
-                return {futureID, false};
-            }
-            break;
-        }
-        case State::ClientDropped: {
-            event->Complete(futureID, EventCompletionType::Shutdown);
-            return {futureID, false};
-        }
-        case State::Nominal:
-            break;
+    if (mClient->IsDisconnected()) {
+        event->Complete(futureID, EventCompletionType::Shutdown);
+        return {futureID, false};
     }
 
     mTrackedEvents.Use([&](auto trackedEvents) {
@@ -96,46 +83,22 @@
     return {futureID, true};
 }
 
-void EventManager::TransitionTo(EventManager::State state) {
-    // If the client is disconnected, this becomes a no-op.
-    if (mState == State::ClientDropped) {
-        return;
-    }
-
-    // Only forward state transitions are allowed.
-    DAWN_ASSERT(state > mState);
-    mState = state;
-
+void EventManager::ShutDown() {
+    // Call any outstanding callbacks before destruction.
     while (true) {
         std::map<FutureID, std::unique_ptr<TrackedEvent>> events;
-        switch (state) {
-            case State::InstanceDropped: {
-                mTrackedEvents.Use([&](auto trackedEvents) {
-                    for (auto it = trackedEvents->begin(); it != trackedEvents->end();) {
-                        auto& event = it->second;
-                        if (event->GetCallbackMode() != WGPUCallbackMode_AllowSpontaneous) {
-                            events.emplace(it->first, std::move(event));
-                            it = trackedEvents->erase(it);
-                        }
-                    }
-                });
-                break;
-            }
-            case State::ClientDropped: {
-                mTrackedEvents.Use([&](auto trackedEvents) { events = std::move(*trackedEvents); });
-                break;
-            }
-            case State::Nominal:
-                // We always start in the nominal state so we should never be transitioning to it.
-                DAWN_UNREACHABLE();
-        }
+        mTrackedEvents.Use([&](auto trackedEvents) { events = std::move(*trackedEvents); });
+
         if (events.empty()) {
             break;
         }
+
+        // Ordering guaranteed because we are using a sorted map.
         for (auto& [futureID, event] : events) {
             event->Complete(futureID, EventCompletionType::Shutdown);
         }
     }
+    mIsShutdown = true;
 }
 
 void EventManager::ProcessPollEvents() {
diff --git a/src/dawn/wire/client/EventManager.h b/src/dawn/wire/client/EventManager.h
index 478c7ac..8c891ce 100644
--- a/src/dawn/wire/client/EventManager.h
+++ b/src/dawn/wire/client/EventManager.h
@@ -88,35 +88,36 @@
 // TODO(crbug.com/dawn/2060): This should probably be merged together with RequestTracker.
 class EventManager final : NonMovable {
   public:
-    ~EventManager();
-
-    // See mState for breakdown of these states.
-    enum class State { Nominal, InstanceDropped, ClientDropped };
+    explicit EventManager(Client*);
+    ~EventManager() = default;
 
     // Returns a pair of the FutureID and a bool that is true iff the event was successfuly tracked,
     // false otherwise. Events may not be tracked if the client is already disconnected.
     std::pair<FutureID, bool> TrackEvent(std::unique_ptr<TrackedEvent> event);
-
-    // Transitions the EventManager to the given state. Note that states can only go in one
-    // direction, i.e. once the EventManager transitions to InstanceDropped, it cannot transition
-    // back to Nominal, though it may transition to ClientDropped later on.
-    void TransitionTo(State state);
+    void ShutDown();
 
     template <typename Event, typename... ReadyArgs>
     WireResult SetFutureReady(FutureID futureID, ReadyArgs&&... readyArgs) {
         DAWN_ASSERT(futureID > 0);
-
-        // If the future id is greater than what we have assigned, it must be invalid.
-        if (futureID > mNextFutureID) {
-            return WireResult::FatalError;
+        // If already shutdown, then all the callbacks should already have fired so we don't need to
+        // fire the callback anymore. This may happen if cleanup/dtor functions try to call this
+        // unconditionally on objects.
+        if (mIsShutdown) {
+#if DAWN_ENABLE_ASSERTS
+            // Note we need to use an if clause here because otherwise the DAWN_ASSERT macro will
+            // generate code that results in the lambda being in an unevaluated context.
+            DAWN_ASSERT(mTrackedEvents.Use([&](auto trackedEvents) {
+                return trackedEvents->find(futureID) == trackedEvents->end();
+            }));
+#endif
+            return WireResult::Success;
         }
 
         std::unique_ptr<TrackedEvent> spontaneousEvent;
         WIRE_TRY(mTrackedEvents.Use([&](auto trackedEvents) {
             auto it = trackedEvents->find(futureID);
             if (it == trackedEvents->end()) {
-                // If the future is not found, it must've already been completed.
-                return WireResult::Success;
+                return WireResult::FatalError;
             }
             auto& trackedEvent = it->second;
 
@@ -149,17 +150,8 @@
     WGPUWaitStatus WaitAny(size_t count, WGPUFutureWaitInfo* infos, uint64_t timeoutNS);
 
   private:
-    // Different states of the EventManager dictate how new incoming events are handled.
-    //   Nominal: Usual state of the manager. All events are tracked and callbacks are fired
-    //     depending on the callback modes.
-    //   InstanceDropped: Transitioned to this state if the last external reference of the Instance
-    //     is dropped. In this mode, any non-spontaneous events are no longer tracked and their
-    //     callbacks are immediately called since the user cannot call WaitAny or ProcessEvents
-    //     anymore. Any existing non-spontaneous events' callbacks are also called on transition.
-    //   ClientDropped: Transitioned to this state once the client is dropped. In this mode, no new
-    //     events are tracked and callbacks are all immediately fired. Any existing tracked events'
-    //     callbacks are also called on transition.
-    State mState = State::Nominal;
+    Client* mClient;
+    bool mIsShutdown = false;
 
     // Tracks all kinds of events (for both WaitAny and ProcessEvents). We use an ordered map so
     // that in most cases, event ordering is already implicit when we iterate the map. (Not true for
diff --git a/src/dawn/wire/client/Instance.cpp b/src/dawn/wire/client/Instance.cpp
index 280ea4b..6c0597f0 100644
--- a/src/dawn/wire/client/Instance.cpp
+++ b/src/dawn/wire/client/Instance.cpp
@@ -134,12 +134,6 @@
 
 // Instance
 
-Instance::Instance(const ObjectBaseParams& params) : ObjectWithEventsBase(params, params.handle) {}
-
-Instance::~Instance() {
-    GetEventManager().TransitionTo(EventManager::State::InstanceDropped);
-}
-
 WireResult Instance::Initialize(const WGPUInstanceDescriptor* descriptor) {
     if (descriptor == nullptr) {
         return WireResult::Success;
@@ -191,16 +185,15 @@
 WGPUFuture Instance::RequestAdapterF(const WGPURequestAdapterOptions* options,
                                      const WGPURequestAdapterCallbackInfo& callbackInfo) {
     Client* client = GetClient();
-    Adapter* adapter = client->Make<Adapter>(GetEventManagerHandle());
-    auto [futureIDInternal, tracked] =
-        GetEventManager().TrackEvent(std::make_unique<RequestAdapterEvent>(callbackInfo, adapter));
+    Adapter* adapter = client->Make<Adapter>();
+    auto [futureIDInternal, tracked] = client->GetEventManager()->TrackEvent(
+        std::make_unique<RequestAdapterEvent>(callbackInfo, adapter));
     if (!tracked) {
         return {futureIDInternal};
     }
 
     InstanceRequestAdapterCmd cmd;
     cmd.instanceId = GetWireId();
-    cmd.eventManagerHandle = GetEventManagerHandle();
     cmd.future = {futureIDInternal};
     cmd.adapterObjectHandle = adapter->GetWireHandle();
     cmd.options = options;
@@ -209,7 +202,7 @@
     return {futureIDInternal};
 }
 
-bool Client::DoInstanceRequestAdapterCallback(ObjectHandle eventManager,
+bool Client::DoInstanceRequestAdapterCallback(Instance* instance,
                                               WGPUFuture future,
                                               WGPURequestAdapterStatus status,
                                               const char* message,
@@ -217,13 +210,30 @@
                                               const WGPUSupportedLimits* limits,
                                               uint32_t featuresCount,
                                               const WGPUFeatureName* features) {
-    return GetEventManager(eventManager)
-               .SetFutureReady<RequestAdapterEvent>(future.id, status, message, properties, limits,
-                                                    featuresCount, features) == WireResult::Success;
+    // May have been deleted or recreated so this isn't an error.
+    if (instance == nullptr) {
+        return true;
+    }
+    return instance->OnRequestAdapterCallback(future, status, message, properties, limits,
+                                              featuresCount, features);
+}
+
+bool Instance::OnRequestAdapterCallback(WGPUFuture future,
+                                        WGPURequestAdapterStatus status,
+                                        const char* message,
+                                        const WGPUAdapterProperties* properties,
+                                        const WGPUSupportedLimits* limits,
+                                        uint32_t featuresCount,
+                                        const WGPUFeatureName* features) {
+    return GetClient()->GetEventManager()->SetFutureReady<RequestAdapterEvent>(
+               future.id, status, message, properties, limits, featuresCount, features) ==
+           WireResult::Success;
 }
 
 void Instance::ProcessEvents() {
-    GetEventManager().ProcessPollEvents();
+    // TODO(crbug.com/dawn/2061): This should only process events for this Instance, not others
+    // on the same client. When EventManager is moved to Instance, this can be fixed.
+    GetClient()->GetEventManager()->ProcessPollEvents();
 
     // TODO(crbug.com/dawn/1987): The responsibility of ProcessEvents here is a bit mixed. It both
     // processes events coming in from the server, and also prompts the server to check for and
@@ -245,7 +255,10 @@
 }
 
 WGPUWaitStatus Instance::WaitAny(size_t count, WGPUFutureWaitInfo* infos, uint64_t timeoutNS) {
-    return GetEventManager().WaitAny(count, infos, timeoutNS);
+    // In principle the EventManager should be on the Instance, not the Client.
+    // But it's hard to get from an object to its Instance right now, so we can
+    // store it on the Client.
+    return GetClient()->GetEventManager()->WaitAny(count, infos, timeoutNS);
 }
 
 void Instance::GatherWGSLFeatures(const WGPUDawnWireWGSLControl* wgslControl,
diff --git a/src/dawn/wire/client/Instance.h b/src/dawn/wire/client/Instance.h
index 43301ef..3fce377 100644
--- a/src/dawn/wire/client/Instance.h
+++ b/src/dawn/wire/client/Instance.h
@@ -41,10 +41,9 @@
 WGPUBool ClientGetInstanceFeatures(WGPUInstanceFeatures* features);
 WGPUInstance ClientCreateInstance(WGPUInstanceDescriptor const* descriptor);
 
-class Instance final : public ObjectWithEventsBase {
+class Instance final : public ObjectBase {
   public:
-    explicit Instance(const ObjectBaseParams& params);
-    ~Instance() override;
+    using ObjectBase::ObjectBase;
 
     WireResult Initialize(const WGPUInstanceDescriptor* descriptor);
 
@@ -53,6 +52,13 @@
                         void* userdata);
     WGPUFuture RequestAdapterF(const WGPURequestAdapterOptions* options,
                                const WGPURequestAdapterCallbackInfo& callbackInfo);
+    bool OnRequestAdapterCallback(WGPUFuture future,
+                                  WGPURequestAdapterStatus status,
+                                  const char* message,
+                                  const WGPUAdapterProperties* properties,
+                                  const WGPUSupportedLimits* limits,
+                                  uint32_t featuresCount,
+                                  const WGPUFeatureName* features);
 
     void ProcessEvents();
     WGPUWaitStatus WaitAny(size_t count, WGPUFutureWaitInfo* infos, uint64_t timeoutNS);
diff --git a/src/dawn/wire/client/ObjectBase.cpp b/src/dawn/wire/client/ObjectBase.cpp
index d66f521..84b6af7 100644
--- a/src/dawn/wire/client/ObjectBase.cpp
+++ b/src/dawn/wire/client/ObjectBase.cpp
@@ -28,7 +28,6 @@
 #include "dawn/wire/client/ObjectBase.h"
 
 #include "dawn/common/Assert.h"
-#include "dawn/wire/client/Client.h"
 
 namespace dawn::wire::client {
 
@@ -65,16 +64,4 @@
     return mRefcount == 0;
 }
 
-ObjectWithEventsBase::ObjectWithEventsBase(const ObjectBaseParams& params,
-                                           const ObjectHandle& eventManagerHandle)
-    : ObjectBase(params), mEventManagerHandle(eventManagerHandle) {}
-
-const ObjectHandle& ObjectWithEventsBase::GetEventManagerHandle() const {
-    return mEventManagerHandle;
-}
-
-EventManager& ObjectWithEventsBase::GetEventManager() const {
-    return GetClient()->GetEventManager(mEventManagerHandle);
-}
-
 }  // namespace dawn::wire::client
diff --git a/src/dawn/wire/client/ObjectBase.h b/src/dawn/wire/client/ObjectBase.h
index 8c90683..5e1688c 100644
--- a/src/dawn/wire/client/ObjectBase.h
+++ b/src/dawn/wire/client/ObjectBase.h
@@ -32,7 +32,6 @@
 
 #include "dawn/common/LinkedList.h"
 #include "dawn/wire/ObjectHandle.h"
-#include "dawn/wire/client/EventManager.h"
 
 namespace dawn::wire::client {
 
@@ -74,23 +73,6 @@
     uint32_t mRefcount;
 };
 
-// Compositable functionality for objects on the client side that need to have access to the event
-// manager.
-class ObjectWithEventsBase : public ObjectBase {
-  public:
-    // Note that the ObjectHandle associated with an EventManager is the same handle associated to
-    // the Instance that "owns" the EventManager.
-    ObjectWithEventsBase(const ObjectBaseParams& params, const ObjectHandle& eventManager);
-
-    const ObjectHandle& GetEventManagerHandle() const;
-    EventManager& GetEventManager() const;
-
-  private:
-    // The EventManager is owned by the client and long-lived. When the client is destroyed all
-    // objects are also freed.
-    ObjectHandle mEventManagerHandle;
-};
-
 }  // namespace dawn::wire::client
 
 #endif  // SRC_DAWN_WIRE_CLIENT_OBJECTBASE_H_
diff --git a/src/dawn/wire/client/Queue.cpp b/src/dawn/wire/client/Queue.cpp
index eee8a00..89c0bb5 100644
--- a/src/dawn/wire/client/Queue.cpp
+++ b/src/dawn/wire/client/Queue.cpp
@@ -69,10 +69,8 @@
 
 Queue::~Queue() = default;
 
-bool Client::DoQueueWorkDoneCallback(ObjectHandle eventManager,
-                                     WGPUFuture future,
-                                     WGPUQueueWorkDoneStatus status) {
-    return GetEventManager(eventManager).SetFutureReady<WorkDoneEvent>(future.id, status) ==
+bool Queue::OnWorkDoneCallback(WGPUFuture future, WGPUQueueWorkDoneStatus status) {
+    return GetClient()->GetEventManager()->SetFutureReady<WorkDoneEvent>(future.id, status) ==
            WireResult::Success;
 }
 
@@ -91,14 +89,13 @@
 
     Client* client = GetClient();
     auto [futureIDInternal, tracked] =
-        GetEventManager().TrackEvent(std::make_unique<WorkDoneEvent>(callbackInfo));
+        client->GetEventManager()->TrackEvent(std::make_unique<WorkDoneEvent>(callbackInfo));
     if (!tracked) {
         return {futureIDInternal};
     }
 
     QueueOnSubmittedWorkDoneCmd cmd;
     cmd.queueId = GetWireId();
-    cmd.eventManagerHandle = GetEventManagerHandle();
     cmd.future = {futureIDInternal};
 
     client->SerializeCommand(cmd);
diff --git a/src/dawn/wire/client/Queue.h b/src/dawn/wire/client/Queue.h
index 0d4cc55..0b47342 100644
--- a/src/dawn/wire/client/Queue.h
+++ b/src/dawn/wire/client/Queue.h
@@ -36,11 +36,13 @@
 
 namespace dawn::wire::client {
 
-class Queue final : public ObjectWithEventsBase {
+class Queue final : public ObjectBase {
   public:
-    using ObjectWithEventsBase::ObjectWithEventsBase;
+    using ObjectBase::ObjectBase;
     ~Queue() override;
 
+    bool OnWorkDoneCallback(WGPUFuture future, WGPUQueueWorkDoneStatus status);
+
     // Dawn API
     void OnSubmittedWorkDone(WGPUQueueWorkDoneCallback callback, void* userdata);
     WGPUFuture OnSubmittedWorkDoneF(const WGPUQueueWorkDoneCallbackInfo& callbackInfo);
diff --git a/src/dawn/wire/server/Server.h b/src/dawn/wire/server/Server.h
index 5f21a51..e20a300 100644
--- a/src/dawn/wire/server/Server.h
+++ b/src/dawn/wire/server/Server.h
@@ -105,7 +105,6 @@
 
     ObjectHandle buffer;
     WGPUBuffer bufferObj;
-    ObjectHandle eventManager;
     WGPUFuture future;
     uint64_t offset;
     uint64_t size;
@@ -130,7 +129,6 @@
     using CallbackUserdata::CallbackUserdata;
 
     ObjectHandle queue;
-    ObjectHandle eventManager;
     WGPUFuture future;
 };
 
@@ -146,7 +144,6 @@
     using CallbackUserdata::CallbackUserdata;
 
     ObjectHandle instance;
-    ObjectHandle eventManager;
     WGPUFuture future;
     ObjectId adapterObjectId;
 };
diff --git a/src/dawn/wire/server/ServerBuffer.cpp b/src/dawn/wire/server/ServerBuffer.cpp
index ca1471c..5869a5d 100644
--- a/src/dawn/wire/server/ServerBuffer.cpp
+++ b/src/dawn/wire/server/ServerBuffer.cpp
@@ -65,7 +65,6 @@
 }
 
 WireResult Server::DoBufferMapAsync(Known<WGPUBuffer> buffer,
-                                    ObjectHandle eventManager,
                                     WGPUFuture future,
                                     WGPUMapModeFlags mode,
                                     uint64_t offset64,
@@ -74,7 +73,6 @@
     // client will require in the return command.
     std::unique_ptr<MapUserdata> userdata = MakeUserdata<MapUserdata>();
     userdata->buffer = buffer.AsHandle();
-    userdata->eventManager = eventManager;
     userdata->bufferObj = buffer->handle;
     userdata->future = future;
     userdata->mode = mode;
@@ -225,9 +223,7 @@
     bool isSuccess = status == WGPUBufferMapAsyncStatus_Success;
 
     ReturnBufferMapAsyncCallbackCmd cmd;
-    // TODO(dawn:2061) Should be able to remove buffer once mapping is updated.
     cmd.buffer = data->buffer;
-    cmd.eventManager = data->eventManager;
     cmd.future = data->future;
     cmd.status = status;
     cmd.readDataUpdateInfoLength = 0;
diff --git a/src/dawn/wire/server/ServerInstance.cpp b/src/dawn/wire/server/ServerInstance.cpp
index 660c339..3f3f8c4 100644
--- a/src/dawn/wire/server/ServerInstance.cpp
+++ b/src/dawn/wire/server/ServerInstance.cpp
@@ -34,7 +34,6 @@
 namespace dawn::wire::server {
 
 WireResult Server::DoInstanceRequestAdapter(Known<WGPUInstance> instance,
-                                            ObjectHandle eventManager,
                                             WGPUFuture future,
                                             ObjectHandle adapterHandle,
                                             const WGPURequestAdapterOptions* options) {
@@ -43,7 +42,6 @@
 
     auto userdata = MakeUserdata<RequestAdapterUserdata>();
     userdata->instance = instance.AsHandle();
-    userdata->eventManager = eventManager;
     userdata->future = future;
     userdata->adapterObjectId = adapter.id;
 
@@ -58,7 +56,7 @@
                                       WGPUAdapter adapter,
                                       const char* message) {
     ReturnInstanceRequestAdapterCallbackCmd cmd = {};
-    cmd.eventManager = data->eventManager;
+    cmd.instance = data->instance;
     cmd.future = data->future;
     cmd.status = status;
     cmd.message = message;
diff --git a/src/dawn/wire/server/ServerQueue.cpp b/src/dawn/wire/server/ServerQueue.cpp
index 807861b..a4d9c0a 100644
--- a/src/dawn/wire/server/ServerQueue.cpp
+++ b/src/dawn/wire/server/ServerQueue.cpp
@@ -34,19 +34,16 @@
 
 void Server::OnQueueWorkDone(QueueWorkDoneUserdata* data, WGPUQueueWorkDoneStatus status) {
     ReturnQueueWorkDoneCallbackCmd cmd;
-    cmd.eventManager = data->eventManager;
+    cmd.queue = data->queue;
     cmd.future = data->future;
     cmd.status = status;
 
     SerializeCommand(cmd);
 }
 
-WireResult Server::DoQueueOnSubmittedWorkDone(Known<WGPUQueue> queue,
-                                              ObjectHandle eventManager,
-                                              WGPUFuture future) {
+WireResult Server::DoQueueOnSubmittedWorkDone(Known<WGPUQueue> queue, WGPUFuture future) {
     auto userdata = MakeUserdata<QueueWorkDoneUserdata>();
     userdata->queue = queue.AsHandle();
-    userdata->eventManager = eventManager;
     userdata->future = future;
 
     mProcs.queueOnSubmittedWorkDone(queue->handle, ForwardToServer<&Server::OnQueueWorkDone>,