From 10869f66b57d70ad95117393ee13b45c375a7634 Mon Sep 17 00:00:00 2001 From: Patrick Shaughnessy Date: Wed, 22 Jan 2020 18:44:33 -0500 Subject: [PATCH] Prevent infinite recursion when upgrading custom elements --- .../script/dom/customelementregistry.rs | 22 +++++++++---------- components/script/dom/element.rs | 4 ++++ .../custom-elements/upgrading.html.ini | 7 ------ 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index 392cf49cce5..a7325315605 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -586,13 +586,17 @@ impl CustomElementDefinition { /// #[allow(unsafe_code)] pub fn upgrade_element(definition: Rc, element: &Element) { - // Steps 1-2 + // Step 1 let state = element.get_custom_element_state(); - if state == CustomElementState::Custom || state == CustomElementState::Failed { + if state != CustomElementState::Undefined && state != CustomElementState::Uncustomized { return; } - // Step 3 happens later to save having to undo it in an exception + // Step 2 + element.set_custom_element_definition(Rc::clone(&definition)); + + // Step 3 + element.set_custom_element_state(CustomElementState::Failed); // Step 4 for attr in element.attrs().iter() { @@ -630,14 +634,12 @@ pub fn upgrade_element(definition: Rc, element: &Elemen // Step 8 exception handling if let Err(error) = result { // Step 8.exception.1 - element.set_custom_element_state(CustomElementState::Failed); + element.clear_custom_element_definition(); - // Step 8.exception.2 isn't needed since step 3 hasn't happened yet - - // Step 8.exception.3 + // Step 8.exception.2 element.clear_reaction_queue(); - // Step 8.exception.4 + // Step 8.exception.3 let global = GlobalScope::current().expect("No current global"); let cx = global.get_cx(); unsafe { @@ -651,11 +653,7 @@ pub fn upgrade_element(definition: Rc, element: &Elemen // TODO Step 9: "If element is a form-associated custom element..." // Step 10 - element.set_custom_element_state(CustomElementState::Custom); - - // Step 3 - element.set_custom_element_definition(definition); } /// diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index cb7d339a78e..29bdaf2f3bf 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -342,6 +342,10 @@ impl Element { self.rare_data().as_ref()?.custom_element_definition.clone() } + pub fn clear_custom_element_definition(&self) { + self.ensure_rare_data().custom_element_definition = None; + } + pub fn push_callback_reaction(&self, function: Rc, args: Box<[Heap]>) { self.ensure_rare_data() .custom_element_reaction_queue diff --git a/tests/wpt/metadata/custom-elements/upgrading.html.ini b/tests/wpt/metadata/custom-elements/upgrading.html.ini index e8aee585a04..a58c89d4e3f 100644 --- a/tests/wpt/metadata/custom-elements/upgrading.html.ini +++ b/tests/wpt/metadata/custom-elements/upgrading.html.ini @@ -4,10 +4,3 @@ [If definition's disable shadow is true and element's shadow root is non-null, then throw a "NotSupportedError" DOMException.] expected: FAIL - - [Infinite constructor recursion with upgrade(this) should not be possible] - expected: FAIL - - [Infinite constructor recursion with appendChild should not be possible] - expected: FAIL -