script: use Element::create instead of DOM struct constructors (#39325)

Creating elements by directly calling their interface constructors leads
to some state not being intialized correctly (see #39285). It is also
not in line with the specifications as many of them refer to the
[`create an element`][1] algorithm when an element needs to be created,
which directly maps to `Element::create` in the script crate.

So, switch all such places where elements are created by script to use
`Element::create`.

[1]: https://dom.spec.whatwg.org/#concept-create-element

Testing: Existing WPT tests.

Fixes: #39285

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
Mukilan Thiyagarajan 2025-09-16 14:56:42 +05:30 committed by GitHub
parent 2b261b02bf
commit 07b2ff5d60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 254 additions and 98 deletions

View file

@ -78,7 +78,7 @@ use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::reportingendpoint::ReportingEndpoint;
use crate::dom::shadowroot::IsUserAgentWidget;
use crate::dom::text::Text;
use crate::dom::types::{HTMLAudioElement, HTMLMediaElement, HTMLVideoElement};
use crate::dom::types::HTMLMediaElement;
use crate::dom::virtualmethods::vtable_for;
use crate::network_listener::PreInvoke;
use crate::realms::enter_realm;
@ -1035,27 +1035,43 @@ impl ParserContext {
// Step 5. Set the appropriate attribute of the element host element, as described below,
// to the address of the image, video, or audio resource.
let node = if media_type == MediaType::Image {
let img = HTMLImageElement::new(
local_name!("img"),
let img = Element::create(
QualName::new(None, ns!(html), local_name!("img")),
None,
doc,
None,
ElementCreator::ParserCreated(1),
CustomElementCreationMode::Asynchronous,
None,
CanGc::note(),
);
let img = DomRoot::downcast::<HTMLImageElement>(img).unwrap();
img.SetSrc(USVString(self.url.to_string()));
DomRoot::upcast::<Node>(img)
} else if mime_type.type_() == mime::AUDIO {
let audio = HTMLAudioElement::new(local_name!("audio"), None, doc, None, CanGc::note());
audio
.upcast::<HTMLMediaElement>()
.SetSrc(USVString(self.url.to_string()));
let audio = Element::create(
QualName::new(None, ns!(html), local_name!("audio")),
None,
doc,
ElementCreator::ParserCreated(1),
CustomElementCreationMode::Asynchronous,
None,
CanGc::note(),
);
let audio = DomRoot::downcast::<HTMLMediaElement>(audio).unwrap();
audio.SetSrc(USVString(self.url.to_string()));
DomRoot::upcast::<Node>(audio)
} else {
let video = HTMLVideoElement::new(local_name!("video"), None, doc, None, CanGc::note());
video
.upcast::<HTMLMediaElement>()
.SetSrc(USVString(self.url.to_string()));
let video = Element::create(
QualName::new(None, ns!(html), local_name!("video")),
None,
doc,
ElementCreator::ParserCreated(1),
CustomElementCreationMode::Asynchronous,
None,
CanGc::note(),
);
let video = DomRoot::downcast::<HTMLMediaElement>(video).unwrap();
video.SetSrc(USVString(self.url.to_string()));
DomRoot::upcast::<Node>(video)
};
// Step 4. Append an element host element for the media, as described below, to the body element.