[dawn][emscripten] Fixes some device lost bugs.

- Use a shim for wgpuDeviceDestroy to cause the device lost event
  to immediately happen.
- Fix Ref<> implementation to always call RefCounted functions,
  i.e, not ExternalRefCounted functions.

Change-Id: I4ba3540f4b1c8753d3b88a793c5c719ded56c52a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/211238
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Auto-Submit: Loko Kung <lokokung@google.com>
diff --git a/third_party/emdawnwebgpu/library_webgpu.js b/third_party/emdawnwebgpu/library_webgpu.js
index b4c3db2..1c53c27 100644
--- a/third_party/emdawnwebgpu/library_webgpu.js
+++ b/third_party/emdawnwebgpu/library_webgpu.js
@@ -1706,7 +1706,7 @@
     return ptr;
   },
 
-  wgpuDeviceDestroy: (devicePtr) => {
+  emwgpuDeviceDestroy: (devicePtr) => {
     WebGPU.getJsObject(devicePtr).destroy()
   },
 
diff --git a/third_party/emdawnwebgpu/webgpu.cpp b/third_party/emdawnwebgpu/webgpu.cpp
index e473877..ddbdac4 100644
--- a/third_party/emdawnwebgpu/webgpu.cpp
+++ b/third_party/emdawnwebgpu/webgpu.cpp
@@ -42,7 +42,8 @@
                        uint64_t const* timeoutNSPtr);
 WGPUTextureFormat emwgpuGetPreferredFormat();
 
-// Creation functions to create JS backing objects given a pre-allocated handle.
+// Device functions, i.e. creation functions to create JS backing objects given
+// a pre-allocated handle, and destruction implementations.
 void emwgpuDeviceCreateBuffer(WGPUDevice device,
                               const WGPUBufferDescriptor* descriptor,
                               WGPUBuffer buffer);
@@ -50,6 +51,7 @@
     WGPUDevice device,
     const WGPUShaderModuleDescriptor* descriptor,
     WGPUShaderModule shader);
+void emwgpuDeviceDestroy(WGPUDevice device);
 
 // Buffer mapping operations that has work that needs to be done on the JS side.
 void emwgpuBufferDestroy(WGPUBuffer buffer);
@@ -226,11 +228,11 @@
  private:
   static void AddRef(T value) {
     if (value != nullptr) {
-      value->AddRef();
+      value->RefCounted::AddRef();
     }
   }
   static void Release(T value) {
-    if (value != nullptr && value->Release()) {
+    if (value != nullptr && value->RefCounted::Release()) {
       delete value;
     }
   }
@@ -672,6 +674,7 @@
   // Injection constructor used when we already have a backing Device.
   WGPUDeviceImpl(const EventSource* source, WGPUQueue queue);
 
+  void Destroy();
   WGPUQueue GetQueue() const;
 
   void OnDeviceLost(WGPUDeviceLostReason reason, const char* message);
@@ -1363,6 +1366,12 @@
   mQueue.Acquire(queue);
 }
 
+void WGPUDeviceImpl::Destroy() {
+  emwgpuDeviceDestroy(this);
+  // TODO(374803367): Remove this when we can get the device lost future.
+  OnDeviceLost(WGPUDeviceLostReason_Destroyed, "Device was destroyed.");
+}
+
 WGPUQueue WGPUDeviceImpl::GetQueue() const {
   auto queue = mQueue;
   return ReturnToAPI(std::move(queue));
@@ -1390,7 +1399,7 @@
 }
 
 void WGPUDeviceImpl::WillDropLastExternalRef() {
-  OnDeviceLost(WGPUDeviceLostReason_Destroyed, "Device was destroyed.");
+  Destroy();
 }
 
 // ----------------------------------------------------------------------------
@@ -1705,6 +1714,10 @@
   return shader;
 }
 
+void wgpuDeviceDestroy(WGPUDevice device) {
+  device->Destroy();
+}
+
 WGPUQueue wgpuDeviceGetQueue(WGPUDevice device) {
   return device->GetQueue();
 }