mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Add dimension source attribute to HTMLImageElement (#38152)
HTMLImageElement was missing the dimension source attribute, as step 9 from [here](https://html.spec.whatwg.org/multipage/images.html#updating-the-source-set) wasn't implemented. This meant that for an element like this: ```html <picture> <source media="(min-width: 1000px)" srcset="" width="84" height="29"> <img src="" width="25" height="25" alt="Wikimedia Foundation" lang="en" loading="lazy"> </picture> ``` The `width` and `height` attributes of the source tag were being ignored. This broke stuff like these icons on the main page of Wikipedia. **Original:** <img width="2252" height="229" alt="image" src="https://github.com/user-attachments/assets/fa3fdd9d-5f91-43d4-bc9d-784b0a836d44" /> **Fixed:** <img width="2252" height="229" alt="image" src="https://github.com/user-attachments/assets/6f4ca4ae-e764-4394-ac31-9a92bbb456ab" /> Testing: If there isn't an existing test that covers this I'll make one, waiting for the github runner to tell me whether this is covered and then I'll amend the PR --------- Signed-off-by: Leo Ring <leoring03@gmail.com> Signed-off-by: Xiaocheng Hu <hu.xiaocheng@huawei.com> Signed-off-by: Xiaocheng Hu <xiaochengh.work@gmail.com> Co-authored-by: Xiaocheng Hu <hu.xiaocheng@huawei.com> Co-authored-by: Xiaocheng Hu <xiaochengh.work@gmail.com>
This commit is contained in:
parent
be38bd4636
commit
5592061474
2 changed files with 36 additions and 15 deletions
|
@ -162,6 +162,9 @@ pub(crate) struct HTMLImageElement {
|
||||||
form_owner: MutNullableDom<HTMLFormElement>,
|
form_owner: MutNullableDom<HTMLFormElement>,
|
||||||
generation: Cell<u32>,
|
generation: Cell<u32>,
|
||||||
source_set: DomRefCell<SourceSet>,
|
source_set: DomRefCell<SourceSet>,
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#concept-img-dimension-attribute-source>
|
||||||
|
/// Always non-null after construction.
|
||||||
|
dimension_attribute_source: MutNullableDom<Element>,
|
||||||
last_selected_source: DomRefCell<Option<USVString>>,
|
last_selected_source: DomRefCell<Option<USVString>>,
|
||||||
#[ignore_malloc_size_of = "promises are hard"]
|
#[ignore_malloc_size_of = "promises are hard"]
|
||||||
image_decode_promises: DomRefCell<Vec<Rc<Promise>>>,
|
image_decode_promises: DomRefCell<Vec<Rc<Promise>>>,
|
||||||
|
@ -737,9 +740,20 @@ impl HTMLImageElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4.9
|
// Step 4.9
|
||||||
self.normalise_source_densities(&mut source_set, width);
|
if element
|
||||||
|
.get_attribute(&ns!(), &local_name!("width"))
|
||||||
|
.is_some() ||
|
||||||
|
element
|
||||||
|
.get_attribute(&ns!(), &local_name!("height"))
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
self.dimension_attribute_source.set(Some(element));
|
||||||
|
}
|
||||||
|
|
||||||
// Step 4.10
|
// Step 4.10
|
||||||
|
self.normalise_source_densities(&mut source_set, width);
|
||||||
|
|
||||||
|
// Step 4.11
|
||||||
*self.source_set.borrow_mut() = source_set;
|
*self.source_set.borrow_mut() = source_set;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1348,6 +1362,7 @@ impl HTMLImageElement {
|
||||||
form_owner: Default::default(),
|
form_owner: Default::default(),
|
||||||
generation: Default::default(),
|
generation: Default::default(),
|
||||||
source_set: DomRefCell::new(SourceSet::new()),
|
source_set: DomRefCell::new(SourceSet::new()),
|
||||||
|
dimension_attribute_source: Default::default(),
|
||||||
last_selected_source: DomRefCell::new(None),
|
last_selected_source: DomRefCell::new(None),
|
||||||
image_decode_promises: DomRefCell::new(vec![]),
|
image_decode_promises: DomRefCell::new(vec![]),
|
||||||
line_number: creator.return_line_number(),
|
line_number: creator.return_line_number(),
|
||||||
|
@ -1363,14 +1378,18 @@ impl HTMLImageElement {
|
||||||
creator: ElementCreator,
|
creator: ElementCreator,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<HTMLImageElement> {
|
) -> DomRoot<HTMLImageElement> {
|
||||||
Node::reflect_node_with_proto(
|
let image_element = Node::reflect_node_with_proto(
|
||||||
Box::new(HTMLImageElement::new_inherited(
|
Box::new(HTMLImageElement::new_inherited(
|
||||||
local_name, prefix, document, creator,
|
local_name, prefix, document, creator,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
proto,
|
proto,
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
);
|
||||||
|
image_element
|
||||||
|
.dimension_attribute_source
|
||||||
|
.set(Some(image_element.upcast()));
|
||||||
|
image_element
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn areas(&self) -> Option<Vec<DomRoot<HTMLAreaElement>>> {
|
pub(crate) fn areas(&self) -> Option<Vec<DomRoot<HTMLAreaElement>>> {
|
||||||
|
@ -1487,6 +1506,16 @@ impl<'dom> LayoutDom<'dom, HTMLImageElement> {
|
||||||
fn current_request(self) -> &'dom ImageRequest {
|
fn current_request(self) -> &'dom ImageRequest {
|
||||||
unsafe { self.unsafe_get().current_request.borrow_for_layout() }
|
unsafe { self.unsafe_get().current_request.borrow_for_layout() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn dimension_attribute_source(self) -> LayoutDom<'dom, Element> {
|
||||||
|
unsafe {
|
||||||
|
self.unsafe_get()
|
||||||
|
.dimension_attribute_source
|
||||||
|
.get_inner_as_layout()
|
||||||
|
.expect("dimension attribute source should be always non-null")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutHTMLImageElementHelpers for LayoutDom<'_, HTMLImageElement> {
|
impl LayoutHTMLImageElementHelpers for LayoutDom<'_, HTMLImageElement> {
|
||||||
|
@ -1504,18 +1533,16 @@ impl LayoutHTMLImageElementHelpers for LayoutDom<'_, HTMLImageElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_width(self) -> LengthOrPercentageOrAuto {
|
fn get_width(self) -> LengthOrPercentageOrAuto {
|
||||||
self.upcast::<Element>()
|
self.dimension_attribute_source()
|
||||||
.get_attr_for_layout(&ns!(), &local_name!("width"))
|
.get_attr_for_layout(&ns!(), &local_name!("width"))
|
||||||
.map(AttrValue::as_dimension)
|
.map(|x| *AttrValue::from_dimension(x.to_string()).as_dimension())
|
||||||
.cloned()
|
|
||||||
.unwrap_or(LengthOrPercentageOrAuto::Auto)
|
.unwrap_or(LengthOrPercentageOrAuto::Auto)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_height(self) -> LengthOrPercentageOrAuto {
|
fn get_height(self) -> LengthOrPercentageOrAuto {
|
||||||
self.upcast::<Element>()
|
self.dimension_attribute_source()
|
||||||
.get_attr_for_layout(&ns!(), &local_name!("height"))
|
.get_attr_for_layout(&ns!(), &local_name!("height"))
|
||||||
.map(AttrValue::as_dimension)
|
.map(|x| *AttrValue::from_dimension(x.to_string()).as_dimension())
|
||||||
.cloned()
|
|
||||||
.unwrap_or(LengthOrPercentageOrAuto::Auto)
|
.unwrap_or(LengthOrPercentageOrAuto::Auto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,3 @@
|
||||||
|
|
||||||
[If we only have height attribute, we should get height mapped but no aspect ratio, even if <img> has attributes.]
|
[If we only have height attribute, we should get height mapped but no aspect ratio, even if <img> has attributes.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Loaded picture test: <source> with width and height attributes, <img> without width and height attributes]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Loaded picture test: Both <source> and <img> are with width and height attributes]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue