diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index 392cf49cce5..3b0c4ecc18b 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -21,6 +21,7 @@ use crate::dom::bindings::error::{ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::bindings::settings_stack::is_execution_stack_empty; use crate::dom::bindings::str::DOMString; use crate::dom::document::Document; use crate::dom::domexception::{DOMErrorName, DOMException}; @@ -543,6 +544,14 @@ impl CustomElementDefinition { } } + // https://heycam.github.io/webidl/#construct-a-callback-function + // https://html.spec.whatwg.org/multipage/#clean-up-after-running-script + if is_execution_stack_empty() { + window + .upcast::() + .perform_a_microtask_checkpoint(); + } + rooted!(in(*cx) let element_val = ObjectValue(element.get())); let element: DomRoot = match unsafe { DomRoot::from_jsval(*cx, element_val.handle(), ()) } { @@ -690,6 +699,15 @@ fn run_upgrade_constructor( } { return Err(Error::JSFailed); } + + // https://heycam.github.io/webidl/#construct-a-callback-function + // https://html.spec.whatwg.org/multipage/#clean-up-after-running-script + if is_execution_stack_empty() { + window + .upcast::() + .perform_a_microtask_checkpoint(); + } + // Step 8.3 let mut same = false; rooted!(in(*cx) let construct_result_val = ObjectValue(construct_result.get())); diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index fd2a58f8d7d..4d6ce97c1e7 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -823,6 +823,8 @@ impl HTMLImageElement { // Step 8 Some(data) => data, None => { + self.abort_request(State::Broken, ImageRequestPhase::Current); + self.abort_request(State::Broken, ImageRequestPhase::Pending); // Step 9. // FIXME(nox): Why are errors silenced here? let _ = task_source.queue( @@ -840,11 +842,6 @@ impl HTMLImageElement { if src_present || Self::uses_srcset_or_picture(elem) { this.upcast::().fire_event(atom!("error")); } - // FIXME(nox): According to the spec, setting the current - // request to the broken state is done prior to queuing a - // task, why is this here? - this.abort_request(State::Broken, ImageRequestPhase::Current); - this.abort_request(State::Broken, ImageRequestPhase::Pending); }), window.upcast(), ); @@ -861,6 +858,8 @@ impl HTMLImageElement { self.prepare_image_request(&url, &src, pixel_density); }, Err(_) => { + self.abort_request(State::Broken, ImageRequestPhase::Current); + self.abort_request(State::Broken, ImageRequestPhase::Pending); // Step 12.1-12.5. let src = src.0; // FIXME(nox): Why are errors silenced here? @@ -874,11 +873,6 @@ impl HTMLImageElement { } this.upcast::().fire_event(atom!("error")); - // FIXME(nox): According to the spec, setting the current - // request to the broken state is done prior to queuing a - // task, why is this here? - this.abort_request(State::Broken, ImageRequestPhase::Current); - this.abort_request(State::Broken, ImageRequestPhase::Pending); }), window.upcast(), ); diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index 40f3da3c78e..1e172db35fd 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -558,6 +558,19 @@ impl ServoParser { Err(script) => script, }; + // https://html.spec.whatwg.org/multipage/#parsing-main-incdata + // branch "An end tag whose tag name is "script" + // The spec says to perform the microtask checkpoint before + // setting the insertion mode back from Text, but this is not + // possible with the way servo and html5ever currently + // relate to each other, and hopefully it is not observable. + if is_execution_stack_empty() { + self.document + .window() + .upcast::() + .perform_a_microtask_checkpoint(); + } + let script_nesting_level = self.script_nesting_level.get(); self.script_nesting_level.set(script_nesting_level + 1); diff --git a/components/script/microtask.rs b/components/script/microtask.rs index 43628f46331..6241b6f63a0 100644 --- a/components/script/microtask.rs +++ b/components/script/microtask.rs @@ -90,6 +90,8 @@ impl MicrotaskQueue { // Step 1 self.performing_a_microtask_checkpoint.set(true); + debug!("Now performing a microtask checkpoint"); + // Steps 2 while !self.microtask_queue.borrow().is_empty() { rooted_vec!(let mut pending_queue); diff --git a/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini b/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini deleted file mode 100644 index cc30607acbd..00000000000 --- a/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini +++ /dev/null @@ -1,10 +0,0 @@ -[microtasks-and-constructors.html] - [Microtasks evaluate immediately when the stack is empty inside the parser] - expected: FAIL - - [Microtasks evaluate immediately when the stack is empty inside the parser, causing the checks on no attributes to fail] - expected: FAIL - - [Microtasks evaluate afterward when the stack is not empty using createElement()] - expected: FAIL - diff --git a/tests/wpt/metadata/dom/nodes/MutationObserver-document.html.ini b/tests/wpt/metadata/dom/nodes/MutationObserver-document.html.ini deleted file mode 100644 index 1b5555582d7..00000000000 --- a/tests/wpt/metadata/dom/nodes/MutationObserver-document.html.ini +++ /dev/null @@ -1,11 +0,0 @@ -[MutationObserver-document.html] - type: testharness - [parser insertion mutations] - expected: FAIL - - [parser script insertion mutation] - expected: FAIL - - [removal of parent during parsing] - expected: FAIL -