aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/bindings/trace.rs4
-rw-r--r--components/script/dom/create.rs2
-rw-r--r--components/script/dom/domtokenlist.rs46
-rw-r--r--components/script/dom/element.rs14
-rw-r--r--components/script/dom/event.rs2
-rw-r--r--components/script/dom/eventtarget.rs12
-rw-r--r--components/script/dom/globalscope.rs6
-rw-r--r--components/script/dom/gpubindgroup.rs58
-rw-r--r--components/script/dom/gpubuffer.rs14
-rw-r--r--components/script/dom/gpudevice.rs67
-rwxr-xr-xcomponents/script/dom/htmlbuttonelement.rs2
-rw-r--r--components/script/dom/htmlformelement.rs26
-rwxr-xr-xcomponents/script/dom/htmlinputelement.rs2
-rw-r--r--components/script/dom/identityhub.rs72
-rw-r--r--components/script/dom/mod.rs2
-rw-r--r--components/script/dom/submitevent.rs79
-rw-r--r--components/script/dom/webidls/GPUBindGroup.webidl31
-rw-r--r--components/script/dom/webidls/GPUDevice.webidl4
-rw-r--r--components/script/dom/webidls/SubmitEvent.webidl15
-rw-r--r--components/script/dom/xmlhttprequest.rs28
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) {