CanGc fixes through focusevent.rs & hashchangeevent.rs (#33921)

Signed-off-by: taniishkaaa <tanishkasingh2004@gmail.com>
This commit is contained in:
tanishka 2024-10-20 13:35:11 +05:30 committed by GitHub
parent d0d02cd56c
commit a57b6a3f79
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 140 additions and 69 deletions

View file

@ -101,6 +101,10 @@ DOMInterfaces = {
'canGc': ['SetInnerHTML', 'SetOuterHTML', 'InsertAdjacentHTML', 'GetClientRects', 'GetBoundingClientRect'], 'canGc': ['SetInnerHTML', 'SetOuterHTML', 'InsertAdjacentHTML', 'GetClientRects', 'GetBoundingClientRect'],
}, },
'ElementInternals': {
'canGc': ['ReportValidity'],
},
'EventSource': { 'EventSource': {
'weakReferenceable': True, 'weakReferenceable': True,
}, },
@ -135,8 +139,24 @@ DOMInterfaces = {
'inRealms': ['PlayEffect', 'Reset'] 'inRealms': ['PlayEffect', 'Reset']
}, },
'HTMLButtonElement': {
'canGc': ['ReportValidity'],
},
'HTMLElement': {
'canGc': ['Focus', 'Blur'],
},
'HTMLFieldSetElement': {
'canGc': ['ReportValidity'],
},
'HTMLFormElement': { 'HTMLFormElement': {
'canGc': ['RequestSubmit'], 'canGc': ['RequestSubmit', 'ReportValidity'],
},
'HTMLInputElement': {
'canGc': ['ReportValidity'],
}, },
'HTMLMediaElement': { 'HTMLMediaElement': {
@ -144,14 +164,30 @@ DOMInterfaces = {
'inRealms': ['Play'], 'inRealms': ['Play'],
}, },
'HTMLObjectElement': {
'canGc': ['ReportValidity'],
},
'HTMLOutputElement': {
'canGc': ['ReportValidity'],
},
'HTMLCanvasElement': { 'HTMLCanvasElement': {
'canGc': ['CaptureStream', 'GetContext'], 'canGc': ['CaptureStream', 'GetContext'],
}, },
'HTMLSelectElement': {
'canGc': ['ReportValidity'],
},
'HTMLTemplateElement': { 'HTMLTemplateElement': {
'canGc': ['Content'], 'canGc': ['Content'],
}, },
'HTMLTextAreaElement': {
'canGc': ['ReportValidity'],
},
'MediaDevices': { 'MediaDevices': {
'canGc': ['GetUserMedia'], 'canGc': ['GetUserMedia'],
'inRealms': ['GetUserMedia', 'GetClientRects', 'GetBoundingClientRect'], 'inRealms': ['GetUserMedia', 'GetClientRects', 'GetBoundingClientRect'],

View file

@ -1112,20 +1112,26 @@ impl Document {
} }
/// <https://html.spec.whatwg.org/multipage/#focus-fixup-rule> /// <https://html.spec.whatwg.org/multipage/#focus-fixup-rule>
pub(crate) fn perform_focus_fixup_rule(&self, not_focusable: &Element) { pub(crate) fn perform_focus_fixup_rule(&self, not_focusable: &Element, can_gc: CanGc) {
if Some(not_focusable) != self.focused.get().as_deref() { if Some(not_focusable) != self.focused.get().as_deref() {
return; return;
} }
self.request_focus( self.request_focus(
self.GetBody().as_ref().map(|e| e.upcast()), self.GetBody().as_ref().map(|e| e.upcast()),
FocusType::Element, FocusType::Element,
can_gc,
) )
} }
/// Request that the given element receive focus once the current transaction is complete. /// Request that the given element receive focus once the current transaction is complete.
/// If None is passed, then whatever element is currently focused will no longer be focused /// If None is passed, then whatever element is currently focused will no longer be focused
/// once the transaction is complete. /// once the transaction is complete.
pub(crate) fn request_focus(&self, elem: Option<&Element>, focus_type: FocusType) { pub(crate) fn request_focus(
&self,
elem: Option<&Element>,
focus_type: FocusType,
can_gc: CanGc,
) {
let implicit_transaction = matches!( let implicit_transaction = matches!(
*self.focus_transaction.borrow(), *self.focus_transaction.borrow(),
FocusTransaction::NotInTransaction FocusTransaction::NotInTransaction
@ -1138,13 +1144,13 @@ impl Document {
FocusTransaction::InTransaction(elem.map(Dom::from_ref)); FocusTransaction::InTransaction(elem.map(Dom::from_ref));
} }
if implicit_transaction { if implicit_transaction {
self.commit_focus_transaction(focus_type); self.commit_focus_transaction(focus_type, can_gc);
} }
} }
/// Reassign the focus context to the element that last requested focus during this /// Reassign the focus context to the element that last requested focus during this
/// transaction, or none if no elements requested it. /// transaction, or none if no elements requested it.
fn commit_focus_transaction(&self, focus_type: FocusType) { fn commit_focus_transaction(&self, focus_type: FocusType, can_gc: CanGc) {
let possibly_focused = match *self.focus_transaction.borrow() { let possibly_focused = match *self.focus_transaction.borrow() {
FocusTransaction::NotInTransaction => unreachable!(), FocusTransaction::NotInTransaction => unreachable!(),
FocusTransaction::InTransaction(ref elem) => { FocusTransaction::InTransaction(ref elem) => {
@ -1159,7 +1165,7 @@ impl Document {
let node = elem.upcast::<Node>(); let node = elem.upcast::<Node>();
elem.set_focus_state(false); elem.set_focus_state(false);
// FIXME: pass appropriate relatedTarget // FIXME: pass appropriate relatedTarget
self.fire_focus_event(FocusEventType::Blur, node, None); self.fire_focus_event(FocusEventType::Blur, node, None, can_gc);
// Notify the embedder to hide the input method. // Notify the embedder to hide the input method.
if elem.input_method_type().is_some() { if elem.input_method_type().is_some() {
@ -1173,7 +1179,7 @@ impl Document {
elem.set_focus_state(true); elem.set_focus_state(true);
let node = elem.upcast::<Node>(); let node = elem.upcast::<Node>();
// FIXME: pass appropriate relatedTarget // FIXME: pass appropriate relatedTarget
self.fire_focus_event(FocusEventType::Focus, node, None); self.fire_focus_event(FocusEventType::Focus, node, None, can_gc);
// Update the focus state for all elements in the focus chain. // Update the focus state for all elements in the focus chain.
// https://html.spec.whatwg.org/multipage/#focus-chain // https://html.spec.whatwg.org/multipage/#focus-chain
if focus_type == FocusType::Element { if focus_type == FocusType::Element {
@ -1299,6 +1305,7 @@ impl Document {
node_address: Option<UntrustedNodeAddress>, node_address: Option<UntrustedNodeAddress>,
point_in_node: Option<Point2D<f32>>, point_in_node: Option<Point2D<f32>>,
pressed_mouse_buttons: u16, pressed_mouse_buttons: u16,
can_gc: CanGc,
) { ) {
let mouse_event_type_string = match mouse_event_type { let mouse_event_type_string = match mouse_event_type {
MouseEventType::Click => "click".to_owned(), MouseEventType::Click => "click".to_owned(),
@ -1328,7 +1335,7 @@ impl Document {
} }
self.begin_focus_transaction(); self.begin_focus_transaction();
self.request_focus(Some(&*el), FocusType::Element); self.request_focus(Some(&*el), FocusType::Element, can_gc);
} }
// https://w3c.github.io/uievents/#event-type-click // https://w3c.github.io/uievents/#event-type-click
@ -1390,7 +1397,7 @@ impl Document {
} }
if let MouseEventType::Click = mouse_event_type { if let MouseEventType::Click = mouse_event_type {
self.commit_focus_transaction(FocusType::Element); self.commit_focus_transaction(FocusType::Element, can_gc);
self.maybe_fire_dblclick(client_point, node, pressed_mouse_buttons); self.maybe_fire_dblclick(client_point, node, pressed_mouse_buttons);
} }
} }
@ -1901,10 +1908,11 @@ impl Document {
} }
} }
pub fn ime_dismissed(&self) { pub fn ime_dismissed(&self, can_gc: CanGc) {
self.request_focus( self.request_focus(
self.GetBody().as_ref().map(|e| e.upcast()), self.GetBody().as_ref().map(|e| e.upcast()),
FocusType::Element, FocusType::Element,
can_gc,
) )
} }
@ -2850,6 +2858,7 @@ impl Document {
focus_event_type: FocusEventType, focus_event_type: FocusEventType,
node: &Node, node: &Node,
related_target: Option<&EventTarget>, related_target: Option<&EventTarget>,
can_gc: CanGc,
) { ) {
let (event_name, does_bubble) = match focus_event_type { let (event_name, does_bubble) = match focus_event_type {
FocusEventType::Focus => (DOMString::from("focus"), EventBubbles::DoesNotBubble), FocusEventType::Focus => (DOMString::from("focus"), EventBubbles::DoesNotBubble),
@ -2863,6 +2872,7 @@ impl Document {
Some(&self.window), Some(&self.window),
0i32, 0i32,
related_target, related_target,
can_gc,
); );
let event = event.upcast::<Event>(); let event = event.upcast::<Event>();
event.set_trusted(true); event.set_trusted(true);
@ -4680,6 +4690,7 @@ impl DocumentMethods for Document {
))), ))),
"hashchangeevent" => Ok(DomRoot::upcast(HashChangeEvent::new_uninitialized( "hashchangeevent" => Ok(DomRoot::upcast(HashChangeEvent::new_uninitialized(
&self.window, &self.window,
can_gc,
))), ))),
"keyboardevent" => Ok(DomRoot::upcast(KeyboardEvent::new_uninitialized( "keyboardevent" => Ok(DomRoot::upcast(KeyboardEvent::new_uninitialized(
&self.window, &self.window,

View file

@ -2002,7 +2002,7 @@ impl Element {
} }
} }
pub(crate) fn update_sequentially_focusable_status(&self) { pub(crate) fn update_sequentially_focusable_status(&self, can_gc: CanGc) {
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
let is_sequentially_focusable = self.is_sequentially_focusable(); let is_sequentially_focusable = self.is_sequentially_focusable();
node.set_flag(NodeFlags::SEQUENTIALLY_FOCUSABLE, is_sequentially_focusable); node.set_flag(NodeFlags::SEQUENTIALLY_FOCUSABLE, is_sequentially_focusable);
@ -2010,7 +2010,7 @@ impl Element {
// https://html.spec.whatwg.org/multipage/#focus-fixup-rule // https://html.spec.whatwg.org/multipage/#focus-fixup-rule
if !is_sequentially_focusable { if !is_sequentially_focusable {
let document = document_from_node(self); let document = document_from_node(self);
document.perform_focus_fixup_rule(self); document.perform_focus_fixup_rule(self, can_gc);
} }
} }
@ -3327,7 +3327,7 @@ impl VirtualMethods for Element {
let doc = node.owner_doc(); let doc = node.owner_doc();
match attr.local_name() { match attr.local_name() {
&local_name!("tabindex") | &local_name!("draggable") | &local_name!("hidden") => { &local_name!("tabindex") | &local_name!("draggable") | &local_name!("hidden") => {
self.update_sequentially_focusable_status() self.update_sequentially_focusable_status(CanGc::note())
}, },
&local_name!("style") => { &local_name!("style") => {
// Modifying the `style` attribute might change style. // Modifying the `style` attribute might change style.
@ -3493,7 +3493,7 @@ impl VirtualMethods for Element {
return; return;
} }
self.update_sequentially_focusable_status(); self.update_sequentially_focusable_status(CanGc::note());
if let Some(ref id) = *self.id_attribute.borrow() { if let Some(ref id) = *self.id_attribute.borrow() {
if let Some(shadow_root) = self.upcast::<Node>().containing_shadow_root() { if let Some(shadow_root) = self.upcast::<Node>().containing_shadow_root() {
@ -3526,7 +3526,7 @@ impl VirtualMethods for Element {
return; return;
} }
self.update_sequentially_focusable_status(); self.update_sequentially_focusable_status(CanGc::note());
let doc = document_from_node(self); let doc = document_from_node(self);

View file

@ -25,6 +25,7 @@ use crate::dom::node::{window_from_node, Node};
use crate::dom::nodelist::NodeList; use crate::dom::nodelist::NodeList;
use crate::dom::validation::{is_barred_by_datalist_ancestor, Validatable}; use crate::dom::validation::{is_barred_by_datalist_ancestor, Validatable};
use crate::dom::validitystate::{ValidationFlags, ValidityState}; use crate::dom::validitystate::{ValidationFlags, ValidityState};
use crate::script_runtime::CanGc;
#[derive(Clone, JSTraceable, MallocSizeOf)] #[derive(Clone, JSTraceable, MallocSizeOf)]
enum SubmissionValue { enum SubmissionValue {
@ -324,11 +325,11 @@ impl ElementInternalsMethods for ElementInternals {
} }
/// <https://html.spec.whatwg.org/multipage#dom-elementinternals-reportvalidity> /// <https://html.spec.whatwg.org/multipage#dom-elementinternals-reportvalidity>
fn ReportValidity(&self) -> Fallible<bool> { fn ReportValidity(&self, can_gc: CanGc) -> Fallible<bool> {
if !self.is_target_form_associated() { if !self.is_target_form_associated() {
return Err(Error::NotSupported); return Err(Error::NotSupported);
} }
Ok(self.report_validity()) Ok(self.report_validity(can_gc))
} }
} }

View file

@ -55,6 +55,7 @@ impl FocusEvent {
view: Option<&Window>, view: Option<&Window>,
detail: i32, detail: i32,
related_target: Option<&EventTarget>, related_target: Option<&EventTarget>,
can_gc: CanGc,
) -> DomRoot<FocusEvent> { ) -> DomRoot<FocusEvent> {
Self::new_with_proto( Self::new_with_proto(
window, window,
@ -65,7 +66,7 @@ impl FocusEvent {
view, view,
detail, detail,
related_target, related_target,
CanGc::note(), can_gc,
) )
} }

View file

@ -35,19 +35,20 @@ impl HashChangeEvent {
} }
} }
pub fn new_uninitialized(window: &Window) -> DomRoot<HashChangeEvent> { pub fn new_uninitialized(window: &Window, can_gc: CanGc) -> DomRoot<HashChangeEvent> {
Self::new_uninitialized_with_proto(window, None) Self::new_uninitialized_with_proto(window, None, can_gc)
} }
fn new_uninitialized_with_proto( fn new_uninitialized_with_proto(
window: &Window, window: &Window,
proto: Option<HandleObject>, proto: Option<HandleObject>,
can_gc: CanGc,
) -> DomRoot<HashChangeEvent> { ) -> DomRoot<HashChangeEvent> {
reflect_dom_object_with_proto( reflect_dom_object_with_proto(
Box::new(HashChangeEvent::new_inherited(String::new(), String::new())), Box::new(HashChangeEvent::new_inherited(String::new(), String::new())),
window, window,
proto, proto,
CanGc::note(), can_gc,
) )
} }
@ -58,16 +59,10 @@ impl HashChangeEvent {
cancelable: bool, cancelable: bool,
old_url: String, old_url: String,
new_url: String, new_url: String,
can_gc: CanGc,
) -> DomRoot<HashChangeEvent> { ) -> DomRoot<HashChangeEvent> {
Self::new_with_proto( Self::new_with_proto(
window, window, None, type_, bubbles, cancelable, old_url, new_url, can_gc,
None,
type_,
bubbles,
cancelable,
old_url,
new_url,
CanGc::note(),
) )
} }

View file

@ -152,6 +152,7 @@ impl History {
false, false,
old_url.into_string(), old_url.into_string(),
url.into_string(), url.into_string(),
can_gc,
); );
event event
.upcast::<Event>() .upcast::<Event>()

View file

@ -175,8 +175,8 @@ impl HTMLButtonElementMethods for HTMLButtonElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity // https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity
fn ReportValidity(&self) -> bool { fn ReportValidity(&self, can_gc: CanGc) -> bool {
self.report_validity() self.report_validity(can_gc)
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage // https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage
@ -245,7 +245,7 @@ impl VirtualMethods for HTMLButtonElement {
el.check_ancestors_disabled_state_for_form_control(); el.check_ancestors_disabled_state_for_form_control();
}, },
} }
el.update_sequentially_focusable_status(); el.update_sequentially_focusable_status(CanGc::note());
self.validity_state() self.validity_state()
.perform_validation_and_update(ValidationFlags::all()); .perform_validation_and_update(ValidationFlags::all());
}, },

View file

@ -51,6 +51,7 @@ use crate::dom::node::{
}; };
use crate::dom::text::Text; use crate::dom::text::Text;
use crate::dom::virtualmethods::VirtualMethods; use crate::dom::virtualmethods::VirtualMethods;
use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
#[dom_struct] #[dom_struct]
@ -399,22 +400,22 @@ impl HTMLElementMethods for HTMLElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-focus // https://html.spec.whatwg.org/multipage/#dom-focus
fn Focus(&self) { fn Focus(&self, can_gc: CanGc) {
// TODO: Mark the element as locked for focus and run the focusing steps. // TODO: Mark the element as locked for focus and run the focusing steps.
// https://html.spec.whatwg.org/multipage/#focusing-steps // https://html.spec.whatwg.org/multipage/#focusing-steps
let document = document_from_node(self); let document = document_from_node(self);
document.request_focus(Some(self.upcast()), FocusType::Element); document.request_focus(Some(self.upcast()), FocusType::Element, can_gc);
} }
// https://html.spec.whatwg.org/multipage/#dom-blur // https://html.spec.whatwg.org/multipage/#dom-blur
fn Blur(&self) { fn Blur(&self, can_gc: CanGc) {
// TODO: Run the unfocusing steps. // TODO: Run the unfocusing steps.
if !self.as_element().focus_state() { if !self.as_element().focus_state() {
return; return;
} }
// https://html.spec.whatwg.org/multipage/#unfocusing-steps // https://html.spec.whatwg.org/multipage/#unfocusing-steps
let document = document_from_node(self); let document = document_from_node(self);
document.request_focus(None, FocusType::Element); document.request_focus(None, FocusType::Element, can_gc);
} }
// https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent // https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent
@ -1077,7 +1078,7 @@ impl VirtualMethods for HTMLElement {
super_type.bind_to_tree(context); super_type.bind_to_tree(context);
} }
let element = self.as_element(); let element = self.as_element();
element.update_sequentially_focusable_status(); element.update_sequentially_focusable_status(CanGc::note());
// Binding to a tree can disable a form control if one of the new // Binding to a tree can disable a form control if one of the new
// ancestors is a fieldset. // ancestors is a fieldset.

View file

@ -25,6 +25,7 @@ use crate::dom::node::{window_from_node, Node, ShadowIncluding};
use crate::dom::validation::Validatable; use crate::dom::validation::Validatable;
use crate::dom::validitystate::ValidityState; use crate::dom::validitystate::ValidityState;
use crate::dom::virtualmethods::VirtualMethods; use crate::dom::virtualmethods::VirtualMethods;
use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
#[dom_struct] #[dom_struct]
@ -131,8 +132,8 @@ impl HTMLFieldSetElementMethods for HTMLFieldSetElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity // https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity
fn ReportValidity(&self) -> bool { fn ReportValidity(&self, can_gc: CanGc) -> bool {
self.report_validity() self.report_validity(can_gc)
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage // https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage
@ -219,7 +220,7 @@ impl VirtualMethods for HTMLFieldSetElement {
); );
} }
} }
element.update_sequentially_focusable_status(); element.update_sequentially_focusable_status(CanGc::note());
} }
} else { } else {
for field in fields { for field in fields {
@ -240,10 +241,10 @@ impl VirtualMethods for HTMLFieldSetElement {
); );
} }
} }
element.update_sequentially_focusable_status(); element.update_sequentially_focusable_status(CanGc::note());
} }
} }
element.update_sequentially_focusable_status(); element.update_sequentially_focusable_status(CanGc::note());
}, },
local_name!("form") => { local_name!("form") => {
self.form_attribute_mutated(mutation); self.form_attribute_mutated(mutation);

View file

@ -634,8 +634,8 @@ impl HTMLFormElementMethods for HTMLFormElement {
} }
/// <https://html.spec.whatwg.org/multipage/#dom-form-reportvalidity> /// <https://html.spec.whatwg.org/multipage/#dom-form-reportvalidity>
fn ReportValidity(&self) -> bool { fn ReportValidity(&self, can_gc: CanGc) -> bool {
self.interactive_validation().is_ok() self.interactive_validation(can_gc).is_ok()
} }
} }
@ -733,7 +733,7 @@ impl HTMLFormElement {
// Step 6.2 // Step 6.2
self.firing_submission_events.set(true); self.firing_submission_events.set(true);
// Step 6.3 // Step 6.3
if !submitter.no_validate(self) && self.interactive_validation().is_err() { if !submitter.no_validate(self) && self.interactive_validation(can_gc).is_err() {
self.firing_submission_events.set(false); self.firing_submission_events.set(false);
return; return;
} }
@ -1029,7 +1029,7 @@ impl HTMLFormElement {
/// Interactively validate the constraints of form elements /// Interactively validate the constraints of form elements
/// <https://html.spec.whatwg.org/multipage/#interactively-validate-the-constraints> /// <https://html.spec.whatwg.org/multipage/#interactively-validate-the-constraints>
fn interactive_validation(&self) -> Result<(), ()> { fn interactive_validation(&self, can_gc: CanGc) -> Result<(), ()> {
// Step 1-2 // Step 1-2
let unhandled_invalid_controls = match self.static_validation() { let unhandled_invalid_controls = match self.static_validation() {
Ok(()) => return Ok(()), Ok(()) => return Ok(()),
@ -1045,7 +1045,7 @@ impl HTMLFormElement {
} }
if first { if first {
if let Some(html_elem) = elem.downcast::<HTMLElement>() { if let Some(html_elem) = elem.downcast::<HTMLElement>() {
html_elem.Focus(); html_elem.Focus(can_gc);
first = false; first = false;
} }
} }

View file

@ -1591,8 +1591,8 @@ impl HTMLInputElementMethods for HTMLInputElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity // https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity
fn ReportValidity(&self) -> bool { fn ReportValidity(&self, can_gc: CanGc) -> bool {
self.report_validity() self.report_validity(can_gc)
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage // https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage
@ -2267,7 +2267,7 @@ impl VirtualMethods for HTMLInputElement {
el.set_read_write_state(read_write); el.set_read_write_state(read_write);
} }
el.update_sequentially_focusable_status(); el.update_sequentially_focusable_status(CanGc::note());
}, },
local_name!("checked") if !self.checked_changed.get() => { local_name!("checked") if !self.checked_changed.get() => {
let checked_state = match mutation { let checked_state = match mutation {

View file

@ -24,6 +24,7 @@ use crate::dom::node::{window_from_node, Node};
use crate::dom::validation::Validatable; use crate::dom::validation::Validatable;
use crate::dom::validitystate::ValidityState; use crate::dom::validitystate::ValidityState;
use crate::dom::virtualmethods::VirtualMethods; use crate::dom::virtualmethods::VirtualMethods;
use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct HTMLObjectElement { pub struct HTMLObjectElement {
@ -114,8 +115,8 @@ impl HTMLObjectElementMethods for HTMLObjectElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity // https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity
fn ReportValidity(&self) -> bool { fn ReportValidity(&self, can_gc: CanGc) -> bool {
self.report_validity() self.report_validity(can_gc)
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage // https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage

View file

@ -21,6 +21,7 @@ use crate::dom::nodelist::NodeList;
use crate::dom::validation::Validatable; use crate::dom::validation::Validatable;
use crate::dom::validitystate::ValidityState; use crate::dom::validitystate::ValidityState;
use crate::dom::virtualmethods::VirtualMethods; use crate::dom::virtualmethods::VirtualMethods;
use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct HTMLOutputElement { pub struct HTMLOutputElement {
@ -136,8 +137,8 @@ impl HTMLOutputElementMethods for HTMLOutputElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity // https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity
fn ReportValidity(&self) -> bool { fn ReportValidity(&self, can_gc: CanGc) -> bool {
self.report_validity() self.report_validity(can_gc)
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage // https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage

View file

@ -39,6 +39,7 @@ use crate::dom::nodelist::NodeList;
use crate::dom::validation::{is_barred_by_datalist_ancestor, Validatable}; use crate::dom::validation::{is_barred_by_datalist_ancestor, Validatable};
use crate::dom::validitystate::{ValidationFlags, ValidityState}; use crate::dom::validitystate::{ValidationFlags, ValidityState};
use crate::dom::virtualmethods::VirtualMethods; use crate::dom::virtualmethods::VirtualMethods;
use crate::script_runtime::CanGc;
#[derive(JSTraceable, MallocSizeOf)] #[derive(JSTraceable, MallocSizeOf)]
struct OptionsFilter; struct OptionsFilter;
@ -395,8 +396,8 @@ impl HTMLSelectElementMethods for HTMLSelectElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity // https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity
fn ReportValidity(&self) -> bool { fn ReportValidity(&self, can_gc: CanGc) -> bool {
self.report_validity() self.report_validity(can_gc)
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage // https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage

View file

@ -42,6 +42,7 @@ use crate::dom::textcontrol::{TextControlElement, TextControlSelection};
use crate::dom::validation::{is_barred_by_datalist_ancestor, Validatable}; use crate::dom::validation::{is_barred_by_datalist_ancestor, Validatable};
use crate::dom::validitystate::{ValidationFlags, ValidityState}; use crate::dom::validitystate::{ValidationFlags, ValidityState};
use crate::dom::virtualmethods::VirtualMethods; use crate::dom::virtualmethods::VirtualMethods;
use crate::script_runtime::CanGc;
use crate::textinput::{ use crate::textinput::{
Direction, KeyReaction, Lines, SelectionDirection, TextInput, UTF16CodeUnits, UTF8Bytes, Direction, KeyReaction, Lines, SelectionDirection, TextInput, UTF16CodeUnits, UTF8Bytes,
}; };
@ -428,8 +429,8 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity // https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity
fn ReportValidity(&self) -> bool { fn ReportValidity(&self, can_gc: CanGc) -> bool {
self.report_validity() self.report_validity(can_gc)
} }
// https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage // https://html.spec.whatwg.org/multipage/#dom-cva-validationmessage
@ -484,7 +485,7 @@ impl VirtualMethods for HTMLTextAreaElement {
} }
}, },
} }
el.update_sequentially_focusable_status(); el.update_sequentially_focusable_status(CanGc::note());
}, },
local_name!("maxlength") => match *attr.value() { local_name!("maxlength") => match *attr.value() {
AttrValue::Int(_, value) => { AttrValue::Int(_, value) => {

View file

@ -12,6 +12,7 @@ use crate::dom::htmldatalistelement::HTMLDataListElement;
use crate::dom::htmlelement::HTMLElement; use crate::dom::htmlelement::HTMLElement;
use crate::dom::node::Node; use crate::dom::node::Node;
use crate::dom::validitystate::{ValidationFlags, ValidityState}; use crate::dom::validitystate::{ValidationFlags, ValidityState};
use crate::script_runtime::CanGc;
/// Trait for elements with constraint validation support /// Trait for elements with constraint validation support
pub trait Validatable { pub trait Validatable {
@ -46,7 +47,7 @@ pub trait Validatable {
} }
/// <https://html.spec.whatwg.org/multipage/#report-validity-steps> /// <https://html.spec.whatwg.org/multipage/#report-validity-steps>
fn report_validity(&self) -> bool { fn report_validity(&self, can_gc: CanGc) -> bool {
// Step 1. // Step 1.
if !self.is_instance_validatable() { if !self.is_instance_validatable() {
return true; return true;
@ -70,7 +71,7 @@ pub trait Validatable {
validation_message_for_flags(&self.validity_state(), flags) validation_message_for_flags(&self.validity_state(), flags)
); );
if let Some(html_elem) = self.as_element().downcast::<HTMLElement>() { if let Some(html_elem) = self.as_element().downcast::<HTMLElement>() {
html_elem.Focus(); html_elem.Focus(can_gc);
} }
} }

View file

@ -2262,7 +2262,8 @@ impl Window {
false, false,
false, false,
old_url, old_url,
new_url); new_url,
CanGc::note());
event.upcast::<Event>().fire(this.upcast::<EventTarget>()); event.upcast::<Event>().fire(this.upcast::<EventTarget>());
}); });
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?

View file

@ -1581,6 +1581,7 @@ impl ScriptThread {
node_address, node_address,
point_in_node, point_in_node,
pressed_mouse_buttons, pressed_mouse_buttons,
can_gc,
); );
}, },
@ -1628,7 +1629,7 @@ impl ScriptThread {
}, },
CompositorEvent::IMEDismissedEvent => { CompositorEvent::IMEDismissedEvent => {
document.ime_dismissed(); document.ime_dismissed(can_gc);
}, },
CompositorEvent::CompositionEvent(composition_event) => { CompositorEvent::CompositionEvent(composition_event) => {
@ -2381,7 +2382,7 @@ impl ScriptThread {
self.handle_remove_history_states(pipeline_id, history_states) self.handle_remove_history_states(pipeline_id, history_states)
}, },
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) => { ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) => {
self.handle_focus_iframe_msg(parent_pipeline_id, frame_id) self.handle_focus_iframe_msg(parent_pipeline_id, frame_id, can_gc)
}, },
ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) => { ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) => {
self.handle_webdriver_msg(pipeline_id, msg, can_gc) self.handle_webdriver_msg(pipeline_id, msg, can_gc)
@ -2782,10 +2783,22 @@ impl ScriptThread {
) )
}, },
WebDriverScriptCommand::FocusElement(element_id, reply) => { WebDriverScriptCommand::FocusElement(element_id, reply) => {
webdriver_handlers::handle_focus_element(&documents, pipeline_id, element_id, reply) webdriver_handlers::handle_focus_element(
&documents,
pipeline_id,
element_id,
reply,
can_gc,
)
}, },
WebDriverScriptCommand::ElementClick(element_id, reply) => { WebDriverScriptCommand::ElementClick(element_id, reply) => {
webdriver_handlers::handle_element_click(&documents, pipeline_id, element_id, reply) webdriver_handlers::handle_element_click(
&documents,
pipeline_id,
element_id,
reply,
can_gc,
)
}, },
WebDriverScriptCommand::GetActiveElement(reply) => { WebDriverScriptCommand::GetActiveElement(reply) => {
webdriver_handlers::handle_get_active_element(&documents, pipeline_id, reply) webdriver_handlers::handle_get_active_element(&documents, pipeline_id, reply)
@ -3027,6 +3040,7 @@ impl ScriptThread {
&self, &self,
parent_pipeline_id: PipelineId, parent_pipeline_id: PipelineId,
browsing_context_id: BrowsingContextId, browsing_context_id: BrowsingContextId,
can_gc: CanGc,
) { ) {
let doc = self let doc = self
.documents .documents
@ -3036,7 +3050,7 @@ impl ScriptThread {
let frame_element = doc.find_iframe(browsing_context_id); let frame_element = doc.find_iframe(browsing_context_id);
if let Some(ref frame_element) = frame_element { if let Some(ref frame_element) = frame_element {
doc.request_focus(Some(frame_element.upcast()), FocusType::Parent); doc.request_focus(Some(frame_element.upcast()), FocusType::Parent, can_gc);
} }
} }
@ -3914,6 +3928,7 @@ impl ScriptThread {
node_address: Option<UntrustedNodeAddress>, node_address: Option<UntrustedNodeAddress>,
point_in_node: Option<Point2D<f32>>, point_in_node: Option<Point2D<f32>>,
pressed_mouse_buttons: u16, pressed_mouse_buttons: u16,
can_gc: CanGc,
) { ) {
let Some(document) = self.documents.borrow().find_document(pipeline_id) else { let Some(document) = self.documents.borrow().find_document(pipeline_id) else {
warn!("Message sent to closed pipeline {pipeline_id}."); warn!("Message sent to closed pipeline {pipeline_id}.");
@ -3927,6 +3942,7 @@ impl ScriptThread {
node_address, node_address,
point_in_node, point_in_node,
pressed_mouse_buttons, pressed_mouse_buttons,
can_gc,
) )
} }
} }

View file

@ -677,6 +677,7 @@ pub fn handle_focus_element(
pipeline: PipelineId, pipeline: PipelineId,
element_id: String, element_id: String,
reply: IpcSender<Result<(), ErrorStatus>>, reply: IpcSender<Result<(), ErrorStatus>>,
can_gc: CanGc,
) { ) {
reply reply
.send( .send(
@ -684,7 +685,7 @@ pub fn handle_focus_element(
match node.downcast::<HTMLElement>() { match node.downcast::<HTMLElement>() {
Some(element) => { Some(element) => {
// Need a way to find if this actually succeeded // Need a way to find if this actually succeeded
element.Focus(); element.Focus(can_gc);
Ok(()) Ok(())
}, },
None => Err(ErrorStatus::UnknownError), None => Err(ErrorStatus::UnknownError),
@ -1072,6 +1073,7 @@ pub fn handle_element_click(
pipeline: PipelineId, pipeline: PipelineId,
element_id: String, element_id: String,
reply: IpcSender<Result<Option<String>, ErrorStatus>>, reply: IpcSender<Result<Option<String>, ErrorStatus>>,
can_gc: CanGc,
) { ) {
reply reply
.send( .send(
@ -1122,7 +1124,7 @@ pub fn handle_element_click(
// Step 8.5 // Step 8.5
match parent_node.downcast::<HTMLElement>() { match parent_node.downcast::<HTMLElement>() {
Some(html_element) => html_element.Focus(), Some(html_element) => html_element.Focus(can_gc),
None => return Err(ErrorStatus::UnknownError), None => return Err(ErrorStatus::UnknownError),
} }