Bug 1809567: Propagate promise creation failures in mozilla::webgpu::Device::CreateShaderModule. r=webgpu-reviewers,webidl,smaug,saschanaz,ErichDonGubler

If creation of the `CompilationInfo` promise fails in
`mozilla::webgpu::Device::CreateShaderModule`, propagate the error
properly, rather than leaving a local `ErrorResult` unhandled.

Differential Revision: https://phabricator.services.mozilla.com/D197600
This commit is contained in:
Jim Blandy 2024-01-06 17:06:19 +00:00
parent 231b768e20
commit 5ad3692e95
6 changed files with 82 additions and 5 deletions

View File

@ -247,16 +247,17 @@ already_AddRefed<BindGroup> Device::CreateBindGroup(
}
already_AddRefed<ShaderModule> Device::CreateShaderModule(
JSContext* aCx, const dom::GPUShaderModuleDescriptor& aDesc) {
JSContext* aCx, const dom::GPUShaderModuleDescriptor& aDesc,
ErrorResult& aRv) {
Unused << aCx;
if (!mBridge->CanSend()) {
aRv.ThrowInvalidStateError("Connection to GPU process has shut down");
return nullptr;
}
ErrorResult err;
RefPtr<dom::Promise> promise = dom::Promise::Create(GetParentObject(), err);
if (NS_WARN_IF(err.Failed())) {
RefPtr<dom::Promise> promise = dom::Promise::Create(GetParentObject(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}

View File

@ -165,7 +165,8 @@ class Device final : public DOMEventTargetHelper, public SupportsWeakPtr {
const dom::GPUBindGroupDescriptor& aDesc);
MOZ_CAN_RUN_SCRIPT already_AddRefed<ShaderModule> CreateShaderModule(
JSContext* aCx, const dom::GPUShaderModuleDescriptor& aDesc);
JSContext* aCx, const dom::GPUShaderModuleDescriptor& aDesc,
ErrorResult& aRv);
already_AddRefed<ComputePipeline> CreateComputePipeline(
const dom::GPUComputePipelineDescriptor& aDesc);
already_AddRefed<RenderPipeline> CreateRenderPipeline(

View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html class="reftest-wait">
<body>
<script>
// The bulk of the test is wrapped in an async function because
// the WebGPU API returns promises of adapters and devices,
// which we would like to conveniently await.
async function orphan_webgpu_device() {
// Create an iframe in the same origin as this code.
let iframe = document.createElement('iframe');
document.body.appendChild(iframe);
// Define a function in that iframe that creates a WebGPU
// `GPUDevice`.
let script = iframe.contentDocument.createElement('script');
script.type = 'text/javascript';
script.text = `
async function create_device() {
// WebGPU is not yet available in beta or release.
if (!navigator.gpu) {
return null;
}
let adapter = await navigator.gpu.requestAdapter({ });
// Not all GPUs are capable of supporting WebGPU.
if (!adapter) {
return null;
}
return await adapter.requestDevice({ });
}
`;
iframe.contentDocument.body.appendChild(script);
// Call that function to create a `GPUDevice` in the iframe.
let device = await iframe.contentWindow.create_device();
// If we can't run WebGPU in this browser, then we can't reach the crash.
if (device) {
// Remove the iframe from our document. This closes its window.
iframe.remove();
try {
// When a Web API JavaScript object has had its parent window
// closed, C++ implementations of its WebIDL methods become unable
// to create JavaScript objects as usual: calling
// `EventTarget::GetParentObject` returns `nullptr`.
//
// Since we removed `iframe` from this document, the following
// call will fail trying to create a `Promise` of the module's
// `GPUCompilationInfo`.
device.createShaderModule({ code: '' });
} catch (error) {
// Eating errors indiscriminately wastes later developers' time.
if (error.name != "NS_ERROR_UNEXPECTED") {
throw error;
}
}
}
}
orphan_webgpu_device()
.catch((error) => {
console.log(error);
})
.finally(() => {
// End the crashtest.
document.documentElement.removeAttribute("class");
});
</script>
</body>
</html>

View File

@ -0,0 +1 @@
load 1809567.html

View File

@ -157,6 +157,7 @@ interface GPUDevice : EventTarget {
GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
[Throws]
GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);

View File

@ -33,6 +33,7 @@ include ../../dom/smil/crashtests/crashtests.list
include ../../dom/streams/crashtests/crashtests.list
include ../../dom/svg/crashtests/crashtests.list
include ../../dom/vr/test/crashtests/crashtests.list
include ../../dom/webgpu/crashtests/crashtests.list
include ../../dom/workers/test/crashtests/crashtests.list
include ../../dom/xhr/tests/crashtests/crashtests.list
include ../../dom/xml/crashtests/crashtests.list