diff options
Diffstat (limited to 'components/script/dom')
20 files changed, 408 insertions, 78 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index ffd4a4952d0..471d890c80b 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -152,7 +152,8 @@ use tendril::{StrTendril, TendrilSink}; use time::{Duration, Timespec, Tm}; use uuid::Uuid; use webgpu::{ - WebGPU, WebGPUAdapter, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice, WebGPUPipelineLayout, + WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice, + WebGPUPipelineLayout, }; use webrender_api::{DocumentId, ImageKey}; use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; @@ -532,6 +533,7 @@ unsafe_no_jsmanaged_fields!(WebGPU); unsafe_no_jsmanaged_fields!(WebGPUAdapter); unsafe_no_jsmanaged_fields!(WebGPUDevice); unsafe_no_jsmanaged_fields!(WebGPUBuffer); +unsafe_no_jsmanaged_fields!(WebGPUBindGroup); unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout); unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout); unsafe_no_jsmanaged_fields!(GPUBufferState); diff --git a/components/script/dom/create.rs b/components/script/dom/create.rs index d67550ee47f..f68a680483d 100644 --- a/components/script/dom/create.rs +++ b/components/script/dom/create.rs @@ -200,6 +200,8 @@ fn create_html_element( None => { if is_valid_custom_element_name(&*name.local) { result.set_custom_element_state(CustomElementState::Undefined); + } else { + result.set_custom_element_state(CustomElementState::Uncustomized); } }, }; diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index b870ab4f16d..7f56f58c502 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -52,6 +52,17 @@ impl DOMTokenList { slice => Ok(Atom::from(slice)), } } + + // https://dom.spec.whatwg.org/#concept-dtl-update + fn perform_update_steps(&self, atoms: Vec<Atom>) { + // Step 1 + if !self.element.has_attribute(&self.local_name) && atoms.len() == 0 { + return; + } + // step 2 + self.element + .set_atomic_tokenlist_attribute(&self.local_name, atoms) + } } // https://dom.spec.whatwg.org/#domtokenlist @@ -93,8 +104,7 @@ impl DOMTokenListMethods for DOMTokenList { atoms.push(token); } } - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); Ok(()) } @@ -108,8 +118,7 @@ impl DOMTokenListMethods for DOMTokenList { .position(|atom| *atom == token) .map(|index| atoms.remove(index)); } - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); Ok(()) } @@ -122,8 +131,7 @@ impl DOMTokenListMethods for DOMTokenList { Some(true) => Ok(true), _ => { atoms.remove(index); - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); Ok(false) }, }, @@ -131,8 +139,7 @@ impl DOMTokenListMethods for DOMTokenList { Some(false) => Ok(false), _ => { atoms.push(token); - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); Ok(true) }, }, @@ -166,14 +173,27 @@ impl DOMTokenListMethods for DOMTokenList { let mut atoms = self.element.get_tokenlist_attribute(&self.local_name); let mut result = false; if let Some(pos) = atoms.iter().position(|atom| *atom == token) { - if !atoms.contains(&new_token) { - atoms[pos] = new_token; + if let Some(redundant_pos) = atoms.iter().position(|atom| *atom == new_token) { + if redundant_pos > pos { + // The replacement is already in the list, later, + // so we perform the replacement and remove the + // later copy. + atoms[pos] = new_token; + atoms.remove(redundant_pos); + } else if redundant_pos < pos { + // The replacement is already in the list, earlier, + // so we remove the index where we'd be putting the + // later copy. + atoms.remove(pos); + } + // else we are replacing the token with itself, nothing to change } else { - atoms.remove(pos); + // The replacement is not in the list already + atoms[pos] = new_token; } + // Step 5. - self.element - .set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.perform_update_steps(atoms); result = true; } Ok(result) diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 29bdaf2f3bf..c26e492d544 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -324,14 +324,23 @@ impl Element { } pub fn set_custom_element_state(&self, state: CustomElementState) { - self.ensure_rare_data().custom_element_state = state; + // no need to inflate rare data for uncustomized + if state != CustomElementState::Uncustomized || self.rare_data().is_some() { + self.ensure_rare_data().custom_element_state = state; + } + // https://dom.spec.whatwg.org/#concept-element-defined + let in_defined_state = match state { + CustomElementState::Uncustomized | CustomElementState::Custom => true, + _ => false, + }; + self.set_state(ElementState::IN_DEFINED_STATE, in_defined_state) } pub fn get_custom_element_state(&self) -> CustomElementState { if let Some(rare_data) = self.rare_data().as_ref() { return rare_data.custom_element_state; } - CustomElementState::Undefined + CustomElementState::Uncustomized } pub fn set_custom_element_definition(&self, definition: Rc<CustomElementDefinition>) { @@ -3039,6 +3048,7 @@ impl<'a> SelectorsElement for DomRoot<Element> { NonTSPseudoClass::Focus | NonTSPseudoClass::Fullscreen | NonTSPseudoClass::Hover | + NonTSPseudoClass::Defined | NonTSPseudoClass::Enabled | NonTSPseudoClass::Disabled | NonTSPseudoClass::Checked | diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index e8e7ad7251c..561022f0f3a 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -419,7 +419,7 @@ pub enum EventPhase { /// helps us to prevent such events from being [sent to the constellation][msg] where it will be /// handled once again for page scrolling (which is definitely not what we'd want). /// -/// [msg]: https://doc.servo.org/script_traits/enum.ConstellationMsg.html#variant.KeyEvent +/// [msg]: https://doc.servo.org/compositing/enum.ConstellationMsg.html#variant.KeyEvent /// #[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] pub enum EventDefault { diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs index 5de65567595..1d80781a2fb 100644 --- a/components/script/dom/eventtarget.rs +++ b/components/script/dom/eventtarget.rs @@ -404,9 +404,15 @@ impl EventTarget { }); match idx { - Some(idx) => { - entries[idx].listener = - EventListenerType::Inline(listener.unwrap_or(InlineEventListener::Null)); + Some(idx) => match listener { + // Replace if there's something to replace with, + // but remove entirely if there isn't. + Some(listener) => { + entries[idx].listener = EventListenerType::Inline(listener); + }, + None => { + entries.remove(idx); + }, }, None => { if let Some(listener) = listener { diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index f8427ffd083..aa0bfee1b79 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -98,7 +98,7 @@ use std::sync::Arc; use time::{get_time, Timespec}; use uuid::Uuid; use webgpu::wgpu::{ - id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, + id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, Backend, }; @@ -2105,6 +2105,10 @@ impl GlobalScope { self.gpu_id_hub.borrow_mut().create_adapter_ids() } + pub fn wgpu_create_bind_group_id(&self, backend: Backend) -> BindGroupId { + self.gpu_id_hub.borrow_mut().create_bind_group_id(backend) + } + pub fn wgpu_create_bind_group_layout_id(&self, backend: Backend) -> BindGroupLayoutId { self.gpu_id_hub .borrow_mut() diff --git a/components/script/dom/gpubindgroup.rs b/components/script/dom/gpubindgroup.rs new file mode 100644 index 00000000000..c14ca7a23b5 --- /dev/null +++ b/components/script/dom/gpubindgroup.rs @@ -0,0 +1,58 @@ +/* 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::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::{ + GPUBindGroupBinding, GPUBindGroupMethods, +}; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::globalscope::GlobalScope; +use dom_struct::dom_struct; +use std::cell::Cell; +use webgpu::WebGPUBindGroup; + +#[dom_struct] +pub struct GPUBindGroup { + reflector_: Reflector, + label: DomRefCell<Option<DOMString>>, + bind_group: WebGPUBindGroup, + valid: Cell<bool>, +} + +impl GPUBindGroup { + fn new_inherited(bind_group: WebGPUBindGroup, valid: bool) -> GPUBindGroup { + Self { + reflector_: Reflector::new(), + label: DomRefCell::new(None), + bind_group, + valid: Cell::new(valid), + } + } + + pub fn new( + global: &GlobalScope, + bind_group: WebGPUBindGroup, + valid: bool, + ) -> DomRoot<GPUBindGroup> { + reflect_dom_object( + Box::new(GPUBindGroup::new_inherited(bind_group, valid)), + global, + GPUBindGroupBinding::Wrap, + ) + } +} + +impl GPUBindGroupMethods for GPUBindGroup { + /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label + fn GetLabel(&self) -> Option<DOMString> { + self.label.borrow().clone() + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label + fn SetLabel(&self, value: Option<DOMString>) { + *self.label.borrow_mut() = value; + } +} diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs index 160ef6cf79c..8cc9bc52249 100644 --- a/components/script/dom/gpubuffer.rs +++ b/components/script/dom/gpubuffer.rs @@ -79,6 +79,20 @@ impl GPUBuffer { } } +impl GPUBuffer { + pub fn id(&self) -> WebGPUBuffer { + self.buffer + } + + pub fn size(&self) -> GPUBufferSize { + self.size + } + + pub fn usage(&self) -> u32 { + self.usage + } +} + impl Drop for GPUBuffer { fn drop(&mut self) { self.Destroy() diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index de3efec8117..4c576c37e8b 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -6,6 +6,7 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits; +use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::GPUBindGroupDescriptor; use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{ GPUBindGroupLayoutBindings, GPUBindGroupLayoutDescriptor, GPUBindingType, }; @@ -18,6 +19,7 @@ use crate::dom::bindings::str::DOMString; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::gpuadapter::GPUAdapter; +use crate::dom::gpubindgroup::GPUBindGroup; use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState}; use crate::dom::gpupipelinelayout::GPUPipelineLayout; @@ -29,7 +31,10 @@ use js::jsval::{JSVal, ObjectValue}; use js::typedarray::{ArrayBuffer, CreateWith}; use std::collections::{HashMap, HashSet}; use std::ptr::{self, NonNull}; -use webgpu::wgpu::binding_model::{BindGroupLayoutBinding, BindingType, ShaderStage}; +use webgpu::wgpu::binding_model::{ + BindGroupBinding, BindGroupLayoutBinding, BindingResource, BindingType, BufferBinding, + ShaderStage, +}; use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage}; use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest}; @@ -463,4 +468,64 @@ impl GPUDeviceMethods for GPUDevice { let pipeline_layout = receiver.recv().unwrap(); GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid) } + + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup + fn CreateBindGroup(&self, descriptor: &GPUBindGroupDescriptor) -> DomRoot<GPUBindGroup> { + let alignment: u64 = 256; + let mut valid = descriptor.layout.bindings().len() == descriptor.bindings.len(); + + valid &= descriptor.bindings.iter().all(|bind| { + let buffer_size = bind.resource.buffer.size(); + let resource_size = bind.resource.size.unwrap_or(buffer_size); + let length = bind.resource.offset.checked_add(resource_size); + let usage = BufferUsage::from_bits(bind.resource.buffer.usage()).unwrap(); + + length.is_some() && + buffer_size >= length.unwrap() && // check buffer OOB + bind.resource.offset % alignment == 0 && // check alignment + bind.resource.offset < buffer_size && // on Vulkan offset must be less than size of buffer + descriptor.layout.bindings().iter().any(|layout_bind| { + let ty = match layout_bind.type_ { + GPUBindingType::Storage_buffer => BufferUsage::STORAGE, + // GPUBindingType::Readonly_storage_buffer => BufferUsage::STORAGE_READ, + GPUBindingType::Uniform_buffer => BufferUsage::UNIFORM, + _ => unimplemented!(), + }; + // binding must be present in layout + layout_bind.binding == bind.binding && + // binding must contain one buffer of its type + usage.contains(ty) + }) + }); + + let bindings = descriptor + .bindings + .iter() + .map(|bind| BindGroupBinding { + binding: bind.binding, + resource: BindingResource::Buffer(BufferBinding { + buffer: bind.resource.buffer.id().0, + offset: bind.resource.offset, + size: bind.resource.size.unwrap_or(bind.resource.buffer.size()), + }), + }) + .collect::<Vec<_>>(); + let (sender, receiver) = ipc::channel().unwrap(); + let id = self + .global() + .wgpu_create_bind_group_id(self.device.0.backend()); + self.channel + .0 + .send(WebGPURequest::CreateBindGroup( + sender, + self.device, + id, + descriptor.layout.id(), + bindings, + )) + .expect("Failed to create WebGPU PipelineLayout"); + + let bind_group = receiver.recv().unwrap(); + GPUBindGroup::new(&self.global(), bind_group, valid) + } } diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs index b7c7da1e9bf..49541a2d4a0 100755 --- a/components/script/dom/htmlbuttonelement.rs +++ b/components/script/dom/htmlbuttonelement.rs @@ -307,7 +307,7 @@ impl Activatable for HTMLButtonElement { if let Some(owner) = self.form_owner() { owner.submit( SubmittedFrom::NotFromForm, - FormSubmitter::ButtonElement(self.clone()), + FormSubmitter::ButtonElement(self), ); } }, diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index ebbe1d49615..bf59dc0280b 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -48,6 +48,7 @@ use crate::dom::node::{Node, NodeFlags, ShadowIncluding}; use crate::dom::node::{UnbindContext, VecPreOrderInsertionHelper}; use crate::dom::nodelist::{NodeList, RadioListMode}; use crate::dom::radionodelist::RadioNodeList; +use crate::dom::submitevent::SubmitEvent; use crate::dom::validitystate::ValidationFlags; use crate::dom::virtualmethods::VirtualMethods; use crate::dom::window::Window; @@ -604,10 +605,29 @@ impl HTMLFormElement { } } // Step 7 + // spec calls this "submitterButton" but it doesn't have to be a button, + // just not be the form itself + let submitter_button = match submitter { + FormSubmitter::FormElement(f) => { + if f == self { + None + } else { + Some(f.upcast::<HTMLElement>()) + } + }, + FormSubmitter::InputElement(i) => Some(i.upcast::<HTMLElement>()), + FormSubmitter::ButtonElement(b) => Some(b.upcast::<HTMLElement>()), + }; if submit_method_flag == SubmittedFrom::NotFromForm { - let event = self - .upcast::<EventTarget>() - .fire_bubbling_cancelable_event(atom!("submit")); + let event = SubmitEvent::new( + &self.global(), + atom!("submit"), + true, + true, + submitter_button.map(|s| DomRoot::from_ref(s)), + ); + let event = event.upcast::<Event>(); + event.fire(self.upcast::<EventTarget>()); if event.DefaultPrevented() { return; } diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index a8587b58ed0..88b2e688d65 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -2470,7 +2470,7 @@ impl Activatable for HTMLInputElement { self.form_owner().map(|o| { o.submit( SubmittedFrom::NotFromForm, - FormSubmitter::InputElement(self.clone()), + FormSubmitter::InputElement(self), ) }); }, diff --git a/components/script/dom/identityhub.rs b/components/script/dom/identityhub.rs index 91ead1acf0a..311428893c0 100644 --- a/components/script/dom/identityhub.rs +++ b/components/script/dom/identityhub.rs @@ -5,7 +5,7 @@ use smallvec::SmallVec; use webgpu::wgpu::{ hub::IdentityManager, - id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, + id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, Backend, }; @@ -14,6 +14,7 @@ pub struct IdentityHub { adapters: IdentityManager, devices: IdentityManager, buffers: IdentityManager, + bind_groups: IdentityManager, bind_group_layouts: IdentityManager, pipeline_layouts: IdentityManager, backend: Backend, @@ -25,6 +26,7 @@ impl IdentityHub { adapters: IdentityManager::default(), devices: IdentityManager::default(), buffers: IdentityManager::default(), + bind_groups: IdentityManager::default(), bind_group_layouts: IdentityManager::default(), pipeline_layouts: IdentityManager::default(), backend, @@ -43,6 +45,10 @@ impl IdentityHub { self.buffers.alloc(self.backend) } + fn create_bind_group_id(&mut self) -> BindGroupId { + self.bind_groups.alloc(self.backend) + } + fn create_bind_group_layout_id(&mut self) -> BindGroupLayoutId { self.bind_group_layouts.alloc(self.backend) } @@ -82,6 +88,20 @@ impl Identities { } } + fn select(&mut self, backend: Backend) -> &mut IdentityHub { + match backend { + #[cfg(any(target_os = "linux", target_os = "windows"))] + Backend::Vulkan => &mut self.vk_hub, + #[cfg(target_os = "windows")] + Backend::Dx12 => &mut self.dx12_hub, + #[cfg(target_os = "windows")] + Backend::Dx11 => &mut self.dx11_hub, + #[cfg(any(target_os = "ios", target_os = "macos"))] + Backend::Metal => &mut self.metal_hub, + _ => &mut self.dummy_hub, + } + } + fn hubs(&mut self) -> Vec<&mut IdentityHub> { vec![ #[cfg(any(target_os = "linux", target_os = "windows"))] @@ -97,17 +117,7 @@ impl Identities { } pub fn create_device_id(&mut self, backend: Backend) -> DeviceId { - match backend { - #[cfg(any(target_os = "linux", target_os = "windows"))] - Backend::Vulkan => self.vk_hub.create_device_id(), - #[cfg(target_os = "windows")] - Backend::Dx12 => self.dx12_hub.create_device_id(), - #[cfg(target_os = "windows")] - Backend::Dx11 => self.dx11_hub.create_device_id(), - #[cfg(any(target_os = "ios", target_os = "macos"))] - Backend::Metal => self.metal_hub.create_device_id(), - _ => self.dummy_hub.create_device_id(), - } + self.select(backend).create_device_id() } pub fn create_adapter_ids(&mut self) -> SmallVec<[AdapterId; 4]> { @@ -119,44 +129,28 @@ impl Identities { } pub fn create_buffer_id(&mut self, backend: Backend) -> BufferId { + self.select(backend).create_buffer_id() + } + + pub fn create_bind_group_id(&mut self, backend: Backend) -> BindGroupId { match backend { #[cfg(any(target_os = "linux", target_os = "windows"))] - Backend::Vulkan => self.vk_hub.create_buffer_id(), + Backend::Vulkan => self.vk_hub.create_bind_group_id(), #[cfg(target_os = "windows")] - Backend::Dx12 => self.dx12_hub.create_buffer_id(), + Backend::Dx12 => self.dx12_hub.create_bind_group_id(), #[cfg(target_os = "windows")] - Backend::Dx11 => self.dx11_hub.create_buffer_id(), + Backend::Dx11 => self.dx11_hub.create_bind_group_id(), #[cfg(any(target_os = "ios", target_os = "macos"))] - Backend::Metal => self.metal_hub.create_buffer_id(), - _ => self.dummy_hub.create_buffer_id(), + Backend::Metal => self.metal_hub.create_bind_group_id(), + _ => self.dummy_hub.create_bind_group_id(), } } pub fn create_bind_group_layout_id(&mut self, backend: Backend) -> BindGroupLayoutId { - match backend { - #[cfg(any(target_os = "linux", target_os = "windows"))] - Backend::Vulkan => self.vk_hub.create_bind_group_layout_id(), - #[cfg(target_os = "windows")] - Backend::Dx12 => self.dx12_hub.create_bind_group_layout_id(), - #[cfg(target_os = "windows")] - Backend::Dx11 => self.dx11_hub.create_bind_group_layout_id(), - #[cfg(any(target_os = "ios", target_os = "macos"))] - Backend::Metal => self.metal_hub.create_bind_group_layout_id(), - _ => self.dummy_hub.create_bind_group_layout_id(), - } + self.select(backend).create_bind_group_layout_id() } pub fn create_pipeline_layout_id(&mut self, backend: Backend) -> PipelineLayoutId { - match backend { - #[cfg(any(target_os = "linux", target_os = "windows"))] - Backend::Vulkan => self.vk_hub.create_pipeline_layout_id(), - #[cfg(target_os = "windows")] - Backend::Dx12 => self.dx12_hub.create_pipeline_layout_id(), - #[cfg(target_os = "windows")] - Backend::Dx11 => self.dx11_hub.create_pipeline_layout_id(), - #[cfg(any(target_os = "ios", target_os = "macos"))] - Backend::Metal => self.metal_hub.create_pipeline_layout_id(), - _ => self.dummy_hub.create_pipeline_layout_id(), - } + self.select(backend).create_pipeline_layout_id() } } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 2550eeda007..c1a1ab72354 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -318,6 +318,7 @@ pub mod gamepadlist; pub mod globalscope; pub mod gpu; pub mod gpuadapter; +pub mod gpubindgroup; pub mod gpubindgrouplayout; pub mod gpubuffer; pub mod gpubufferusage; @@ -483,6 +484,7 @@ pub mod storageevent; pub mod stylepropertymapreadonly; pub mod stylesheet; pub mod stylesheetlist; +pub mod submitevent; pub mod svgelement; pub mod svggraphicselement; pub mod svgsvgelement; diff --git a/components/script/dom/submitevent.rs b/components/script/dom/submitevent.rs new file mode 100644 index 00000000000..17f8e7fd003 --- /dev/null +++ b/components/script/dom/submitevent.rs @@ -0,0 +1,79 @@ +/* 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::EventMethods; +use crate::dom::bindings::codegen::Bindings::SubmitEventBinding; +use crate::dom::bindings::codegen::Bindings::SubmitEventBinding::SubmitEventMethods; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::event::Event; +use crate::dom::globalscope::GlobalScope; +use crate::dom::htmlelement::HTMLElement; +use crate::dom::window::Window; +use dom_struct::dom_struct; +use servo_atoms::Atom; + +#[dom_struct] +#[allow(non_snake_case)] +pub struct SubmitEvent { + event: Event, + submitter: Option<DomRoot<HTMLElement>>, +} + +impl SubmitEvent { + fn new_inherited(submitter: Option<DomRoot<HTMLElement>>) -> SubmitEvent { + SubmitEvent { + event: Event::new_inherited(), + submitter: submitter, + } + } + + pub fn new( + global: &GlobalScope, + type_: Atom, + bubbles: bool, + cancelable: bool, + submitter: Option<DomRoot<HTMLElement>>, + ) -> DomRoot<SubmitEvent> { + let ev = reflect_dom_object( + Box::new(SubmitEvent::new_inherited(submitter)), + global, + SubmitEventBinding::Wrap, + ); + { + let event = ev.upcast::<Event>(); + event.init_event(type_, bubbles, cancelable); + } + ev + } + + #[allow(non_snake_case)] + pub fn Constructor( + window: &Window, + type_: DOMString, + init: &SubmitEventBinding::SubmitEventInit, + ) -> DomRoot<SubmitEvent> { + SubmitEvent::new( + &window.global(), + Atom::from(type_), + init.parent.bubbles, + init.parent.cancelable, + init.submitter.as_ref().map(|s| DomRoot::from_ref(&**s)), + ) + } +} + +impl SubmitEventMethods for SubmitEvent { + /// <https://dom.spec.whatwg.org/#dom-event-istrusted> + fn IsTrusted(&self) -> bool { + self.event.IsTrusted() + } + + /// https://html.spec.whatwg.org/multipage/#dom-submitevent-submitter + fn GetSubmitter(&self) -> Option<DomRoot<HTMLElement>> { + self.submitter.as_ref().map(|s| DomRoot::from_ref(&**s)) + } +} diff --git a/components/script/dom/webidls/GPUBindGroup.webidl b/components/script/dom/webidls/GPUBindGroup.webidl new file mode 100644 index 00000000000..537fda29a63 --- /dev/null +++ b/components/script/dom/webidls/GPUBindGroup.webidl @@ -0,0 +1,31 @@ +/* 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/#gpubindgrouplayout +[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"] +interface GPUBindGroup { +}; +GPUBindGroup includes GPUObjectBase; + +dictionary GPUBindGroupDescriptor : GPUObjectDescriptorBase { + required GPUBindGroupLayout layout; + required sequence<GPUBindGroupBindings> bindings; +}; + +typedef /*(GPUSampler or GPUTextureView or*/ GPUBufferBindings/*)*/ GPUBindingResource; + +// Note: Servo codegen doesn't like the name `GPUBindGroupBinding` because it's already occupied +// dictionary GPUBindGroupBinding { +dictionary GPUBindGroupBindings { + required unsigned long binding; + required GPUBindingResource resource; +}; + +// Note: Servo codegen doesn't like the name `GPUBufferBinding` because it's already occupied +// dictionary GPUBufferBinding { +dictionary GPUBufferBindings { + required GPUBuffer buffer; + GPUBufferSize offset = 0; + GPUBufferSize size; +}; diff --git a/components/script/dom/webidls/GPUDevice.webidl b/components/script/dom/webidls/GPUDevice.webidl index 85e8a3ea633..1966c9b1e92 100644 --- a/components/script/dom/webidls/GPUDevice.webidl +++ b/components/script/dom/webidls/GPUDevice.webidl @@ -17,9 +17,9 @@ interface GPUDevice : EventTarget { GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor); GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor); - /*GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor); + GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor); - GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); + /*GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor); GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor); diff --git a/components/script/dom/webidls/SubmitEvent.webidl b/components/script/dom/webidls/SubmitEvent.webidl new file mode 100644 index 00000000000..f5b2c49257d --- /dev/null +++ b/components/script/dom/webidls/SubmitEvent.webidl @@ -0,0 +1,15 @@ +/* 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://html.spec.whatwg.org/multipage/#submitevent +[Exposed=Window] +interface SubmitEvent : Event { + constructor(DOMString typeArg, optional SubmitEventInit eventInitDict = {}); + + readonly attribute HTMLElement? submitter; +}; + +dictionary SubmitEventInit : EventInit { + HTMLElement? submitter = null; +}; diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 08b37c946c5..6c531e5b4d6 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -618,7 +618,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest { } // Substep 2 if !self.upload_complete.get() { - self.dispatch_upload_progress_event(atom!("loadstart"), Some(0)); + self.dispatch_upload_progress_event(atom!("loadstart"), Ok(Some(0))); if self.generation_id.get() != gen_id { return Ok(()); } @@ -1062,11 +1062,11 @@ impl XMLHttpRequest { self.upload_complete.set(true); // Substeps 2-4 if !self.sync.get() { - self.dispatch_upload_progress_event(atom!("progress"), None); + self.dispatch_upload_progress_event(atom!("progress"), Ok(None)); return_if_fetch_was_terminated!(); - self.dispatch_upload_progress_event(atom!("load"), None); + self.dispatch_upload_progress_event(atom!("load"), Ok(None)); return_if_fetch_was_terminated!(); - self.dispatch_upload_progress_event(atom!("loadend"), None); + self.dispatch_upload_progress_event(atom!("loadend"), Ok(None)); return_if_fetch_was_terminated!(); } // Part of step 13, send() (processing response) @@ -1164,9 +1164,9 @@ impl XMLHttpRequest { let upload_complete = &self.upload_complete; if !upload_complete.get() { upload_complete.set(true); - self.dispatch_upload_progress_event(Atom::from(errormsg), None); + self.dispatch_upload_progress_event(Atom::from(errormsg), Err(())); return_if_fetch_was_terminated!(); - self.dispatch_upload_progress_event(atom!("loadend"), None); + self.dispatch_upload_progress_event(atom!("loadend"), Err(())); return_if_fetch_was_terminated!(); } self.dispatch_response_progress_event(Atom::from(errormsg)); @@ -1210,11 +1210,19 @@ impl XMLHttpRequest { progressevent.upcast::<Event>().fire(target); } - fn dispatch_upload_progress_event(&self, type_: Atom, partial_load: Option<u64>) { - // If partial_load is None, loading has completed and we can just use the value from the request body + fn dispatch_upload_progress_event(&self, type_: Atom, partial_load: Result<Option<u64>, ()>) { + // If partial_load is Ok(None), loading has completed and we can just use the value from the request body + // If an error occured, we pass 0 for both loaded and total - let total = self.request_body_len.get() as u64; - self.dispatch_progress_event(true, type_, partial_load.unwrap_or(total), Some(total)); + let request_body_len = self.request_body_len.get() as u64; + let (loaded, total) = match partial_load { + Ok(l) => match l { + Some(loaded) => (loaded, Some(request_body_len)), + None => (request_body_len, Some(request_body_len)), + }, + Err(()) => (0, None), + }; + self.dispatch_progress_event(true, type_, loaded, total); } fn dispatch_response_progress_event(&self, type_: Atom) { |