aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/attr.rs10
-rw-r--r--components/script/dom/create.rs2
-rw-r--r--components/script/dom/element.rs19
-rw-r--r--components/script/dom/htmliframeelement.rs26
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/node.rs3
-rw-r--r--components/script/dom/svgelement.rs3
-rw-r--r--components/script/dom/svgimageelement.rs96
-rw-r--r--components/script/dom/virtualmethods.rs4
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)) => {