From 7f53339d78070d6745841a2f46476def949cf551 Mon Sep 17 00:00:00 2001 From: Kunal Mohan Date: Tue, 11 Aug 2020 13:05:17 +0530 Subject: [PATCH] Implement GPUUncapturedErrorEvent --- Cargo.lock | 4 +- components/atoms/static_atoms.txt | 1 + components/script/dom/gpudevice.rs | 37 +++++--- .../script/dom/gpuuncapturederrorevent.rs | 84 +++++++++++++++++++ components/script/dom/mod.rs | 1 + .../webidls/GPUUncapturedErrorEvent.webidl | 22 +++++ 6 files changed, 136 insertions(+), 13 deletions(-) create mode 100644 components/script/dom/gpuuncapturederrorevent.rs create mode 100644 components/script/dom/webidls/GPUUncapturedErrorEvent.webidl diff --git a/Cargo.lock b/Cargo.lock index 098934e8a07..6211bd7f5e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6945,7 +6945,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#8057acf120f9944056a6b5de6cf326f18ae7671d" +source = "git+https://github.com/gfx-rs/wgpu#430b29d781200009ef02839e41136718ff62456a" dependencies = [ "arrayvec 0.5.1", "bitflags", @@ -6972,7 +6972,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#8057acf120f9944056a6b5de6cf326f18ae7671d" +source = "git+https://github.com/gfx-rs/wgpu#430b29d781200009ef02839e41136718ff62456a" dependencies = [ "bitflags", "serde", diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt index 81d8e510e60..bdb16e30e78 100644 --- a/components/atoms/static_atoms.txt +++ b/components/atoms/static_atoms.txt @@ -137,6 +137,7 @@ transitioncancel transitionend transitionrun transitionstart +uncapturederror unhandledrejection unload url diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index e54c0d1540a..19f6f8258d4 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -5,6 +5,8 @@ #![allow(unsafe_code)] use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::EventBinding::EventInit; +use crate::dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::{ GPUBindGroupDescriptor, GPUBindingResource, }; @@ -32,6 +34,7 @@ use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{ GPUTextureDimension, GPUTextureFormat, }; use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureViewDimension; +use crate::dom::bindings::codegen::Bindings::GPUUncapturedErrorEventBinding::GPUUncapturedErrorEventInit; use crate::dom::bindings::codegen::Bindings::GPUValidationErrorBinding::{ GPUError, GPUErrorFilter, }; @@ -57,6 +60,7 @@ use crate::dom::gpurenderpipeline::GPURenderPipeline; use crate::dom::gpusampler::GPUSampler; use crate::dom::gpushadermodule::GPUShaderModule; use crate::dom::gputexture::GPUTexture; +use crate::dom::gpuuncapturederrorevent::GPUUncapturedErrorEvent; use crate::dom::gpuvalidationerror::GPUValidationError; use crate::dom::promise::Promise; use crate::realms::InRealm; @@ -76,7 +80,7 @@ use webgpu::{self, identity::WebGPUOpResult, wgt, ErrorScopeId, WebGPU, WebGPURe #[derive(JSTraceable, MallocSizeOf)] struct ErrorScopeInfo { op_count: u64, - #[ignore_malloc_size_of = "defined in webgpu"] + #[ignore_malloc_size_of = "Because it is non-owning"] error: Option, #[ignore_malloc_size_of = "promises are hard"] promise: Option>, @@ -201,12 +205,14 @@ impl GPUDevice { if let Some(s) = scop { self.handle_error(s, err); } else { - // Fire UncapturedErrorEvent. + self.fire_uncaptured_error(err); } } self.try_remove_scope(s_id); } else { - // Fire UncapturedErrorEvent if result is Error + if let Err((err, _)) = result { + self.fire_uncaptured_error(err); + } } } @@ -228,10 +234,7 @@ impl GPUDevice { if let Some(ref promise) = err_scope.promise { if !promise.is_fulfilled() { if let Some(ref e) = err_scope.error { - match e { - GPUError::GPUValidationError(v) => promise.resolve_native(&v), - GPUError::GPUOutOfMemoryError(w) => promise.resolve_native(&w), - } + promise.resolve_native(e); } else if err_scope.op_count == 0 { promise.resolve_native(&None::); } @@ -248,6 +251,18 @@ impl GPUDevice { } } + fn fire_uncaptured_error(&self, err: GPUError) { + let ev = GPUUncapturedErrorEvent::new( + &self.global(), + DOMString::from("uncapturederror"), + &GPUUncapturedErrorEventInit { + error: err, + parent: EventInit::empty(), + }, + ); + let _ = self.eventtarget.DispatchEvent(ev.event()); + } + pub fn use_current_scope(&self) -> Option { let mut context = self.scope_context.borrow_mut(); let scope_id = context @@ -1051,10 +1066,7 @@ impl GPUDeviceMethods for GPUDevice { }; let remove = if let Some(mut err_scope) = context.error_scopes.get_mut(&scope_id) { if let Some(ref e) = err_scope.error { - match e { - GPUError::GPUValidationError(ref v) => promise.resolve_native(&v), - GPUError::GPUOutOfMemoryError(ref w) => promise.resolve_native(&w), - } + promise.resolve_native(e); } else if err_scope.op_count == 0 { promise.resolve_native(&None::); } @@ -1070,6 +1082,9 @@ impl GPUDeviceMethods for GPUDevice { } promise } + + // https://gpuweb.github.io/gpuweb/#dom-gpudevice-onuncapturederror + event_handler!(uncapturederror, GetOnuncapturederror, SetOnuncapturederror); } fn convert_address_mode(address_mode: GPUAddressMode) -> wgt::AddressMode { diff --git a/components/script/dom/gpuuncapturederrorevent.rs b/components/script/dom/gpuuncapturederrorevent.rs new file mode 100644 index 00000000000..30c9692a27d --- /dev/null +++ b/components/script/dom/gpuuncapturederrorevent.rs @@ -0,0 +1,84 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMethods; +use crate::dom::bindings::codegen::Bindings::GPUUncapturedErrorEventBinding::{ + GPUUncapturedErrorEventInit, GPUUncapturedErrorEventMethods, +}; +use crate::dom::bindings::codegen::Bindings::GPUValidationErrorBinding::GPUError; +use crate::dom::bindings::reflector::reflect_dom_object; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::event::Event; +use crate::dom::globalscope::GlobalScope; +use dom_struct::dom_struct; +use servo_atoms::Atom; + +#[dom_struct] +pub struct GPUUncapturedErrorEvent { + event: Event, + #[ignore_malloc_size_of = "Because it is non-owning"] + gpu_error: GPUError, +} + +impl GPUUncapturedErrorEvent { + fn new_inherited(init: &GPUUncapturedErrorEventInit) -> Self { + Self { + gpu_error: clone_gpu_error(&init.error), + event: Event::new_inherited(), + } + } + + pub fn new( + global: &GlobalScope, + type_: DOMString, + init: &GPUUncapturedErrorEventInit, + ) -> DomRoot { + let ev = reflect_dom_object( + Box::new(GPUUncapturedErrorEvent::new_inherited(init)), + global, + ); + ev.event.init_event( + Atom::from(type_), + init.parent.bubbles, + init.parent.cancelable, + ); + ev + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpuuncapturederrorevent-gpuuncapturederrorevent + #[allow(non_snake_case)] + pub fn Constructor( + global: &GlobalScope, + type_: DOMString, + init: &GPUUncapturedErrorEventInit, + ) -> DomRoot { + GPUUncapturedErrorEvent::new(global, type_, init) + } +} + +impl GPUUncapturedErrorEvent { + pub fn event(&self) -> &Event { + &self.event + } +} + +impl GPUUncapturedErrorEventMethods for GPUUncapturedErrorEvent { + /// https://gpuweb.github.io/gpuweb/#dom-gpuuncapturederrorevent-error + fn Error(&self) -> GPUError { + clone_gpu_error(&self.gpu_error) + } + + /// https://dom.spec.whatwg.org/#dom-event-istrusted + fn IsTrusted(&self) -> bool { + self.event.IsTrusted() + } +} + +fn clone_gpu_error(error: &GPUError) -> GPUError { + match *error { + GPUError::GPUValidationError(ref v) => GPUError::GPUValidationError(v.clone()), + GPUError::GPUOutOfMemoryError(ref w) => GPUError::GPUOutOfMemoryError(w.clone()), + } +} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index a4d27057446..9120ce7c9f4 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -349,6 +349,7 @@ pub mod gpuswapchain; pub mod gputexture; pub mod gputextureusage; pub mod gputextureview; +pub mod gpuuncapturederrorevent; pub mod gpuvalidationerror; pub mod hashchangeevent; pub mod headers; diff --git a/components/script/dom/webidls/GPUUncapturedErrorEvent.webidl b/components/script/dom/webidls/GPUUncapturedErrorEvent.webidl new file mode 100644 index 00000000000..565c72ef9be --- /dev/null +++ b/components/script/dom/webidls/GPUUncapturedErrorEvent.webidl @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// https://gpuweb.github.io/gpuweb/#gpuuncapturederrorevent +[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] +interface GPUUncapturedErrorEvent : Event { + constructor( + DOMString type, + GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict + ); + /*[SameObject]*/ readonly attribute GPUError error; +}; + +dictionary GPUUncapturedErrorEventInit : EventInit { + required GPUError error; +}; + +partial interface GPUDevice { + [Exposed=(Window, DedicatedWorker)] + attribute EventHandler onuncapturederror; +};