diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/attr.rs | 10 | ||||
-rw-r--r-- | components/script/dom/create.rs | 2 | ||||
-rw-r--r-- | components/script/dom/element.rs | 19 | ||||
-rw-r--r-- | components/script/dom/htmliframeelement.rs | 26 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/node.rs | 3 | ||||
-rw-r--r-- | components/script/dom/svgelement.rs | 3 | ||||
-rw-r--r-- | components/script/dom/svgimageelement.rs | 96 | ||||
-rw-r--r-- | components/script/dom/virtualmethods.rs | 4 |
9 files changed, 155 insertions, 9 deletions
diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index 52d0ca7e20c..9f1520bd085 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -8,7 +8,7 @@ use std::mem; use devtools_traits::AttrInfo; use dom_struct::dom_struct; -use html5ever::{LocalName, Namespace, Prefix, ns}; +use html5ever::{LocalName, Namespace, Prefix, local_name, ns}; use style::attr::{AttrIdentifier, AttrValue}; use style::values::GenericAtomIdent; use stylo_atoms::Atom; @@ -179,7 +179,7 @@ impl Attr { assert_eq!(Some(owner), self.owner().as_deref()); owner.will_mutate_attr(self); self.swap_value(&mut value); - if *self.namespace() == ns!() { + if is_relevant_attribute(self.namespace(), self.local_name()) { vtable_for(owner.upcast()).attribute_mutated( self, AttributeMutation::Set(Some(&value)), @@ -283,3 +283,9 @@ impl<'dom> AttrHelpersForLayout<'dom> for LayoutDom<'dom, Attr> { &self.unsafe_get().identifier.namespace.0 } } + +/// A helper function to check if attribute is relevant. +pub(crate) fn is_relevant_attribute(namespace: &Namespace, local_name: &LocalName) -> bool { + // <https://svgwg.org/svg2-draft/linking.html#XLinkHrefAttribute> + namespace == &ns!() || (namespace == &ns!(xlink) && local_name == &local_name!("href")) +} diff --git a/components/script/dom/create.rs b/components/script/dom/create.rs index 5722dc4f6ac..2e7c4cf8def 100644 --- a/components/script/dom/create.rs +++ b/components/script/dom/create.rs @@ -85,6 +85,7 @@ use crate::dom::htmlulistelement::HTMLUListElement; use crate::dom::htmlunknownelement::HTMLUnknownElement; use crate::dom::htmlvideoelement::HTMLVideoElement; use crate::dom::svgelement::SVGElement; +use crate::dom::svgimageelement::SVGImageElement; use crate::dom::svgsvgelement::SVGSVGElement; use crate::realms::{InRealm, enter_realm}; use crate::script_runtime::CanGc; @@ -114,6 +115,7 @@ fn create_svg_element( } match name.local { + local_name!("image") => make!(SVGImageElement), local_name!("svg") => make!(SVGSVGElement), _ => make!(SVGElement), } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 4f1b957c12c..cb120f0b174 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -65,7 +65,7 @@ use xml5ever::serialize::TraversalScope::{ use crate::conversions::Convert; use crate::dom::activation::Activatable; -use crate::dom::attr::{Attr, AttrHelpersForLayout}; +use crate::dom::attr::{Attr, AttrHelpersForLayout, is_relevant_attribute}; use crate::dom::bindings::cell::{DomRefCell, Ref, RefMut, ref_filter_map}; use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; @@ -1705,7 +1705,7 @@ impl Element { assert!(attr.GetOwnerElement().as_deref() == Some(self)); self.will_mutate_attr(attr); self.attrs.borrow_mut().push(Dom::from_ref(attr)); - if attr.namespace() == &ns!() { + if is_relevant_attribute(attr.namespace(), attr.local_name()) { vtable_for(self.upcast()).attribute_mutated(attr, AttributeMutation::Set(None), can_gc); } } @@ -1847,7 +1847,7 @@ impl Element { local_name: &LocalName, value: DOMString, ) -> AttrValue { - if *namespace == ns!() { + if is_relevant_attribute(namespace, local_name) { vtable_for(self.upcast()).parse_plain_attribute(local_name, value) } else { AttrValue::String(value.into()) @@ -1902,7 +1902,7 @@ impl Element { self.attrs.borrow_mut().remove(idx); attr.set_owner(None); - if attr.namespace() == &ns!() { + if is_relevant_attribute(attr.namespace(), attr.local_name()) { vtable_for(self.upcast()).attribute_mutated( &attr, AttributeMutation::Removed, @@ -1996,6 +1996,15 @@ impl Element { .unwrap_or_else(|_| TrustedScriptURLOrUSVString::USVString(USVString(value.to_owned()))) } + pub(crate) fn get_trusted_html_attribute(&self, local_name: &LocalName) -> TrustedHTMLOrString { + assert_eq!(*local_name, local_name.to_ascii_lowercase()); + let value = match self.get_attribute(&ns!(), local_name) { + Some(attr) => (&**attr.value()).into(), + None => "".into(), + }; + TrustedHTMLOrString::String(value) + } + pub(crate) fn get_string_attribute(&self, local_name: &LocalName) -> DOMString { match self.get_attribute(&ns!(), local_name) { Some(x) => x.Value(), @@ -2722,7 +2731,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element { attr.set_owner(Some(self)); self.attrs.borrow_mut()[position] = Dom::from_ref(attr); old_attr.set_owner(None); - if attr.namespace() == &ns!() { + if is_relevant_attribute(attr.namespace(), attr.local_name()) { vtable.attribute_mutated( attr, AttributeMutation::Set(Some(&old_attr.value())), diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 0fbff86e44a..18116eee8ae 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -27,6 +27,8 @@ use crate::dom::attr::Attr; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods; +use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrString; +use crate::dom::bindings::error::Fallible; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::DomGlobal; use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom}; @@ -40,6 +42,7 @@ use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlelement::HTMLElement; use crate::dom::node::{Node, NodeDamage, NodeTraits, UnbindContext}; +use crate::dom::trustedhtml::TrustedHTML; use crate::dom::virtualmethods::VirtualMethods; use crate::dom::windowproxy::WindowProxy; use crate::script_runtime::CanGc; @@ -595,10 +598,29 @@ impl HTMLIFrameElementMethods<crate::DomTypeHolder> for HTMLIFrameElement { make_url_setter!(SetSrc, "src"); // https://html.spec.whatwg.org/multipage/#dom-iframe-srcdoc - make_getter!(Srcdoc, "srcdoc"); + fn Srcdoc(&self) -> TrustedHTMLOrString { + let element = self.upcast::<Element>(); + element.get_trusted_html_attribute(&local_name!("srcdoc")) + } // https://html.spec.whatwg.org/multipage/#dom-iframe-srcdoc - make_setter!(SetSrcdoc, "srcdoc"); + fn SetSrcdoc(&self, value: TrustedHTMLOrString, can_gc: CanGc) -> Fallible<()> { + // Step 1: Let compliantString be the result of invoking the + // Get Trusted Type compliant string algorithm with TrustedHTML, + // this's relevant global object, the given value, "HTMLIFrameElement srcdoc", and "script". + let element = self.upcast::<Element>(); + let local_name = &local_name!("srcdoc"); + let value = TrustedHTML::get_trusted_script_compliant_string( + &element.owner_global(), + value, + "HTMLIFrameElement", + local_name, + can_gc, + )?; + // Step 2: Set an attribute value given this, srcdoc's local name, and compliantString. + element.set_attribute(local_name, AttrValue::String(value), can_gc); + Ok(()) + } // https://html.spec.whatwg.org/multipage/#dom-iframe-sandbox fn Sandbox(&self, can_gc: CanGc) -> DomRoot<DOMTokenList> { diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 1622cf57b79..91a4e1b1359 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -547,6 +547,7 @@ pub(crate) mod submitevent; pub(crate) mod subtlecrypto; pub(crate) mod svgelement; pub(crate) mod svggraphicselement; +pub(crate) mod svgimageelement; pub(crate) mod svgsvgelement; pub(crate) mod testbinding; pub(crate) mod testbindingiterable; diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index ca785773b48..5f08abce354 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -4207,6 +4207,9 @@ impl From<ElementTypeIdWrapper> for LayoutElementType { LayoutElementType::HTMLTextAreaElement }, ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement( + SVGGraphicsElementTypeId::SVGImageElement, + )) => LayoutElementType::SVGImageElement, + ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement( SVGGraphicsElementTypeId::SVGSVGElement, )) => LayoutElementType::SVGSVGElement, _ => LayoutElementType::Element, diff --git a/components/script/dom/svgelement.rs b/components/script/dom/svgelement.rs index 9c8b990826d..0f36d942f3e 100644 --- a/components/script/dom/svgelement.rs +++ b/components/script/dom/svgelement.rs @@ -82,6 +82,9 @@ impl SVGElementMethods<crate::DomTypeHolder> for SVGElement { }) } + // <https://html.spec.whatwg.org/multipage/#globaleventhandlers> + global_event_handlers!(); + // FIXME: The nonce should be stored in an internal slot instead of an // attribute (https://html.spec.whatwg.org/multipage/#cryptographicnonce) // https://html.spec.whatwg.org/multipage/#dom-noncedelement-nonce diff --git a/components/script/dom/svgimageelement.rs b/components/script/dom/svgimageelement.rs new file mode 100644 index 00000000000..17a5a9149d8 --- /dev/null +++ b/components/script/dom/svgimageelement.rs @@ -0,0 +1,96 @@ +/* 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 dom_struct::dom_struct; +use html5ever::{LocalName, Prefix, local_name, ns}; +use js::rust::HandleObject; +use style::attr::AttrValue; + +use crate::dom::attr::Attr; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::str::DOMString; +use crate::dom::document::Document; +use crate::dom::element::AttributeMutation; +use crate::dom::node::{Node, NodeTraits}; +use crate::dom::svggraphicselement::SVGGraphicsElement; +use crate::dom::virtualmethods::VirtualMethods; +use crate::script_runtime::CanGc; + +/// <https://svgwg.org/svg2-draft/embedded.html#Placement> +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[dom_struct] +pub(crate) struct SVGImageElement { + svggraphicselement: SVGGraphicsElement, +} + +impl SVGImageElement { + fn new_inherited( + local_name: LocalName, + prefix: Option<Prefix>, + document: &Document, + ) -> SVGImageElement { + SVGImageElement { + svggraphicselement: SVGGraphicsElement::new_inherited(local_name, prefix, document), + } + } + + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + pub(crate) fn new( + local_name: LocalName, + prefix: Option<Prefix>, + document: &Document, + proto: Option<HandleObject>, + can_gc: CanGc, + ) -> DomRoot<SVGImageElement> { + Node::reflect_node_with_proto( + Box::new(SVGImageElement::new_inherited(local_name, prefix, document)), + document, + proto, + can_gc, + ) + } + + /// <https://svgwg.org/svg2-draft/linking.html#processingURL> + fn fetch_image_resource(&self) { + // TODO: Process and fetch the image resource (as HTMLImageElement). + // Reject any resource fetching request immediately. + self.owner_global() + .task_manager() + .dom_manipulation_task_source() + .queue_simple_event(self.upcast(), atom!("error")); + } +} + +impl VirtualMethods for SVGImageElement { + fn super_type(&self) -> Option<&dyn VirtualMethods> { + Some(self.upcast::<SVGGraphicsElement>() as &dyn VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) { + self.super_type() + .unwrap() + .attribute_mutated(attr, mutation, can_gc); + if attr.local_name() == &local_name!("href") && + matches!(attr.namespace(), &ns!() | &ns!(xlink)) + { + if let AttributeMutation::Set(_) = mutation { + self.fetch_image_resource(); + } + } + } + + fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue { + match *name { + local_name!("width") => AttrValue::from_u32(value.into(), DEFAULT_WIDTH), + local_name!("height") => AttrValue::from_u32(value.into(), DEFAULT_HEIGHT), + _ => self + .super_type() + .unwrap() + .parse_plain_attribute(name, value), + } + } +} diff --git a/components/script/dom/virtualmethods.rs b/components/script/dom/virtualmethods.rs index 57ecba7b172..1d992b1f301 100644 --- a/components/script/dom/virtualmethods.rs +++ b/components/script/dom/virtualmethods.rs @@ -61,6 +61,7 @@ use crate::dom::htmlvideoelement::HTMLVideoElement; use crate::dom::node::{BindContext, ChildrenMutation, CloneChildrenFlag, Node, UnbindContext}; use crate::dom::shadowroot::ShadowRoot; use crate::dom::svgelement::SVGElement; +use crate::dom::svgimageelement::SVGImageElement; use crate::dom::svgsvgelement::SVGSVGElement; /// Trait to allow DOM nodes to opt-in to overriding (or adding to) common @@ -299,6 +300,9 @@ pub(crate) fn vtable_for(node: &Node) -> &dyn VirtualMethods { node.downcast::<HTMLTitleElement>().unwrap() as &dyn VirtualMethods }, NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement( + SVGGraphicsElementTypeId::SVGImageElement, + ))) => node.downcast::<SVGImageElement>().unwrap() as &dyn VirtualMethods, + NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement( SVGGraphicsElementTypeId::SVGSVGElement, ))) => node.downcast::<SVGSVGElement>().unwrap() as &dyn VirtualMethods, NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGElement)) => { |