Add ReturnToAPI() method for returning object to API

Bug: dawn:2184
Change-Id: If48532f1ef03b39c9ccfeaefb502fed7ffd733d4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/169941
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Peng Huang <penghuang@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index be930d2..32f4f49 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -186,7 +186,7 @@
         mPhysicalDevice->GetInstance()->ConsumedError(result.AcquireError());
         return nullptr;
     }
-    return result.AcquireSuccess().Detach();
+    return ReturnToAPI(result.AcquireSuccess());
 }
 
 ResultOrError<Ref<DeviceBase>> AdapterBase::CreateDevice(const DeviceDescriptor* rawDescriptor) {
@@ -259,7 +259,7 @@
     WGPURequestDeviceStatus status =
         device == nullptr ? WGPURequestDeviceStatus_Unknown : WGPURequestDeviceStatus_Success;
     // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
-    callback(status, ToAPI(device.Detach()), nullptr, userdata);
+    callback(status, ToAPI(ReturnToAPI(std::move(device))), nullptr, userdata);
 }
 
 const TogglesState& AdapterBase::GetTogglesState() const {
diff --git a/src/dawn/native/BindGroup.cpp b/src/dawn/native/BindGroup.cpp
index b61089d..510019c 100644
--- a/src/dawn/native/BindGroup.cpp
+++ b/src/dawn/native/BindGroup.cpp
@@ -508,8 +508,8 @@
     : ApiObjectBase(device, tag, label), mBindingData() {}
 
 // static
-BindGroupBase* BindGroupBase::MakeError(DeviceBase* device, const char* label) {
-    return new BindGroupBase(device, ObjectBase::kError, label);
+Ref<BindGroupBase> BindGroupBase::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new BindGroupBase(device, ObjectBase::kError, label));
 }
 
 ObjectType BindGroupBase::GetType() const {
diff --git a/src/dawn/native/BindGroup.h b/src/dawn/native/BindGroup.h
index ad27182..c7b964a 100644
--- a/src/dawn/native/BindGroup.h
+++ b/src/dawn/native/BindGroup.h
@@ -57,7 +57,7 @@
 
 class BindGroupBase : public ApiObjectBase {
   public:
-    static BindGroupBase* MakeError(DeviceBase* device, const char* label);
+    static Ref<BindGroupBase> MakeError(DeviceBase* device, const char* label);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/BindGroupLayout.cpp b/src/dawn/native/BindGroupLayout.cpp
index 52d1fdc..2ba521b 100644
--- a/src/dawn/native/BindGroupLayout.cpp
+++ b/src/dawn/native/BindGroupLayout.cpp
@@ -51,8 +51,8 @@
 }
 
 // static
-BindGroupLayoutBase* BindGroupLayoutBase::MakeError(DeviceBase* device, const char* label) {
-    return new BindGroupLayoutBase(device, ObjectBase::kError, label);
+Ref<BindGroupLayoutBase> BindGroupLayoutBase::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new BindGroupLayoutBase(device, ObjectBase::kError, label));
 }
 
 BindGroupLayoutInternalBase* BindGroupLayoutBase::GetInternalBindGroupLayout() const {
diff --git a/src/dawn/native/BindGroupLayout.h b/src/dawn/native/BindGroupLayout.h
index 1e71bf8..73c663b 100644
--- a/src/dawn/native/BindGroupLayout.h
+++ b/src/dawn/native/BindGroupLayout.h
@@ -45,7 +45,7 @@
                         Ref<BindGroupLayoutInternalBase> internal,
                         PipelineCompatibilityToken pipelineCompatibilityToken);
 
-    static BindGroupLayoutBase* MakeError(DeviceBase* device, const char* label = nullptr);
+    static Ref<BindGroupLayoutBase> MakeError(DeviceBase* device, const char* label = nullptr);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/Buffer.cpp b/src/dawn/native/Buffer.cpp
index d5cb53d..805380d 100644
--- a/src/dawn/native/Buffer.cpp
+++ b/src/dawn/native/Buffer.cpp
@@ -368,8 +368,8 @@
 }
 
 // static
-BufferBase* BufferBase::MakeError(DeviceBase* device, const BufferDescriptor* descriptor) {
-    return new ErrorBuffer(device, descriptor);
+Ref<BufferBase> BufferBase::MakeError(DeviceBase* device, const BufferDescriptor* descriptor) {
+    return AcquireRef(new ErrorBuffer(device, descriptor));
 }
 
 ObjectType BufferBase::GetType() const {
diff --git a/src/dawn/native/Buffer.h b/src/dawn/native/Buffer.h
index 6f28716..17ea29f 100644
--- a/src/dawn/native/Buffer.h
+++ b/src/dawn/native/Buffer.h
@@ -76,7 +76,7 @@
         HostMappedPersistent,
         Destroyed,
     };
-    static BufferBase* MakeError(DeviceBase* device, const BufferDescriptor* descriptor);
+    static Ref<BufferBase> MakeError(DeviceBase* device, const BufferDescriptor* descriptor);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/CommandBuffer.cpp b/src/dawn/native/CommandBuffer.cpp
index e4f3c27..6d34a01 100644
--- a/src/dawn/native/CommandBuffer.cpp
+++ b/src/dawn/native/CommandBuffer.cpp
@@ -53,8 +53,8 @@
     : ApiObjectBase(device, tag, label) {}
 
 // static
-CommandBufferBase* CommandBufferBase::MakeError(DeviceBase* device, const char* label) {
-    return new CommandBufferBase(device, ObjectBase::kError, label);
+Ref<CommandBufferBase> CommandBufferBase::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new CommandBufferBase(device, ObjectBase::kError, label));
 }
 
 ObjectType CommandBufferBase::GetType() const {
diff --git a/src/dawn/native/CommandBuffer.h b/src/dawn/native/CommandBuffer.h
index 9fae1ed..2f182fc 100644
--- a/src/dawn/native/CommandBuffer.h
+++ b/src/dawn/native/CommandBuffer.h
@@ -49,7 +49,7 @@
   public:
     CommandBufferBase(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor);
 
-    static CommandBufferBase* MakeError(DeviceBase* device, const char* label);
+    static Ref<CommandBufferBase> MakeError(DeviceBase* device, const char* label);
 
     ObjectType GetType() const override;
     void FormatLabel(absl::FormatSink* s) const override;
diff --git a/src/dawn/native/CommandEncoder.cpp b/src/dawn/native/CommandEncoder.cpp
index f7dd037..835fc2d 100644
--- a/src/dawn/native/CommandEncoder.cpp
+++ b/src/dawn/native/CommandEncoder.cpp
@@ -932,8 +932,8 @@
 }
 
 // static
-CommandEncoder* CommandEncoder::MakeError(DeviceBase* device, const char* label) {
-    return new CommandEncoder(device, ObjectBase::kError, label);
+Ref<CommandEncoder> CommandEncoder::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new CommandEncoder(device, ObjectBase::kError, label));
 }
 
 CommandEncoder::CommandEncoder(DeviceBase* device,
@@ -997,7 +997,7 @@
     // This function will create new object, need to lock the Device.
     auto deviceLock(GetDevice()->GetScopedLock());
 
-    return BeginComputePass(descriptor).Detach();
+    return ReturnToAPI(BeginComputePass(descriptor));
 }
 
 Ref<ComputePassEncoder> CommandEncoder::BeginComputePass(const ComputePassDescriptor* descriptor) {
@@ -1057,7 +1057,7 @@
     // This function will create new object, need to lock the Device.
     auto deviceLock(GetDevice()->GetScopedLock());
 
-    return BeginRenderPass(descriptor).Detach();
+    return ReturnToAPI(BeginRenderPass(descriptor));
 }
 
 Ref<RenderPassEncoder> CommandEncoder::BeginRenderPass(const RenderPassDescriptor* rawDescriptor) {
@@ -2104,13 +2104,13 @@
 
     Ref<CommandBufferBase> commandBuffer;
     if (GetDevice()->ConsumedError(Finish(descriptor), &commandBuffer)) {
-        CommandBufferBase* errorCommandBuffer =
+        Ref<CommandBufferBase> errorCommandBuffer =
             CommandBufferBase::MakeError(GetDevice(), descriptor ? descriptor->label : nullptr);
         errorCommandBuffer->SetEncoderLabel(this->GetLabel());
-        return errorCommandBuffer;
+        return ReturnToAPI(std::move(errorCommandBuffer));
     }
     DAWN_ASSERT(!IsError());
-    return commandBuffer.Detach();
+    return ReturnToAPI(std::move(commandBuffer));
 }
 
 ResultOrError<Ref<CommandBufferBase>> CommandEncoder::Finish(
diff --git a/src/dawn/native/CommandEncoder.h b/src/dawn/native/CommandEncoder.h
index efc41b2..b25c984 100644
--- a/src/dawn/native/CommandEncoder.h
+++ b/src/dawn/native/CommandEncoder.h
@@ -52,7 +52,7 @@
   public:
     static Ref<CommandEncoder> Create(DeviceBase* device,
                                       const UnpackedPtr<CommandEncoderDescriptor>& descriptor);
-    static CommandEncoder* MakeError(DeviceBase* device, const char* label);
+    static Ref<CommandEncoder> MakeError(DeviceBase* device, const char* label);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/ComputePipeline.cpp b/src/dawn/native/ComputePipeline.cpp
index d03a7ab..a8b2f67 100644
--- a/src/dawn/native/ComputePipeline.cpp
+++ b/src/dawn/native/ComputePipeline.cpp
@@ -97,7 +97,7 @@
 }
 
 // static
-ComputePipelineBase* ComputePipelineBase::MakeError(DeviceBase* device, const char* label) {
+Ref<ComputePipelineBase> ComputePipelineBase::MakeError(DeviceBase* device, const char* label) {
     class ErrorComputePipeline final : public ComputePipelineBase {
       public:
         explicit ErrorComputePipeline(DeviceBase* device, const char* label)
@@ -109,7 +109,7 @@
         }
     };
 
-    return new ErrorComputePipeline(device, label);
+    return AcquireRef(new ErrorComputePipeline(device, label));
 }
 
 ObjectType ComputePipelineBase::GetType() const {
diff --git a/src/dawn/native/ComputePipeline.h b/src/dawn/native/ComputePipeline.h
index f055fdf..2d2e1bd 100644
--- a/src/dawn/native/ComputePipeline.h
+++ b/src/dawn/native/ComputePipeline.h
@@ -48,7 +48,7 @@
                         const UnpackedPtr<ComputePipelineDescriptor>& descriptor);
     ~ComputePipelineBase() override;
 
-    static ComputePipelineBase* MakeError(DeviceBase* device, const char* label);
+    static Ref<ComputePipelineBase> MakeError(DeviceBase* device, const char* label);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index 4889f74..3caceda3 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -1076,35 +1076,37 @@
     Ref<BindGroupBase> result;
     if (ConsumedError(CreateBindGroup(descriptor), &result, "calling %s.CreateBindGroup(%s).", this,
                       descriptor)) {
-        return BindGroupBase::MakeError(this, descriptor ? descriptor->label : nullptr);
+        return ReturnToAPI(
+            BindGroupBase::MakeError(this, descriptor ? descriptor->label : nullptr));
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 BindGroupLayoutBase* DeviceBase::APICreateBindGroupLayout(
     const BindGroupLayoutDescriptor* descriptor) {
     Ref<BindGroupLayoutBase> result;
     if (ConsumedError(CreateBindGroupLayout(descriptor), &result,
                       "calling %s.CreateBindGroupLayout(%s).", this, descriptor)) {
-        return BindGroupLayoutBase::MakeError(this, descriptor ? descriptor->label : nullptr);
+        return ReturnToAPI(
+            BindGroupLayoutBase::MakeError(this, descriptor ? descriptor->label : nullptr));
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 BufferBase* DeviceBase::APICreateBuffer(const BufferDescriptor* descriptor) {
-    Ref<BufferBase> result = nullptr;
+    Ref<BufferBase> result;
     if (ConsumedError(CreateBuffer(descriptor), &result, InternalErrorType::OutOfMemory,
                       "calling %s.CreateBuffer(%s).", this, descriptor)) {
         DAWN_ASSERT(result == nullptr);
-        return BufferBase::MakeError(this, descriptor);
+        result = BufferBase::MakeError(this, descriptor);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 CommandEncoder* DeviceBase::APICreateCommandEncoder(const CommandEncoderDescriptor* descriptor) {
     Ref<CommandEncoder> result;
     if (ConsumedError(CreateCommandEncoder(descriptor), &result,
                       "calling %s.CreateCommandEncoder(%s).", this, descriptor)) {
-        return CommandEncoder::MakeError(this, descriptor ? descriptor->label : nullptr);
+        result = CommandEncoder::MakeError(this, descriptor ? descriptor->label : nullptr);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 ComputePipelineBase* DeviceBase::APICreateComputePipeline(
     const ComputePipelineDescriptor* descriptor) {
@@ -1114,9 +1116,9 @@
     Ref<ComputePipelineBase> result;
     if (ConsumedError(CreateComputePipeline(descriptor), &result, InternalErrorType::Internal,
                       "calling %s.CreateComputePipeline(%s).", this, descriptor)) {
-        return ComputePipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
+        result = ComputePipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 void DeviceBase::APICreateComputePipelineAsync(const ComputePipelineDescriptor* descriptor,
                                                WGPUCreateComputePipelineAsyncCallback callback,
@@ -1141,7 +1143,7 @@
     if (cachedComputePipeline.Get() != nullptr) {
         mCallbackTaskManager->AddCallbackTask(
             std::bind(callback, WGPUCreatePipelineAsyncStatus_Success,
-                      ToAPI(cachedComputePipeline.Detach()), "", userdata));
+                      ToAPI(ReturnToAPI(std::move(cachedComputePipeline))), "", userdata));
     } else {
         // Otherwise we will create the pipeline object in InitializeComputePipelineAsyncImpl(),
         // where the pipeline object may be initialized asynchronously and the result will be
@@ -1155,25 +1157,25 @@
     Ref<PipelineLayoutBase> result;
     if (ConsumedError(CreatePipelineLayout(descriptor), &result,
                       "calling %s.CreatePipelineLayout(%s).", this, descriptor)) {
-        return PipelineLayoutBase::MakeError(this, descriptor ? descriptor->label : nullptr);
+        result = PipelineLayoutBase::MakeError(this, descriptor ? descriptor->label : nullptr);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 QuerySetBase* DeviceBase::APICreateQuerySet(const QuerySetDescriptor* descriptor) {
     Ref<QuerySetBase> result;
     if (ConsumedError(CreateQuerySet(descriptor), &result, InternalErrorType::OutOfMemory,
                       "calling %s.CreateQuerySet(%s).", this, descriptor)) {
-        return QuerySetBase::MakeError(this, descriptor);
+        result = QuerySetBase::MakeError(this, descriptor);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 SamplerBase* DeviceBase::APICreateSampler(const SamplerDescriptor* descriptor) {
     Ref<SamplerBase> result;
     if (ConsumedError(CreateSampler(descriptor), &result, "calling %s.CreateSampler(%s).", this,
                       descriptor)) {
-        return SamplerBase::MakeError(this, descriptor ? descriptor->label : nullptr);
+        result = SamplerBase::MakeError(this, descriptor ? descriptor->label : nullptr);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 void DeviceBase::APICreateRenderPipelineAsync(const RenderPipelineDescriptor* descriptor,
                                               WGPUCreateRenderPipelineAsyncCallback callback,
@@ -1199,7 +1201,7 @@
     if (cachedRenderPipeline != nullptr) {
         mCallbackTaskManager->AddCallbackTask(
             std::bind(callback, WGPUCreatePipelineAsyncStatus_Success,
-                      ToAPI(cachedRenderPipeline.Detach()), "", userdata));
+                      ToAPI(ReturnToAPI(std::move(cachedRenderPipeline))), "", userdata));
     } else {
         // Otherwise we will create the pipeline object in InitializeRenderPipelineAsyncImpl(),
         // where the pipeline object may be initialized asynchronously and the result will be
@@ -1214,9 +1216,9 @@
     Ref<RenderBundleEncoder> result;
     if (ConsumedError(CreateRenderBundleEncoder(descriptor), &result,
                       "calling %s.CreateRenderBundleEncoder(%s).", this, descriptor)) {
-        return RenderBundleEncoder::MakeError(this, descriptor ? descriptor->label : nullptr);
+        result = RenderBundleEncoder::MakeError(this, descriptor ? descriptor->label : nullptr);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 RenderPipelineBase* DeviceBase::APICreateRenderPipeline(
     const RenderPipelineDescriptor* descriptor) {
@@ -1226,9 +1228,9 @@
     Ref<RenderPipelineBase> result;
     if (ConsumedError(CreateRenderPipeline(descriptor), &result, InternalErrorType::Internal,
                       "calling %s.CreateRenderPipeline(%s).", this, descriptor)) {
-        return RenderPipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
+        result = RenderPipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 ShaderModuleBase* DeviceBase::APICreateShaderModule(const ShaderModuleDescriptor* descriptor) {
     TRACE_EVENT1(GetPlatform(), General, "DeviceBase::APICreateShaderModule", "label",
@@ -1247,7 +1249,7 @@
     // is an error shader module.
     result->InjectCompilationMessages(std::move(compilationMessages));
 
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 ShaderModuleBase* DeviceBase::APICreateErrorShaderModule(const ShaderModuleDescriptor* descriptor,
                                                          const char* errorMessage) {
@@ -1262,24 +1264,24 @@
         DAWN_VALIDATION_ERROR("Error in calling %s.CreateShaderModule(%s).", this, descriptor);
     ConsumeError(std::move(errorData));
 
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 SwapChainBase* DeviceBase::APICreateSwapChain(Surface* surface,
                                               const SwapChainDescriptor* descriptor) {
     Ref<SwapChainBase> result;
     if (ConsumedError(CreateSwapChain(surface, descriptor), &result,
                       "calling %s.CreateSwapChain(%s).", this, descriptor)) {
-        return SwapChainBase::MakeError(this, descriptor);
+        result = SwapChainBase::MakeError(this, descriptor);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 TextureBase* DeviceBase::APICreateTexture(const TextureDescriptor* descriptor) {
     Ref<TextureBase> result;
     if (ConsumedError(CreateTexture(descriptor), &result, InternalErrorType::OutOfMemory,
                       "calling %s.CreateTexture(%s).", this, descriptor)) {
-        return TextureBase::MakeError(this, descriptor);
+        result = TextureBase::MakeError(this, descriptor);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 
 wgpu::TextureUsage DeviceBase::APIGetSupportedSurfaceUsage(Surface* surface) {
@@ -1309,15 +1311,15 @@
     // the client side.
     BufferDescriptor fakeDescriptor = *desc;
     fakeDescriptor.size = 0;
-    return BufferBase::MakeError(this, &fakeDescriptor);
+    return ReturnToAPI(BufferBase::MakeError(this, &fakeDescriptor));
 }
 
 ExternalTextureBase* DeviceBase::APICreateErrorExternalTexture() {
-    return ExternalTextureBase::MakeError(this);
+    return ReturnToAPI(ExternalTextureBase::MakeError(this));
 }
 
 TextureBase* DeviceBase::APICreateErrorTexture(const TextureDescriptor* desc) {
-    return TextureBase::MakeError(this, desc);
+    return ReturnToAPI(TextureBase::MakeError(this, desc));
 }
 
 // Other Device API methods
@@ -1377,42 +1379,40 @@
 }
 
 AdapterBase* DeviceBase::APIGetAdapter() {
-    mAdapter->Reference();
+    mAdapter->APIReference();
     return mAdapter.Get();
 }
 
 QueueBase* DeviceBase::APIGetQueue() {
     // Backends gave the primary queue during initialization.
     DAWN_ASSERT(mQueue != nullptr);
-
-    // Returns a new reference to the queue.
-    mQueue->Reference();
-    return mQueue.Get();
+    auto queue = mQueue;
+    return ReturnToAPI(std::move(queue));
 }
 
 ExternalTextureBase* DeviceBase::APICreateExternalTexture(
     const ExternalTextureDescriptor* descriptor) {
-    Ref<ExternalTextureBase> result = nullptr;
+    Ref<ExternalTextureBase> result;
     if (ConsumedError(CreateExternalTextureImpl(descriptor), &result,
                       "calling %s.CreateExternalTexture(%s).", this, descriptor)) {
-        return ExternalTextureBase::MakeError(this);
+        result = ExternalTextureBase::MakeError(this);
     }
 
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 
 SharedTextureMemoryBase* DeviceBase::APIImportSharedTextureMemory(
     const SharedTextureMemoryDescriptor* descriptor) {
-    Ref<SharedTextureMemoryBase> result = nullptr;
+    Ref<SharedTextureMemoryBase> result;
     if (ConsumedError(
             [&]() -> ResultOrError<Ref<SharedTextureMemoryBase>> {
                 DAWN_TRY(ValidateIsAlive());
                 return ImportSharedTextureMemoryImpl(descriptor);
             }(),
             &result, "calling %s.ImportSharedTextureMemory(%s).", this, descriptor)) {
-        return SharedTextureMemoryBase::MakeError(this, descriptor);
+        result = SharedTextureMemoryBase::MakeError(this, descriptor);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 
 ResultOrError<Ref<SharedTextureMemoryBase>> DeviceBase::ImportSharedTextureMemoryImpl(
@@ -1421,16 +1421,16 @@
 }
 
 SharedFenceBase* DeviceBase::APIImportSharedFence(const SharedFenceDescriptor* descriptor) {
-    Ref<SharedFenceBase> result = nullptr;
+    Ref<SharedFenceBase> result;
     if (ConsumedError(
             [&]() -> ResultOrError<Ref<SharedFenceBase>> {
                 DAWN_TRY(ValidateIsAlive());
                 return ImportSharedFenceImpl(descriptor);
             }(),
             &result, "calling %s.ImportSharedFence(%s).", this, descriptor)) {
-        return SharedFenceBase::MakeError(this, descriptor);
+        result = SharedFenceBase::MakeError(this, descriptor);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 
 ResultOrError<Ref<SharedFenceBase>> DeviceBase::ImportSharedFenceImpl(
@@ -2020,8 +2020,9 @@
         // If the device is no longer alive, errors should not be reported anymore.
         // Call the callback with an error pipeline.
         return mCallbackTaskManager->AddCallbackTask(
-            [callback, pipeline = ComputePipelineBase::MakeError(this, label), userdata]() {
-                callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(pipeline), "", userdata);
+            [callback, pipeline = ComputePipelineBase::MakeError(this, label), userdata]() mutable {
+                callback(WGPUCreatePipelineAsyncStatus_Success,
+                         ToAPI(ReturnToAPI(std::move(pipeline))), "", userdata);
             });
     }
 
@@ -2054,7 +2055,8 @@
                         pipeline->GetDevice()->AddOrGetCachedComputePipeline(std::move(pipeline));
                 }
             }
-            callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(pipeline.Detach()), "", userdata);
+            callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(ReturnToAPI(std::move(pipeline))),
+                     "", userdata);
         });
 }
 
@@ -2066,8 +2068,9 @@
         // If the device is no longer alive, errors should not be reported anymore.
         // Call the callback with an error pipeline.
         return mCallbackTaskManager->AddCallbackTask(
-            [callback, pipeline = RenderPipelineBase::MakeError(this, label), userdata]() {
-                callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(pipeline), "", userdata);
+            [callback, pipeline = RenderPipelineBase::MakeError(this, label), userdata]() mutable {
+                callback(WGPUCreatePipelineAsyncStatus_Success,
+                         ToAPI(ReturnToAPI(std::move(pipeline))), "", userdata);
             });
     }
 
@@ -2098,7 +2101,8 @@
                 pipeline = pipeline->GetDevice()->AddOrGetCachedRenderPipeline(std::move(pipeline));
             }
         }
-        callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(pipeline.Detach()), "", userdata);
+        callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(ReturnToAPI(std::move(pipeline))), "",
+                 userdata);
     });
 }
 
diff --git a/src/dawn/native/ExternalTexture.cpp b/src/dawn/native/ExternalTexture.cpp
index f1e185b..8df7864 100644
--- a/src/dawn/native/ExternalTexture.cpp
+++ b/src/dawn/native/ExternalTexture.cpp
@@ -393,8 +393,8 @@
 }
 
 // static
-ExternalTextureBase* ExternalTextureBase::MakeError(DeviceBase* device, const char* label) {
-    return new ExternalTextureBase(device, ObjectBase::kError, label);
+Ref<ExternalTextureBase> ExternalTextureBase::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new ExternalTextureBase(device, ObjectBase::kError, label));
 }
 
 BufferBase* ExternalTextureBase::GetParamsBuffer() const {
diff --git a/src/dawn/native/ExternalTexture.h b/src/dawn/native/ExternalTexture.h
index a12412c..e5d326b 100644
--- a/src/dawn/native/ExternalTexture.h
+++ b/src/dawn/native/ExternalTexture.h
@@ -68,7 +68,7 @@
     const Origin2D& GetVisibleOrigin() const;
 
     MaybeError ValidateCanUseInSubmitNow() const;
-    static ExternalTextureBase* MakeError(DeviceBase* device, const char* label = nullptr);
+    static Ref<ExternalTextureBase> MakeError(DeviceBase* device, const char* label = nullptr);
 
     void APIExpire();
     void APIDestroy();
diff --git a/src/dawn/native/Instance.cpp b/src/dawn/native/Instance.cpp
index c9d8031..56f53f7 100644
--- a/src/dawn/native/Instance.cpp
+++ b/src/dawn/native/Instance.cpp
@@ -140,7 +140,7 @@
         dawn::ErrorLog() << result.AcquireError()->GetFormattedMessage();
         return nullptr;
     }
-    return result.AcquireSuccess().Detach();
+    return ReturnToAPI(result.AcquireSuccess());
 }
 
 // InstanceBase
@@ -255,7 +255,8 @@
     if (adapters.empty()) {
         callback(WGPURequestAdapterStatus_Unavailable, nullptr, "No supported adapters.", userdata);
     } else {
-        callback(WGPURequestAdapterStatus_Success, ToAPI(adapters[0].Detach()), nullptr, userdata);
+        callback(WGPURequestAdapterStatus_Success, ToAPI(ReturnToAPI(std::move(adapters[0]))),
+                 nullptr, userdata);
     }
 }
 
@@ -569,10 +570,10 @@
 Surface* InstanceBase::APICreateSurface(const SurfaceDescriptor* descriptor) {
     UnpackedPtr<SurfaceDescriptor> unpacked;
     if (ConsumedError(ValidateSurfaceDescriptor(this, descriptor), &unpacked)) {
-        return Surface::MakeError(this);
+        return ReturnToAPI(Surface::MakeError(this));
     }
 
-    return new Surface(this, unpacked);
+    return ReturnToAPI(AcquireRef(new Surface(this, unpacked)));
 }
 
 const std::unordered_set<tint::wgsl::LanguageFeature>&
diff --git a/src/dawn/native/ObjectBase.h b/src/dawn/native/ObjectBase.h
index c98861e..c8e1847 100644
--- a/src/dawn/native/ObjectBase.h
+++ b/src/dawn/native/ObjectBase.h
@@ -150,6 +150,11 @@
     std::string mLabel;
 };
 
+template <class T>
+T* ReturnToAPI(Ref<T>&& object) {
+    return object.Detach();
+}
+
 }  // namespace dawn::native
 
 #endif  // SRC_DAWN_NATIVE_OBJECTBASE_H_
diff --git a/src/dawn/native/Pipeline.cpp b/src/dawn/native/Pipeline.cpp
index db5247b..2eb48d1 100644
--- a/src/dawn/native/Pipeline.cpp
+++ b/src/dawn/native/Pipeline.cpp
@@ -305,9 +305,9 @@
     if (GetDevice()->ConsumedError(GetBindGroupLayout(groupIndexIn), &result,
                                    "Validating GetBindGroupLayout (%u) on %s", groupIndexIn,
                                    this)) {
-        return BindGroupLayoutBase::MakeError(GetDevice());
+        result = BindGroupLayoutBase::MakeError(GetDevice());
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 
 size_t PipelineBase::ComputeContentHash() {
diff --git a/src/dawn/native/PipelineLayout.cpp b/src/dawn/native/PipelineLayout.cpp
index 8457a12..294d15a 100644
--- a/src/dawn/native/PipelineLayout.cpp
+++ b/src/dawn/native/PipelineLayout.cpp
@@ -152,8 +152,8 @@
 }
 
 // static
-PipelineLayoutBase* PipelineLayoutBase::MakeError(DeviceBase* device, const char* label) {
-    return new PipelineLayoutBase(device, ObjectBase::kError, label);
+Ref<PipelineLayoutBase> PipelineLayoutBase::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new PipelineLayoutBase(device, ObjectBase::kError, label));
 }
 
 // static
diff --git a/src/dawn/native/PipelineLayout.h b/src/dawn/native/PipelineLayout.h
index 271fbd4..3f57680 100644
--- a/src/dawn/native/PipelineLayout.h
+++ b/src/dawn/native/PipelineLayout.h
@@ -76,7 +76,7 @@
     PipelineLayoutBase(DeviceBase* device, const UnpackedPtr<PipelineLayoutDescriptor>& descriptor);
     ~PipelineLayoutBase() override;
 
-    static PipelineLayoutBase* MakeError(DeviceBase* device, const char* label);
+    static Ref<PipelineLayoutBase> MakeError(DeviceBase* device, const char* label);
     static ResultOrError<Ref<PipelineLayoutBase>> CreateDefault(
         DeviceBase* device,
         std::vector<StageAndDescriptor> stages);
diff --git a/src/dawn/native/QuerySet.cpp b/src/dawn/native/QuerySet.cpp
index aa2bab4..b722664 100644
--- a/src/dawn/native/QuerySet.cpp
+++ b/src/dawn/native/QuerySet.cpp
@@ -109,8 +109,9 @@
 }
 
 // static
-QuerySetBase* QuerySetBase::MakeError(DeviceBase* device, const QuerySetDescriptor* descriptor) {
-    return new ErrorQuerySet(device, descriptor);
+Ref<QuerySetBase> QuerySetBase::MakeError(DeviceBase* device,
+                                          const QuerySetDescriptor* descriptor) {
+    return AcquireRef(new ErrorQuerySet(device, descriptor));
 }
 
 ObjectType QuerySetBase::GetType() const {
diff --git a/src/dawn/native/QuerySet.h b/src/dawn/native/QuerySet.h
index 7019c3a..ff3de37 100644
--- a/src/dawn/native/QuerySet.h
+++ b/src/dawn/native/QuerySet.h
@@ -42,7 +42,7 @@
 
 class QuerySetBase : public ApiObjectBase {
   public:
-    static QuerySetBase* MakeError(DeviceBase* device, const QuerySetDescriptor* descriptor);
+    static Ref<QuerySetBase> MakeError(DeviceBase* device, const QuerySetDescriptor* descriptor);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/Queue.cpp b/src/dawn/native/Queue.cpp
index 449bf78..cebcd93 100644
--- a/src/dawn/native/Queue.cpp
+++ b/src/dawn/native/Queue.cpp
@@ -259,8 +259,8 @@
 void QueueBase::DestroyImpl() {}
 
 // static
-QueueBase* QueueBase::MakeError(DeviceBase* device, const char* label) {
-    return new ErrorQueue(device, label);
+Ref<QueueBase> QueueBase::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new ErrorQueue(device, label));
 }
 
 ObjectType QueueBase::GetType() const {
diff --git a/src/dawn/native/Queue.h b/src/dawn/native/Queue.h
index c802739..a6e7345 100644
--- a/src/dawn/native/Queue.h
+++ b/src/dawn/native/Queue.h
@@ -65,7 +65,7 @@
   public:
     ~QueueBase() override;
 
-    static QueueBase* MakeError(DeviceBase* device, const char* label);
+    static Ref<QueueBase> MakeError(DeviceBase* device, const char* label);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/RenderBundle.cpp b/src/dawn/native/RenderBundle.cpp
index c095826..7b70502 100644
--- a/src/dawn/native/RenderBundle.cpp
+++ b/src/dawn/native/RenderBundle.cpp
@@ -66,8 +66,8 @@
 }
 
 // static
-RenderBundleBase* RenderBundleBase::MakeError(DeviceBase* device, const char* label) {
-    return new RenderBundleBase(device, ObjectBase::kError, label);
+Ref<RenderBundleBase> RenderBundleBase::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new RenderBundleBase(device, ObjectBase::kError, label));
 }
 
 RenderBundleBase::RenderBundleBase(DeviceBase* device, ErrorTag errorTag, const char* label)
diff --git a/src/dawn/native/RenderBundle.h b/src/dawn/native/RenderBundle.h
index b27c77e..91b96f2 100644
--- a/src/dawn/native/RenderBundle.h
+++ b/src/dawn/native/RenderBundle.h
@@ -57,7 +57,7 @@
                      RenderPassResourceUsage resourceUsage,
                      IndirectDrawMetadata indirectDrawMetadata);
 
-    static RenderBundleBase* MakeError(DeviceBase* device, const char* label);
+    static Ref<RenderBundleBase> MakeError(DeviceBase* device, const char* label);
 
     ObjectType GetType() const override;
     void FormatLabel(absl::FormatSink* s) const override;
diff --git a/src/dawn/native/RenderBundleEncoder.cpp b/src/dawn/native/RenderBundleEncoder.cpp
index ba0e246..80b5aa4 100644
--- a/src/dawn/native/RenderBundleEncoder.cpp
+++ b/src/dawn/native/RenderBundleEncoder.cpp
@@ -140,8 +140,8 @@
 }
 
 // static
-RenderBundleEncoder* RenderBundleEncoder::MakeError(DeviceBase* device, const char* label) {
-    return new RenderBundleEncoder(device, ObjectBase::kError, label);
+Ref<RenderBundleEncoder> RenderBundleEncoder::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new RenderBundleEncoder(device, ObjectBase::kError, label));
 }
 
 ObjectType RenderBundleEncoder::GetType() const {
@@ -153,20 +153,18 @@
 }
 
 RenderBundleBase* RenderBundleEncoder::APIFinish(const RenderBundleDescriptor* descriptor) {
-    RenderBundleBase* result = nullptr;
+    Ref<RenderBundleBase> result;
 
     if (GetDevice()->ConsumedError(FinishImpl(descriptor), &result, "calling %s.Finish(%s).", this,
                                    descriptor)) {
-        RenderBundleBase* errorRenderBundle =
-            RenderBundleBase::MakeError(GetDevice(), descriptor ? descriptor->label : nullptr);
-        errorRenderBundle->SetEncoderLabel(this->GetLabel());
-        return errorRenderBundle;
+        result = RenderBundleBase::MakeError(GetDevice(), descriptor ? descriptor->label : nullptr);
+        result->SetEncoderLabel(this->GetLabel());
     }
 
-    return result;
+    return ReturnToAPI(std::move(result));
 }
 
-ResultOrError<RenderBundleBase*> RenderBundleEncoder::FinishImpl(
+ResultOrError<Ref<RenderBundleBase>> RenderBundleEncoder::FinishImpl(
     const RenderBundleDescriptor* descriptor) {
     // Even if mBundleEncodingContext.Finish() validation fails, calling it will mutate the
     // internal state of the encoding context. Subsequent calls to encode commands will generate
@@ -180,9 +178,9 @@
         DAWN_TRY(ValidateFinish(usages));
     }
 
-    return new RenderBundleBase(this, descriptor, AcquireAttachmentState(), IsDepthReadOnly(),
-                                IsStencilReadOnly(), std::move(usages),
-                                std::move(mIndirectDrawMetadata));
+    return AcquireRef(new RenderBundleBase(this, descriptor, AcquireAttachmentState(),
+                                           IsDepthReadOnly(), IsStencilReadOnly(),
+                                           std::move(usages), std::move(mIndirectDrawMetadata)));
 }
 
 MaybeError RenderBundleEncoder::ValidateFinish(const RenderPassResourceUsage& usages) const {
diff --git a/src/dawn/native/RenderBundleEncoder.h b/src/dawn/native/RenderBundleEncoder.h
index 8010e15..f1efb83 100644
--- a/src/dawn/native/RenderBundleEncoder.h
+++ b/src/dawn/native/RenderBundleEncoder.h
@@ -43,7 +43,7 @@
   public:
     static Ref<RenderBundleEncoder> Create(DeviceBase* device,
                                            const RenderBundleEncoderDescriptor* descriptor);
-    static RenderBundleEncoder* MakeError(DeviceBase* device, const char* label);
+    static Ref<RenderBundleEncoder> MakeError(DeviceBase* device, const char* label);
 
     ObjectType GetType() const override;
 
@@ -57,7 +57,7 @@
 
     void DestroyImpl() override;
 
-    ResultOrError<RenderBundleBase*> FinishImpl(const RenderBundleDescriptor* descriptor);
+    ResultOrError<Ref<RenderBundleBase>> FinishImpl(const RenderBundleDescriptor* descriptor);
     MaybeError ValidateFinish(const RenderPassResourceUsage& usages) const;
 
     EncodingContext mBundleEncodingContext;
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp
index 2589b68..1ae53c0 100644
--- a/src/dawn/native/RenderPipeline.cpp
+++ b/src/dawn/native/RenderPipeline.cpp
@@ -996,7 +996,7 @@
 }
 
 // static
-RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device, const char* label) {
+Ref<RenderPipelineBase> RenderPipelineBase::MakeError(DeviceBase* device, const char* label) {
     class ErrorRenderPipeline final : public RenderPipelineBase {
       public:
         explicit ErrorRenderPipeline(DeviceBase* device, const char* label)
@@ -1008,7 +1008,7 @@
         }
     };
 
-    return new ErrorRenderPipeline(device, label);
+    return AcquireRef(new ErrorRenderPipeline(device, label));
 }
 
 ObjectType RenderPipelineBase::GetType() const {
diff --git a/src/dawn/native/RenderPipeline.h b/src/dawn/native/RenderPipeline.h
index ef08ff5..ee16c51 100644
--- a/src/dawn/native/RenderPipeline.h
+++ b/src/dawn/native/RenderPipeline.h
@@ -94,7 +94,7 @@
     RenderPipelineBase(DeviceBase* device, const UnpackedPtr<RenderPipelineDescriptor>& descriptor);
     ~RenderPipelineBase() override;
 
-    static RenderPipelineBase* MakeError(DeviceBase* device, const char* label);
+    static Ref<RenderPipelineBase> MakeError(DeviceBase* device, const char* label);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/Sampler.cpp b/src/dawn/native/Sampler.cpp
index d27ca6a..a04f7fb 100644
--- a/src/dawn/native/Sampler.cpp
+++ b/src/dawn/native/Sampler.cpp
@@ -106,8 +106,8 @@
 }
 
 // static
-SamplerBase* SamplerBase::MakeError(DeviceBase* device, const char* label) {
-    return new SamplerBase(device, ObjectBase::kError, label);
+Ref<SamplerBase> SamplerBase::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new SamplerBase(device, ObjectBase::kError, label));
 }
 
 ObjectType SamplerBase::GetType() const {
diff --git a/src/dawn/native/Sampler.h b/src/dawn/native/Sampler.h
index ef2da08..329573e 100644
--- a/src/dawn/native/Sampler.h
+++ b/src/dawn/native/Sampler.h
@@ -52,7 +52,7 @@
     SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor);
     ~SamplerBase() override;
 
-    static SamplerBase* MakeError(DeviceBase* device, const char* label);
+    static Ref<SamplerBase> MakeError(DeviceBase* device, const char* label);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/SharedFence.cpp b/src/dawn/native/SharedFence.cpp
index 5855da5..3ba1c47 100644
--- a/src/dawn/native/SharedFence.cpp
+++ b/src/dawn/native/SharedFence.cpp
@@ -48,9 +48,9 @@
 }  // namespace
 
 // static
-SharedFenceBase* SharedFenceBase::MakeError(DeviceBase* device,
-                                            const SharedFenceDescriptor* descriptor) {
-    return new ErrorSharedFence(device, descriptor);
+Ref<SharedFenceBase> SharedFenceBase::MakeError(DeviceBase* device,
+                                                const SharedFenceDescriptor* descriptor) {
+    return AcquireRef(new ErrorSharedFence(device, descriptor));
 }
 
 SharedFenceBase::SharedFenceBase(DeviceBase* device,
diff --git a/src/dawn/native/SharedFence.h b/src/dawn/native/SharedFence.h
index 19914b3..e75dd55 100644
--- a/src/dawn/native/SharedFence.h
+++ b/src/dawn/native/SharedFence.h
@@ -38,7 +38,8 @@
 
 class SharedFenceBase : public ApiObjectBase {
   public:
-    static SharedFenceBase* MakeError(DeviceBase* device, const SharedFenceDescriptor* descriptor);
+    static Ref<SharedFenceBase> MakeError(DeviceBase* device,
+                                          const SharedFenceDescriptor* descriptor);
 
     ObjectType GetType() const override;
 
diff --git a/src/dawn/native/SharedTextureMemory.cpp b/src/dawn/native/SharedTextureMemory.cpp
index 6a632b0..d8f693e 100644
--- a/src/dawn/native/SharedTextureMemory.cpp
+++ b/src/dawn/native/SharedTextureMemory.cpp
@@ -61,10 +61,10 @@
 }  // namespace
 
 // static
-SharedTextureMemoryBase* SharedTextureMemoryBase::MakeError(
+Ref<SharedTextureMemoryBase> SharedTextureMemoryBase::MakeError(
     DeviceBase* device,
     const SharedTextureMemoryDescriptor* descriptor) {
-    return new ErrorSharedTextureMemory(device, descriptor);
+    return AcquireRef(new ErrorSharedTextureMemory(device, descriptor));
 }
 
 SharedTextureMemoryBase::SharedTextureMemoryBase(DeviceBase* device,
@@ -151,9 +151,9 @@
     if (GetDevice()->ConsumedError(CreateTexture(descriptor), &result,
                                    InternalErrorType::OutOfMemory, "calling %s.CreateTexture(%s).",
                                    this, descriptor)) {
-        return TextureBase::MakeError(GetDevice(), descriptor);
+        result = TextureBase::MakeError(GetDevice(), descriptor);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 
 Ref<SharedTextureMemoryContents> SharedTextureMemoryBase::CreateContents() {
@@ -346,7 +346,7 @@
         auto* fences = new SharedFenceBase*[fenceCount];
         uint64_t* signaledValues = new uint64_t[fenceCount];
         for (size_t i = 0; i < fenceCount; ++i) {
-            fences[i] = fenceList[i].object.Detach();
+            fences[i] = ReturnToAPI(std::move(fenceList[i].object));
             signaledValues[i] = fenceList[i].signaledValue;
         }
 
diff --git a/src/dawn/native/SharedTextureMemory.h b/src/dawn/native/SharedTextureMemory.h
index d5ac3df..be34418 100644
--- a/src/dawn/native/SharedTextureMemory.h
+++ b/src/dawn/native/SharedTextureMemory.h
@@ -54,8 +54,8 @@
     using EndAccessState = SharedTextureMemoryEndAccessState;
     using PendingFenceList = StackVector<FenceAndSignalValue, 1>;
 
-    static SharedTextureMemoryBase* MakeError(DeviceBase* device,
-                                              const SharedTextureMemoryDescriptor* descriptor);
+    static Ref<SharedTextureMemoryBase> MakeError(DeviceBase* device,
+                                                  const SharedTextureMemoryDescriptor* descriptor);
 
     void Initialize();
 
diff --git a/src/dawn/native/Surface.cpp b/src/dawn/native/Surface.cpp
index 1caa6b5..126aab3 100644
--- a/src/dawn/native/Surface.cpp
+++ b/src/dawn/native/Surface.cpp
@@ -187,8 +187,8 @@
 }
 
 // static
-Surface* Surface::MakeError(InstanceBase* instance) {
-    return new Surface(instance, ErrorMonad::kError);
+Ref<Surface> Surface::MakeError(InstanceBase* instance) {
+    return AcquireRef(new Surface(instance, ErrorMonad::kError));
 }
 
 Surface::Surface(InstanceBase* instance, ErrorTag tag) : ErrorMonad(tag), mInstance(instance) {}
diff --git a/src/dawn/native/Surface.h b/src/dawn/native/Surface.h
index ce4e8c4..56c106e 100644
--- a/src/dawn/native/Surface.h
+++ b/src/dawn/native/Surface.h
@@ -58,7 +58,7 @@
 // replaced.
 class Surface final : public ErrorMonad {
   public:
-    static Surface* MakeError(InstanceBase* instance);
+    static Ref<Surface> MakeError(InstanceBase* instance);
 
     Surface(InstanceBase* instance, const UnpackedPtr<SurfaceDescriptor>& descriptor);
 
diff --git a/src/dawn/native/SwapChain.cpp b/src/dawn/native/SwapChain.cpp
index 850a83b..3c00d47 100644
--- a/src/dawn/native/SwapChain.cpp
+++ b/src/dawn/native/SwapChain.cpp
@@ -27,6 +27,8 @@
 
 #include "dawn/native/SwapChain.h"
 
+#include <utility>
+
 #include "dawn/common/Constants.h"
 #include "dawn/native/Device.h"
 #include "dawn/native/ObjectType_autogen.h"
@@ -145,8 +147,8 @@
       mPresentMode(descriptor->presentMode) {}
 
 // static
-SwapChainBase* SwapChainBase::MakeError(DeviceBase* device, const SwapChainDescriptor* desc) {
-    return new ErrorSwapChain(device, desc);
+Ref<SwapChainBase> SwapChainBase::MakeError(DeviceBase* device, const SwapChainDescriptor* desc) {
+    return AcquireRef(new ErrorSwapChain(device, desc));
 }
 
 void SwapChainBase::DestroyImpl() {}
@@ -180,22 +182,20 @@
     if (GetDevice()->ConsumedError(GetCurrentTexture(), &result, "calling %s.GetCurrentTexture()",
                                    this)) {
         TextureDescriptor desc = GetSwapChainBaseTextureDescriptor(this);
-        TextureBase* errorTexture = TextureBase::MakeError(GetDevice(), &desc);
-        SetChildLabel(errorTexture);
-        return errorTexture;
+        result = TextureBase::MakeError(GetDevice(), &desc);
+        SetChildLabel(result.Get());
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 
 TextureViewBase* SwapChainBase::APIGetCurrentTextureView() {
     Ref<TextureViewBase> result;
     if (GetDevice()->ConsumedError(GetCurrentTextureView(), &result,
                                    "calling %s.GetCurrentTextureView()", this)) {
-        TextureViewBase* errorView = TextureViewBase::MakeError(GetDevice());
-        SetChildLabel(errorView);
-        return errorView;
+        result = TextureViewBase::MakeError(GetDevice());
+        SetChildLabel(result.Get());
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 
 ResultOrError<Ref<TextureBase>> SwapChainBase::GetCurrentTexture() {
diff --git a/src/dawn/native/SwapChain.h b/src/dawn/native/SwapChain.h
index b1e7884..a6c1772 100644
--- a/src/dawn/native/SwapChain.h
+++ b/src/dawn/native/SwapChain.h
@@ -45,7 +45,7 @@
   public:
     SwapChainBase(DeviceBase* device, Surface* surface, const SwapChainDescriptor* descriptor);
 
-    static SwapChainBase* MakeError(DeviceBase* device, const SwapChainDescriptor* descriptor);
+    static Ref<SwapChainBase> MakeError(DeviceBase* device, const SwapChainDescriptor* descriptor);
     ObjectType GetType() const override;
 
     // This is called when the swapchain is detached when one of the following happens:
diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp
index 0afa627..d71ea1f 100644
--- a/src/dawn/native/Texture.cpp
+++ b/src/dawn/native/Texture.cpp
@@ -823,8 +823,8 @@
 }
 
 // static
-TextureBase* TextureBase::MakeError(DeviceBase* device, const TextureDescriptor* descriptor) {
-    return new TextureBase(device, descriptor, ObjectBase::kError);
+Ref<TextureBase> TextureBase::MakeError(DeviceBase* device, const TextureDescriptor* descriptor) {
+    return AcquireRef(new TextureBase(device, descriptor, ObjectBase::kError));
 }
 
 ObjectType TextureBase::GetType() const {
@@ -1118,7 +1118,7 @@
     return GetDevice()->CreateTextureView(this, descriptor);
 }
 
-TextureViewBase* TextureBase::CreateErrorView(const TextureViewDescriptor* descriptor) {
+Ref<TextureViewBase> TextureBase::CreateErrorView(const TextureViewDescriptor* descriptor) {
     return TextureViewBase::MakeError(GetDevice(), descriptor ? descriptor->label : nullptr);
 }
 
@@ -1132,13 +1132,13 @@
     Ref<TextureViewBase> result;
     if (device->ConsumedError(CreateView(descriptor), &result, "calling %s.CreateView(%s).", this,
                               descriptor)) {
-        return CreateErrorView(descriptor);
+        result = CreateErrorView(descriptor);
     }
-    return result.Detach();
+    return ReturnToAPI(std::move(result));
 }
 
 TextureViewBase* TextureBase::APICreateErrorView(const TextureViewDescriptor* descriptor) {
-    return CreateErrorView(descriptor);
+    return ReturnToAPI(CreateErrorView(descriptor));
 }
 
 bool TextureBase::IsImplicitMSAARenderTextureViewSupported() const {
@@ -1205,8 +1205,8 @@
 void TextureViewBase::DestroyImpl() {}
 
 // static
-TextureViewBase* TextureViewBase::MakeError(DeviceBase* device, const char* label) {
-    return new TextureViewBase(device, ObjectBase::kError, label);
+Ref<TextureViewBase> TextureViewBase::MakeError(DeviceBase* device, const char* label) {
+    return AcquireRef(new TextureViewBase(device, ObjectBase::kError, label));
 }
 
 ObjectType TextureViewBase::GetType() const {
diff --git a/src/dawn/native/Texture.h b/src/dawn/native/Texture.h
index 60c661b..b6018d5 100644
--- a/src/dawn/native/Texture.h
+++ b/src/dawn/native/Texture.h
@@ -80,7 +80,7 @@
   public:
     enum class ClearValue { Zero, NonZero };
 
-    static TextureBase* MakeError(DeviceBase* device, const TextureDescriptor* descriptor);
+    static Ref<TextureBase> MakeError(DeviceBase* device, const TextureDescriptor* descriptor);
 
     ObjectType GetType() const override;
 
@@ -141,7 +141,7 @@
 
     ResultOrError<Ref<TextureViewBase>> CreateView(
         const TextureViewDescriptor* descriptor = nullptr);
-    TextureViewBase* CreateErrorView(const TextureViewDescriptor* descriptor = nullptr);
+    Ref<TextureViewBase> CreateErrorView(const TextureViewDescriptor* descriptor = nullptr);
     ApiObjectList* GetViewTrackingList();
 
     bool IsImplicitMSAARenderTextureViewSupported() const;
@@ -209,7 +209,7 @@
     TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor);
     ~TextureViewBase() override;
 
-    static TextureViewBase* MakeError(DeviceBase* device, const char* label = nullptr);
+    static Ref<TextureViewBase> MakeError(DeviceBase* device, const char* label = nullptr);
 
     ObjectType GetType() const override;
     void FormatLabel(absl::FormatSink* s) const override;
diff --git a/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp b/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp
index cc1de49..bad0e62 100644
--- a/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp
+++ b/src/dawn/native/d3d/ExternalImageDXGIImpl.cpp
@@ -183,7 +183,7 @@
     }
     ++mAccessCount;
 
-    return ToAPI(texture.Detach());
+    return ToAPI(ReturnToAPI(std::move(texture)));
 }
 
 void ExternalImageDXGIImpl::EndAccess(WGPUTexture texture,
diff --git a/src/dawn/native/opengl/DeviceGL.cpp b/src/dawn/native/opengl/DeviceGL.cpp
index 267f48c..4249f8a 100644
--- a/src/dawn/native/opengl/DeviceGL.cpp
+++ b/src/dawn/native/opengl/DeviceGL.cpp
@@ -300,8 +300,8 @@
     return {};
 }
 
-TextureBase* Device::CreateTextureWrappingEGLImage(const ExternalImageDescriptor* descriptor,
-                                                   ::EGLImage image) {
+Ref<TextureBase> Device::CreateTextureWrappingEGLImage(const ExternalImageDescriptor* descriptor,
+                                                       ::EGLImage image) {
     const OpenGLFunctions& gl = GetGL();
 
     UnpackedPtr<TextureDescriptor> textureDescriptor;
@@ -338,14 +338,14 @@
 
     // TODO(dawn:803): Validate the OpenGL texture format from the EGLImage against the format
     // in the passed-in TextureDescriptor.
-    auto result = new Texture(this, textureDescriptor, tex);
+    auto result = AcquireRef(new Texture(this, textureDescriptor, tex));
     result->SetIsSubresourceContentInitialized(descriptor->isInitialized,
                                                result->GetAllSubresources());
     return result;
 }
 
-TextureBase* Device::CreateTextureWrappingGLTexture(const ExternalImageDescriptor* descriptor,
-                                                    GLuint texture) {
+Ref<TextureBase> Device::CreateTextureWrappingGLTexture(const ExternalImageDescriptor* descriptor,
+                                                        GLuint texture) {
     const OpenGLFunctions& gl = GetGL();
 
     UnpackedPtr<TextureDescriptor> textureDescriptor;
@@ -379,7 +379,7 @@
         return nullptr;
     }
 
-    auto result = new Texture(this, textureDescriptor, texture);
+    auto result = AcquireRef(new Texture(this, textureDescriptor, texture));
     result->SetIsSubresourceContentInitialized(descriptor->isInitialized,
                                                result->GetAllSubresources());
     return result;
diff --git a/src/dawn/native/opengl/DeviceGL.h b/src/dawn/native/opengl/DeviceGL.h
index 2237dc8..22af159 100644
--- a/src/dawn/native/opengl/DeviceGL.h
+++ b/src/dawn/native/opengl/DeviceGL.h
@@ -67,10 +67,10 @@
     const GLFormat& GetGLFormat(const Format& format);
 
     MaybeError ValidateTextureCanBeWrapped(const UnpackedPtr<TextureDescriptor>& descriptor);
-    TextureBase* CreateTextureWrappingEGLImage(const ExternalImageDescriptor* descriptor,
-                                               ::EGLImage image);
-    TextureBase* CreateTextureWrappingGLTexture(const ExternalImageDescriptor* descriptor,
-                                                GLuint texture);
+    Ref<TextureBase> CreateTextureWrappingEGLImage(const ExternalImageDescriptor* descriptor,
+                                                   ::EGLImage image);
+    Ref<TextureBase> CreateTextureWrappingGLTexture(const ExternalImageDescriptor* descriptor,
+                                                    GLuint texture);
 
     ResultOrError<Ref<CommandBufferBase>> CreateCommandBuffer(
         CommandEncoder* encoder,
diff --git a/src/dawn/native/opengl/OpenGLBackend.cpp b/src/dawn/native/opengl/OpenGLBackend.cpp
index 684ffdc..8ad5d62 100644
--- a/src/dawn/native/opengl/OpenGLBackend.cpp
+++ b/src/dawn/native/opengl/OpenGLBackend.cpp
@@ -30,6 +30,8 @@
 
 #include "dawn/native/OpenGLBackend.h"
 
+#include <utility>
+
 #include "dawn/native/opengl/DeviceGL.h"
 
 namespace dawn::native::opengl {
@@ -47,17 +49,17 @@
 WGPUTexture WrapExternalEGLImage(WGPUDevice device,
                                  const ExternalImageDescriptorEGLImage* descriptor) {
     Device* backendDevice = ToBackend(FromAPI(device));
-    TextureBase* texture =
+    Ref<TextureBase> texture =
         backendDevice->CreateTextureWrappingEGLImage(descriptor, descriptor->image);
-    return ToAPI(texture);
+    return ToAPI(ReturnToAPI(std::move(texture)));
 }
 
 WGPUTexture WrapExternalGLTexture(WGPUDevice device,
                                   const ExternalImageDescriptorGLTexture* descriptor) {
     Device* backendDevice = ToBackend(FromAPI(device));
-    TextureBase* texture =
+    Ref<TextureBase> texture =
         backendDevice->CreateTextureWrappingGLTexture(descriptor, descriptor->texture);
-    return ToAPI(texture);
+    return ToAPI(ReturnToAPI(std::move(texture)));
 }
 
 }  // namespace dawn::native::opengl
diff --git a/src/dawn/native/vulkan/DeviceVk.cpp b/src/dawn/native/vulkan/DeviceVk.cpp
index 2274c47..136f16d 100644
--- a/src/dawn/native/vulkan/DeviceVk.cpp
+++ b/src/dawn/native/vulkan/DeviceVk.cpp
@@ -702,7 +702,7 @@
     }());
 }
 
-TextureBase* Device::CreateTextureWrappingVulkanImage(
+Ref<TextureBase> Device::CreateTextureWrappingVulkanImage(
     const ExternalImageDescriptorVk* descriptor,
     ExternalMemoryHandle memoryHandle,
     const std::vector<ExternalSemaphoreHandle>& waitHandles) {
@@ -738,7 +738,7 @@
 
     // Cleanup in case of a failure, the image creation doesn't acquire the external objects
     // if a failure happems.
-    Texture* result = nullptr;
+    Ref<Texture> result;
     // TODO(crbug.com/1026480): Consolidate this into a single CreateFromExternal call.
     if (ConsumedError(Texture::CreateFromExternal(this, descriptor, textureDescriptor,
                                                   mExternalMemoryService.get()),
@@ -747,9 +747,7 @@
                                           waitHandles, &allocation, &waitSemaphores)) ||
         ConsumedError(result->BindExternalMemory(descriptor, allocation, waitSemaphores))) {
         // Delete the Texture if it was created
-        if (result != nullptr) {
-            result->Release();
-        }
+        result = nullptr;
 
         // Clear image memory
         fn.FreeMemory(GetVkDevice(), allocation, nullptr);
@@ -758,7 +756,6 @@
         for (VkSemaphore semaphore : waitSemaphores) {
             fn.DestroySemaphore(GetVkDevice(), semaphore, nullptr);
         }
-        return nullptr;
     }
 
     return result;
diff --git a/src/dawn/native/vulkan/DeviceVk.h b/src/dawn/native/vulkan/DeviceVk.h
index cdac663..82856ec 100644
--- a/src/dawn/native/vulkan/DeviceVk.h
+++ b/src/dawn/native/vulkan/DeviceVk.h
@@ -82,7 +82,7 @@
 
     // Dawn Native API
 
-    TextureBase* CreateTextureWrappingVulkanImage(
+    Ref<TextureBase> CreateTextureWrappingVulkanImage(
         const ExternalImageDescriptorVk* descriptor,
         ExternalMemoryHandle memoryHandle,
         const std::vector<ExternalSemaphoreHandle>& waitHandles);
diff --git a/src/dawn/native/vulkan/TextureVk.cpp b/src/dawn/native/vulkan/TextureVk.cpp
index 226f884..fb8ab56 100644
--- a/src/dawn/native/vulkan/TextureVk.cpp
+++ b/src/dawn/native/vulkan/TextureVk.cpp
@@ -703,14 +703,14 @@
 }
 
 // static
-ResultOrError<Texture*> Texture::CreateFromExternal(
+ResultOrError<Ref<Texture>> Texture::CreateFromExternal(
     Device* device,
     const ExternalImageDescriptorVk* descriptor,
     const UnpackedPtr<TextureDescriptor>& textureDescriptor,
     external_memory::Service* externalMemoryService) {
     Ref<Texture> texture = AcquireRef(new Texture(device, textureDescriptor));
     DAWN_TRY(texture->InitializeFromExternal(descriptor, externalMemoryService));
-    return texture.Detach();
+    return texture;
 }
 
 // static
diff --git a/src/dawn/native/vulkan/TextureVk.h b/src/dawn/native/vulkan/TextureVk.h
index c006668..f9b5f78 100644
--- a/src/dawn/native/vulkan/TextureVk.h
+++ b/src/dawn/native/vulkan/TextureVk.h
@@ -71,7 +71,7 @@
     // Creates a texture and initializes it with a VkImage that references an external memory
     // object. Before the texture can be used, the VkDeviceMemory associated with the external
     // image must be bound via Texture::BindExternalMemory.
-    static ResultOrError<Texture*> CreateFromExternal(
+    static ResultOrError<Ref<Texture>> CreateFromExternal(
         Device* device,
         const ExternalImageDescriptorVk* descriptor,
         const UnpackedPtr<TextureDescriptor>& textureDescriptor,
diff --git a/src/dawn/native/vulkan/VulkanBackend.cpp b/src/dawn/native/vulkan/VulkanBackend.cpp
index b409077..5ccb078 100644
--- a/src/dawn/native/vulkan/VulkanBackend.cpp
+++ b/src/dawn/native/vulkan/VulkanBackend.cpp
@@ -28,6 +28,8 @@
 // VulkanBackend.cpp: contains the definition of symbols exported by VulkanBackend.h so that they
 // can be compiled twice: once export (shared library), once not exported (static library)
 
+#include <utility>
+
 // Include vulkan_platform.h before VulkanBackend.h includes vulkan.h so that we use our version
 // of the non-dispatchable handles.
 #include "dawn/common/vulkan_platform.h"
@@ -84,18 +86,18 @@
         case ExternalImageType::AHardwareBuffer: {
             const ExternalImageDescriptorAHardwareBuffer* ahbDescriptor =
                 static_cast<const ExternalImageDescriptorAHardwareBuffer*>(descriptor);
-
-            return ToAPI(backendDevice->CreateTextureWrappingVulkanImage(
-                ahbDescriptor, ahbDescriptor->handle, ahbDescriptor->waitFDs));
+            Ref<TextureBase> texture = backendDevice->CreateTextureWrappingVulkanImage(
+                ahbDescriptor, ahbDescriptor->handle, ahbDescriptor->waitFDs);
+            return ToAPI(ReturnToAPI(std::move(texture)));
         }
 #elif DAWN_PLATFORM_IS(LINUX)
         case ExternalImageType::OpaqueFD:
         case ExternalImageType::DmaBuf: {
             const ExternalImageDescriptorFD* fdDescriptor =
                 static_cast<const ExternalImageDescriptorFD*>(descriptor);
-
-            return ToAPI(backendDevice->CreateTextureWrappingVulkanImage(
-                fdDescriptor, fdDescriptor->memoryFD, fdDescriptor->waitFDs));
+            Ref<TextureBase> texture = backendDevice->CreateTextureWrappingVulkanImage(
+                fdDescriptor, fdDescriptor->memoryFD, fdDescriptor->waitFDs);
+            return ToAPI(ReturnToAPI(std::move(texture)));
         }
 #endif  // DAWN_PLATFORM_IS(LINUX)
 
diff --git a/src/dawn/tests/unittests/native/AllowedErrorTests.cpp b/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
index 2527fb0..67cf7af 100644
--- a/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
+++ b/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
@@ -104,8 +104,8 @@
     BufferDescriptor desc = {};
     desc.size = 1;
     desc.usage = wgpu::BufferUsage::CopyDst;
-    BufferMock* bufferMock = new NiceMock<BufferMock>(mDeviceMock, &desc);
-    wgpu::Buffer buffer = wgpu::Buffer::Acquire(ToAPI(bufferMock));
+    Ref<BufferMock> bufferMock = AcquireRef(new NiceMock<BufferMock>(mDeviceMock, &desc));
+    wgpu::Buffer buffer = wgpu::Buffer::Acquire(ToAPI(ReturnToAPI(std::move(bufferMock))));
 
     EXPECT_CALL(*(mDeviceMock->GetQueueMock()), WriteBufferImpl)
         .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
@@ -125,8 +125,8 @@
     desc.size.height = 1;
     desc.usage = wgpu::TextureUsage::CopyDst;
     desc.format = wgpu::TextureFormat::RGBA8Unorm;
-    TextureMock* textureMock = new NiceMock<TextureMock>(mDeviceMock, &desc);
-    wgpu::Texture texture = wgpu::Texture::Acquire(ToAPI(textureMock));
+    Ref<TextureMock> textureMock = AcquireRef(new NiceMock<TextureMock>(mDeviceMock, &desc));
+    wgpu::Texture texture = wgpu::Texture::Acquire(ToAPI(ReturnToAPI(std::move(textureMock))));
 
     EXPECT_CALL(*(mDeviceMock->GetQueueMock()), WriteTextureImpl)
         .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
diff --git a/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp b/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp
index dfc47da..1abf234 100644
--- a/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp
+++ b/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp
@@ -27,6 +27,8 @@
 
 #include "dawn/tests/unittests/native/mocks/DawnMockTest.h"
 
+#include <utility>
+
 #include "dawn/dawn_proc.h"
 
 namespace dawn::native {
@@ -34,8 +36,9 @@
 DawnMockTest::DawnMockTest() {
     dawnProcSetProcs(&dawn::native::GetProcs());
 
-    mDeviceMock = new ::testing::NiceMock<DeviceMock>();
-    device = wgpu::Device::Acquire(ToAPI(mDeviceMock));
+    auto deviceMock = AcquireRef(new ::testing::NiceMock<DeviceMock>());
+    mDeviceMock = deviceMock.Get();
+    device = wgpu::Device::Acquire(ToAPI(ReturnToAPI<DeviceBase>(std::move(deviceMock))));
 }
 
 DawnMockTest::~DawnMockTest() {
diff --git a/src/dawn/tests/white_box/InternalResolveAttachmentSampleTypeTests.cpp b/src/dawn/tests/white_box/InternalResolveAttachmentSampleTypeTests.cpp
index aa79a2c..4752e11 100644
--- a/src/dawn/tests/white_box/InternalResolveAttachmentSampleTypeTests.cpp
+++ b/src/dawn/tests/white_box/InternalResolveAttachmentSampleTypeTests.cpp
@@ -25,6 +25,7 @@
 // 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 <utility>
 #include <vector>
 
 #include "dawn/native/BindGroupLayout.h"
@@ -76,7 +77,8 @@
         Ref<native::BindGroupLayoutBase> bglRef =
             nativeDevice->CreateBindGroupLayout(&bglDesc, true).AcquireSuccess();
 
-        auto bindGroupLayout = wgpu::BindGroupLayout::Acquire(native::ToAPI(bglRef.Detach()));
+        auto bindGroupLayout =
+            wgpu::BindGroupLayout::Acquire(native::ToAPI(ReturnToAPI(std::move(bglRef))));
 
         // Create pipeline layout from the bind group layout.
         wgpu::PipelineLayoutDescriptor descriptor;
diff --git a/src/dawn/tests/white_box/InternalStorageBufferBindingTests.cpp b/src/dawn/tests/white_box/InternalStorageBufferBindingTests.cpp
index 4cd37c9..4060a58 100644
--- a/src/dawn/tests/white_box/InternalStorageBufferBindingTests.cpp
+++ b/src/dawn/tests/white_box/InternalStorageBufferBindingTests.cpp
@@ -25,6 +25,7 @@
 // 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 <utility>
 #include <vector>
 
 #include "dawn/native/BindGroupLayout.h"
@@ -75,7 +76,8 @@
         Ref<native::BindGroupLayoutBase> bglRef =
             nativeDevice->CreateBindGroupLayout(&bglDesc, true).AcquireSuccess();
 
-        wgpu::BindGroupLayout bgl = wgpu::BindGroupLayout::Acquire(native::ToAPI(bglRef.Detach()));
+        wgpu::BindGroupLayout bgl =
+            wgpu::BindGroupLayout::Acquire(native::ToAPI(ReturnToAPI(std::move(bglRef))));
 
         // Create pipeline layout
         wgpu::PipelineLayoutDescriptor plDesc;