From 650afc9d3e0d351df493e11831b1c072f79e8889 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 12 Sep 2015 17:17:22 +0200 Subject: [PATCH 1/4] Fix cloning of Element's attributes No virtual method was invoked when copies of attributes were appended to newly-cloned elements. --- components/script/dom/element.rs | 6 +--- components/script/dom/node.rs | 15 ++++----- .../dom/nodes/Element-matches.html.ini | 12 ------- .../ParentNode-querySelector-All.html.ini | 33 ++----------------- 4 files changed, 10 insertions(+), 56 deletions(-) diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index bd522dccf0a..87804d373fd 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -83,7 +83,7 @@ use url::UrlParser; use std::ascii::AsciiExt; use std::borrow::{Cow, ToOwned}; -use std::cell::{Ref, RefMut}; +use std::cell::Ref; use std::default::Default; use std::mem; use std::sync::Arc; @@ -597,10 +597,6 @@ impl Element { self.attrs.borrow() } - pub fn attrs_mut(&self) -> RefMut>> { - self.attrs.borrow_mut() - } - pub fn style_attribute(&self) -> &DOMRefCell> { &self.style_attribute } diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index ae725d3d856..c9e78200c99 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -1768,15 +1768,12 @@ impl Node { let node_elem = ElementCast::to_ref(node).unwrap(); let copy_elem = ElementCast::to_ref(copy.r()).unwrap(); - let window = document.r().window(); - for ref attr in &*node_elem.attrs() { - let attr = attr.root(); - let newattr = - Attr::new(window.r(), - attr.r().local_name().clone(), attr.r().value().clone(), - attr.r().name().clone(), attr.r().namespace().clone(), - attr.r().prefix().clone(), Some(copy_elem)); - copy_elem.attrs_mut().push(JS::from_rooted(&newattr)); + for attr in node_elem.attrs().iter().map(JS::root) { + copy_elem.push_new_attribute(attr.local_name().clone(), + attr.value().clone(), + attr.name().clone(), + attr.namespace().clone(), + attr.prefix().clone()); } }, _ => () diff --git a/tests/wpt/metadata/dom/nodes/Element-matches.html.ini b/tests/wpt/metadata/dom/nodes/Element-matches.html.ini index cf9f112738c..657462fd41c 100644 --- a/tests/wpt/metadata/dom/nodes/Element-matches.html.ini +++ b/tests/wpt/metadata/dom/nodes/Element-matches.html.ini @@ -27,12 +27,6 @@ [Detached Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en)] expected: FAIL - [Detached Element.matches: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled] - expected: FAIL - - [Detached Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked] - expected: FAIL - [Fragment Element.matches: Attribute hyphen-separated list selector, matching lang attribute with partial value (with no refNodes): #attr-hyphen-div3[lang|="en"\]] expected: FAIL @@ -42,12 +36,6 @@ [Fragment Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en)] expected: FAIL - [Fragment Element.matches: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled] - expected: FAIL - - [Fragment Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked] - expected: FAIL - [In-document Element.matches: Universal selector, matching all children of the specified reference element (with refNode Element): >*] expected: FAIL diff --git a/tests/wpt/metadata/dom/nodes/ParentNode-querySelector-All.html.ini b/tests/wpt/metadata/dom/nodes/ParentNode-querySelector-All.html.ini index a99874300b0..8a083c760ac 100644 --- a/tests/wpt/metadata/dom/nodes/ParentNode-querySelector-All.html.ini +++ b/tests/wpt/metadata/dom/nodes/ParentNode-querySelector-All.html.ini @@ -120,21 +120,6 @@ [Detached Element.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR)] expected: FAIL - [Detached Element.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled] - expected: FAIL - - [Detached Element.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled] - expected: FAIL - - [Detached Element.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled] - expected: FAIL - - [Detached Element.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked] - expected: FAIL - - [Detached Element.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked] - expected: FAIL - [Detached Element.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line] expected: FAIL @@ -201,21 +186,6 @@ [Fragment.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR)] expected: FAIL - [Fragment.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled] - expected: FAIL - - [Fragment.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled] - expected: FAIL - - [Fragment.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled] - expected: FAIL - - [Fragment.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked] - expected: FAIL - - [Fragment.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked] - expected: FAIL - [Fragment.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line] expected: FAIL @@ -759,3 +729,6 @@ [In-document Element.querySelectorAll: Syntax, group of selectors separator, no whitespace: #group em,#group strong] expected: FAIL + [In-document Element.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled] + expected: FAIL + From cba885630903cc58fe31b8651ea4e5a37c4bcf8d Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 13 Sep 2015 02:47:34 +0200 Subject: [PATCH 2/4] Fix Node::query_selector() and Node::query_selector_iter() These should not find the root of the tree to start matching. --- components/script/dom/node.rs | 13 +- .../ParentNode-querySelector-All.html.ini | 450 ------------------ 2 files changed, 5 insertions(+), 458 deletions(-) diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index c9e78200c99..419909fa11e 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -812,18 +812,17 @@ impl Node { Err(()) => Err(Syntax), // Step 3. Ok(ref selectors) => { - let root = self.ancestors().last(); - let root = root.r().unwrap_or(self.clone()); - Ok(root.traverse_preorder().filter_map(ElementCast::to_root).find(|element| { + Ok(self.traverse_preorder().filter_map(ElementCast::to_root).find(|element| { matches(selectors, element, None) })) } } } + /// https://dom.spec.whatwg.org/#scope-match-a-selectors-string /// Get an iterator over all nodes which match a set of selectors - /// Be careful not to do anything which may manipulate the DOM tree whilst iterating, otherwise - /// the iterator may be invalidated + /// Be careful not to do anything which may manipulate the DOM tree + /// whilst iterating, otherwise the iterator may be invalidated. #[allow(unsafe_code)] pub unsafe fn query_selector_iter(&self, selectors: DOMString) -> Fallible { @@ -833,9 +832,7 @@ impl Node { Err(()) => Err(Syntax), // Step 3. Ok(selectors) => { - let root = self.ancestors().last(); - let root = root.r().unwrap_or(self); - Ok(QuerySelectorIterator::new(root.traverse_preorder(), selectors)) + Ok(QuerySelectorIterator::new(self.traverse_preorder(), selectors)) } } } diff --git a/tests/wpt/metadata/dom/nodes/ParentNode-querySelector-All.html.ini b/tests/wpt/metadata/dom/nodes/ParentNode-querySelector-All.html.ini index 8a083c760ac..15b76b64b57 100644 --- a/tests/wpt/metadata/dom/nodes/ParentNode-querySelector-All.html.ini +++ b/tests/wpt/metadata/dom/nodes/ParentNode-querySelector-All.html.ini @@ -210,276 +210,18 @@ [Fragment.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter] expected: FAIL - [In-document Element.querySelectorAll: Type selector, matching html element: html] - expected: FAIL - - [In-document Element.querySelector: Type selector, matching html element: html] - expected: FAIL - - [In-document Element.querySelectorAll: Type selector, matching body element: body] - expected: FAIL - - [In-document Element.querySelector: Type selector, matching body element: body] - expected: FAIL - - [In-document Element.querySelectorAll: Universal selector, matching all children of element with specified ID: #universal>*] - expected: FAIL - - [In-document Element.querySelectorAll: Universal selector, matching all grandchildren of element with specified ID: #universal>*>*] - expected: FAIL - - [In-document Element.querySelectorAll: Universal selector, matching all descendants of element with specified ID: #universal *] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute presence selector, matching align attribute with value: .attr-presence-div1[align\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute presence selector, matching align attribute with empty value: .attr-presence-div2[align\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute presence selector, matching title attribute, case insensitivity: #attr-presence [TiTlE\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute presence selector, matching custom data-* attribute: [data-attr-presence\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute presence selector, matching attribute with non-ASCII characters: ul[data-中文\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute presence selector, matching option with selected attribute: #attr-presence-select2 option[selected\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute presence selector, matching multiple options with selected attributes: #attr-presence-select3 option[selected\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute value selector, matching align attribute with value: #attr-value [align="center"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute value selector, matching align attribute with empty value: #attr-value [align=""\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute value selector, matching custom data-* attribute with unicode escaped value: [data-attr-value="\\e9"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute value selector, matching custom data-* attribute with escaped character: [data-attr-value_foo="\\e9"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute value selector with single-quoted value, matching multiple inputs with type attributes: #attr-value input[type='hidden'\],#attr-value input[type='radio'\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute value selector with double-quoted value, matching multiple inputs with type attributes: #attr-value input[type="hidden"\],#attr-value input[type='radio'\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute value selector with unquoted value, matching multiple inputs with type attributes: #attr-value input[type=hidden\],#attr-value input[type=radio\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute value selector, matching attribute with value using non-ASCII characters: [data-attr-value=中文\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute whitespace-separated list selector, matching class attribute with value: #attr-whitespace [class~="div1"\]] - expected: FAIL - [In-document Element.querySelectorAll: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""\]] expected: FAIL [In-document Element.querySelector: Attribute whitespace-separated list selector, not matching class attribute with empty value: #attr-whitespace [class~=""\]] expected: FAIL - [In-document Element.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value: [data-attr-whitespace~="\\0000e9"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character: [data-attr-whitespace_foo~="\\e9"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~='bookmark'\], #attr-whitespace a[rel~='nofollow'\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~="bookmark"\],#attr-whitespace a[rel~='nofollow'\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes: #attr-whitespace a[rel~=bookmark\], #attr-whitespace a[rel~=nofollow\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters: #attr-whitespace [title~=中文\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with exact value: #attr-hyphen-div2[lang|="fr"\]] - expected: FAIL - [In-document Element.querySelectorAll: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"\]] expected: FAIL [In-document Element.querySelector: Attribute hyphen-separated list selector, matching lang attribute with partial value: #attr-hyphen-div3[lang|="en"\]] expected: FAIL - [In-document Element.querySelectorAll: Attribute begins with selector, matching href attributes beginning with specified substring: #attr-begins a[href^="http://www"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute begins with selector, matching lang attributes beginning with specified substring, : #attr-begins [lang^="en-"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=' apple'\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring: #attr-begins [class^=" apple"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute ends with selector, matching href attributes ending with specified substring: #attr-ends a[href$=".org"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute ends with selector, matching lang attributes ending with specified substring, : #attr-ends [lang$="-CH"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring: #attr-ends [class$='apple '\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring: #attr-ends [class$="apple "\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector, matching href attributes beginning with specified substring: #attr-contains a[href*="http://www"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector, matching href attributes ending with specified substring: #attr-contains a[href*=".org"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector, matching href attributes containing specified substring: #attr-contains a[href*=".example."\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector, matching lang attributes beginning with specified substring, : #attr-contains [lang*="en-"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector, matching lang attributes ending with specified substring, : #attr-contains [lang*="-CH"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=' apple'\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute ending with specified substring: #attr-contains [class*='orange '\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector with single-quoted value, matching class attribute containing specified substring: #attr-contains [class*='ple banana ora'\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring: #attr-contains [class*=" apple"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute ending with specified substring: #attr-contains [class*="orange "\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector with double-quoted value, matching class attribute containing specified substring: #attr-contains [class*="ple banana ora"\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute beginning with specified substring: #attr-contains [class*= apple\]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute ending with specified substring: #attr-contains [class*=orange \]] - expected: FAIL - - [In-document Element.querySelectorAll: Attribute contains selector with unquoted value, matching class attribute containing specified substring: #attr-contains [class*= banana \]] - expected: FAIL - - [In-document Element.querySelectorAll: :root pseudo-class selector, not matching document root element: :root] - expected: FAIL - - [In-document Element.querySelector: :root pseudo-class selector, not matching document root element: :root] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-child selector, matching the third child element: #pseudo-nth-table1 :nth-child(3)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-child selector, matching every third child element: #pseudo-nth li:nth-child(3n)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-child selector, matching every second child element, starting from the fourth: #pseudo-nth li:nth-child(2n+4)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-child selector, matching every fourth child element, starting from the third: #pseudo-nth-p1 :nth-child(4n-1)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-last-child selector, matching the third last child element: #pseudo-nth-table1 :nth-last-child(3)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-last-child selector, matching every third child element from the end: #pseudo-nth li:nth-last-child(3n)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-last-child selector, matching every second child element from the end, starting from the fourth last: #pseudo-nth li:nth-last-child(2n+4)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-last-child selector, matching every fourth element from the end, starting from the third last: #pseudo-nth-p1 :nth-last-child(4n-1)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-of-type selector, matching the third em element: #pseudo-nth-p1 em:nth-of-type(3)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-of-type selector, matching every second element of their type: #pseudo-nth-p1 :nth-of-type(2n)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-of-type selector, matching every second elemetn of their type, starting from the first: #pseudo-nth-p1 span:nth-of-type(2n-1)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-last-of-type selector, matching the thrid last em element: #pseudo-nth-p1 em:nth-last-of-type(3)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type: #pseudo-nth-p1 :nth-last-of-type(2n)] - expected: FAIL - - [In-document Element.querySelectorAll: :nth-last-of-type selector, matching every second last element of their type, starting from the last: #pseudo-nth-p1 span:nth-last-of-type(2n-1)] - expected: FAIL - - [In-document Element.querySelectorAll: :first-of-type selector, matching the first em element: #pseudo-nth-p1 em:first-of-type] - expected: FAIL - - [In-document Element.querySelectorAll: :first-of-type selector, matching the first of every type of element: #pseudo-nth-p1 :first-of-type] - expected: FAIL - - [In-document Element.querySelectorAll: :first-of-type selector, matching the first td element in each table row: #pseudo-nth-table1 tr :first-of-type] - expected: FAIL - - [In-document Element.querySelectorAll: :last-of-type selector, matching the last em elemnet: #pseudo-nth-p1 em:last-of-type] - expected: FAIL - - [In-document Element.querySelectorAll: :last-of-type selector, matching the last of every type of element: #pseudo-nth-p1 :last-of-type] - expected: FAIL - - [In-document Element.querySelectorAll: :last-of-type selector, matching the last td element in each table row: #pseudo-nth-table1 tr :last-of-type] - expected: FAIL - - [In-document Element.querySelectorAll: :first-child pseudo-class selector, matching first child div element: #pseudo-first-child div:first-child] - expected: FAIL - - [In-document Element.querySelectorAll: :first-child pseudo-class selector, matching first-child of multiple elements: #pseudo-first-child span:first-child] - expected: FAIL - - [In-document Element.querySelectorAll: :last-child pseudo-class selector, matching last child div element: #pseudo-last-child div:last-child] - expected: FAIL - - [In-document Element.querySelectorAll: :last-child pseudo-class selector, matching first-child of multiple elements: #pseudo-last-child span:last-child] - expected: FAIL - - [In-document Element.querySelectorAll: :pseudo-only-child pseudo-class selector, matching all only-child elements: #pseudo-only :only-child] - expected: FAIL - - [In-document Element.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type: #pseudo-only :only-of-type] - expected: FAIL - - [In-document Element.querySelectorAll: :pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type: #pseudo-only em:only-of-type] - expected: FAIL - - [In-document Element.querySelectorAll: :empty pseudo-class selector, matching empty p elements: #pseudo-empty p:empty] - expected: FAIL - - [In-document Element.querySelectorAll: :empty pseudo-class selector, matching all empty elements: #pseudo-empty :empty] - expected: FAIL - - [In-document Element.querySelectorAll: :link and :visited pseudo-class selectors, matching a and area elements with href attributes: #pseudo-link :link, #pseudo-link :visited] - expected: FAIL - - [In-document Element.querySelectorAll: :link and :visited pseudo-class selectors, not matching link elements with href attributes: #head :link, #head :visited] - expected: FAIL - - [In-document Element.querySelector: :link and :visited pseudo-class selectors, not matching link elements with href attributes: #head :link, #head :visited] - expected: FAIL - [In-document Element.querySelectorAll: :target pseudo-class selector, matching the element referenced by the URL fragment identifier: :target] expected: FAIL @@ -510,21 +252,12 @@ [In-document Element.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR)] expected: FAIL - [In-document Element.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled] - expected: FAIL - [In-document Element.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked] expected: FAIL [In-document Element.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked] expected: FAIL - [In-document Element.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div)] - expected: FAIL - - [In-document Element.querySelectorAll: :not pseudo-class selector, matching : #not * :not(:first-child)] - expected: FAIL - [In-document Element.querySelectorAll: :first-line pseudo-element (one-colon syntax) selector, not matching any elements: #pseudo-element:first-line] expected: FAIL @@ -549,186 +282,3 @@ [In-document Element.querySelector: ::first-letter pseudo-element (two-colon syntax) selector, not matching any elements: #pseudo-element::first-letter] expected: FAIL - [In-document Element.querySelectorAll: Class selector, matching element with specified class: .class-p] - expected: FAIL - - [In-document Element.querySelectorAll: Class selector, chained, matching only elements with all specified classes: #class .apple.orange.banana] - expected: FAIL - - [In-document Element.querySelectorAll: Class Selector, chained, with type selector: div.apple.banana.orange] - expected: FAIL - - [In-document Element.querySelectorAll: Class selector, matching element with class value using non-ASCII characters: .台北Táiběi] - expected: FAIL - - [In-document Element.querySelectorAll: Class selector, matching multiple elements with class value using non-ASCII characters: .台北] - expected: FAIL - - [In-document Element.querySelectorAll: Class selector, chained, matching element with multiple class values using non-ASCII characters: .台北Táiběi.台北] - expected: FAIL - - [In-document Element.querySelectorAll: Class selector, matching element with class with escaped character: .foo\\:bar] - expected: FAIL - - [In-document Element.querySelectorAll: Class selector, matching element with class with escaped character: .test\\.foo\\[5\\\]bar] - expected: FAIL - - [In-document Element.querySelectorAll: ID selector, matching element with specified id: #id #id-div1] - expected: FAIL - - [In-document Element.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div1] - expected: FAIL - - [In-document Element.querySelectorAll: ID selector, chained, matching element with specified id: #id-div1, #id-div2] - expected: FAIL - - [In-document Element.querySelectorAll: ID Selector, chained, with type selector: div#id-div1, div#id-div2] - expected: FAIL - - [In-document Element.querySelectorAll: ID selector, matching multiple elements with duplicate id: #id-li-duplicate] - expected: FAIL - - [In-document Element.querySelectorAll: ID selector, matching id value using non-ASCII characters: #台北Táiběi] - expected: FAIL - - [In-document Element.querySelectorAll: ID selector, matching id value using non-ASCII characters: #台北] - expected: FAIL - - [In-document Element.querySelectorAll: ID selector, matching id values using non-ASCII characters: #台北Táiběi, #台北] - expected: FAIL - - [In-document Element.querySelectorAll: ID selector, matching element with id with escaped character: #\\#foo\\:bar] - expected: FAIL - - [In-document Element.querySelectorAll: ID selector, matching element with id with escaped character: #test\\.foo\\[5\\\]bar] - expected: FAIL - - [In-document Element.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div] - expected: FAIL - - [In-document Element.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div] - expected: FAIL - - [In-document Element.querySelectorAll: Namespace selector, matching any elements in no namespace only: #no-namespace |*] - expected: FAIL - - [In-document Element.querySelectorAll: Descendant combinator, matching element that is a descendant of an element with id: #descendant div] - expected: FAIL - - [In-document Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: body #descendant-div1] - expected: FAIL - - [In-document Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element: div #descendant-div1] - expected: FAIL - - [In-document Element.querySelectorAll: Descendant combinator, matching element with id that is a descendant of an element with id: #descendant #descendant-div2] - expected: FAIL - - [In-document Element.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with id: #descendant .descendant-div2] - expected: FAIL - - [In-document Element.querySelectorAll: Descendant combinator, matching element with class that is a descendant of an element with class: .descendant-div1 .descendant-div3] - expected: FAIL - - [In-document Element.querySelectorAll: Descendant combinator, whitespace characters: #descendant\t\r\n#descendant-div2] - expected: FAIL - - [In-document Element.querySelectorAll: Child combinator, matching element that is a child of an element with id: #child>div] - expected: FAIL - - [In-document Element.querySelectorAll: Child combinator, matching element with id that is a child of an element: div>#child-div1] - expected: FAIL - - [In-document Element.querySelectorAll: Child combinator, matching element with id that is a child of an element with id: #child>#child-div1] - expected: FAIL - - [In-document Element.querySelectorAll: Child combinator, matching element with id that is a child of an element with class: #child-div1>.child-div2] - expected: FAIL - - [In-document Element.querySelectorAll: Child combinator, matching element with class that is a child of an element with class: .child-div1>.child-div2] - expected: FAIL - - [In-document Element.querySelectorAll: Child combinator, surrounded by whitespace: #child-div1\t\r\n>\t\r\n#child-div2] - expected: FAIL - - [In-document Element.querySelectorAll: Child combinator, whitespace after: #child-div1>\t\r\n#child-div2] - expected: FAIL - - [In-document Element.querySelectorAll: Child combinator, whitespace before: #child-div1\t\r\n>#child-div2] - expected: FAIL - - [In-document Element.querySelectorAll: Child combinator, no whitespace: #child-div1>#child-div2] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id: #adjacent-div2+div] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element: div+#adjacent-div4] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id: #adjacent-div2+#adjacent-div4] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id: #adjacent-div2+.adjacent-div4] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class: .adjacent-div2+.adjacent-div4] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element: #adjacent div+p] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, surrounded by whitespace: #adjacent-p2\t\r\n+\t\r\n#adjacent-p3] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, whitespace after: #adjacent-p2+\t\r\n#adjacent-p3] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, whitespace before: #adjacent-p2\t\r\n+#adjacent-p3] - expected: FAIL - - [In-document Element.querySelectorAll: Adjacent sibling combinator, no whitespace: #adjacent-p2+#adjacent-p3] - expected: FAIL - - [In-document Element.querySelectorAll: General sibling combinator, matching element that is a sibling of an element with id: #sibling-div2~div] - expected: FAIL - - [In-document Element.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element: div~#sibling-div4] - expected: FAIL - - [In-document Element.querySelectorAll: General sibling combinator, matching element with id that is a sibling of an element with id: #sibling-div2~#sibling-div4] - expected: FAIL - - [In-document Element.querySelectorAll: General sibling combinator, matching element with class that is a sibling of an element with id: #sibling-div2~.sibling-div] - expected: FAIL - - [In-document Element.querySelectorAll: General sibling combinator, matching p element that is a sibling of a div element: #sibling div~p] - expected: FAIL - - [In-document Element.querySelectorAll: General sibling combinator, surrounded by whitespace: #sibling-p2\t\r\n~\t\r\n#sibling-p3] - expected: FAIL - - [In-document Element.querySelectorAll: General sibling combinator, whitespace after: #sibling-p2~\t\r\n#sibling-p3] - expected: FAIL - - [In-document Element.querySelectorAll: General sibling combinator, whitespace before: #sibling-p2\t\r\n~#sibling-p3] - expected: FAIL - - [In-document Element.querySelectorAll: General sibling combinator, no whitespace: #sibling-p2~#sibling-p3] - expected: FAIL - - [In-document Element.querySelectorAll: Syntax, group of selectors separator, surrounded by whitespace: #group em\t\r \n,\t\r \n#group strong] - expected: FAIL - - [In-document Element.querySelectorAll: Syntax, group of selectors separator, whitespace after: #group em,\t\r\n#group strong] - expected: FAIL - - [In-document Element.querySelectorAll: Syntax, group of selectors separator, whitespace before: #group em\t\r\n,#group strong] - expected: FAIL - - [In-document Element.querySelectorAll: Syntax, group of selectors separator, no whitespace: #group em,#group strong] - expected: FAIL - - [In-document Element.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled] - expected: FAIL - From ea655ada10cca75423dc5380ee26779e09c26883 Mon Sep 17 00:00:00 2001 From: Ali Sabil Date: Thu, 23 Jul 2015 23:04:48 +0200 Subject: [PATCH 3/4] Cache the `id` attribute on Element --- components/script/dom/element.rs | 38 +++++++++++++++----------------- tests/unit/script/size_of.rs | 8 +++---- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 87804d373fd..0ca9c3c3f90 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -95,6 +95,7 @@ pub struct Element { namespace: Namespace, prefix: Option, attrs: DOMRefCell>>, + id_attribute: DOMRefCell>, style_attribute: DOMRefCell>, attr_list: MutNullableHeap>, class_list: MutNullableHeap>, @@ -149,6 +150,7 @@ impl Element { attrs: DOMRefCell::new(vec!()), attr_list: Default::default(), class_list: Default::default(), + id_attribute: DOMRefCell::new(None), style_attribute: DOMRefCell::new(None), } } @@ -1466,6 +1468,15 @@ impl VirtualMethods for Element { NodeDamage::NodeStyleDamaged }, &atom!(id) => { + *self.id_attribute.borrow_mut() = + mutation.new_value(attr).and_then(|value| { + let value = value.as_atom(); + if value != &atom!("") { + Some(value.clone()) + } else { + None + } + }); if node.is_in_doc() { let value = attr.value().as_atom().clone(); match mutation { @@ -1512,13 +1523,9 @@ impl VirtualMethods for Element { if !tree_in_doc { return; } - if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) { - let value = attr.value(); - if !value.is_empty() { - let doc = document_from_node(self); - let value = Atom::from_slice(&value); - doc.register_named_element(self, value.to_owned()); - } + if let Some(ref value) = *self.id_attribute.borrow() { + let doc = document_from_node(self); + doc.register_named_element(self, value.clone()); } } @@ -1529,13 +1536,9 @@ impl VirtualMethods for Element { if !tree_in_doc { return; } - if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) { - let value = attr.value(); - if !value.is_empty() { - let doc = document_from_node(self); - let value = Atom::from_slice(&value); - doc.unregister_named_element(self, value.to_owned()); - } + if let Some(ref value) = *self.id_attribute.borrow() { + let doc = document_from_node(self); + doc.unregister_named_element(self, value.clone()); } } } @@ -1621,12 +1624,7 @@ impl<'a> ::selectors::Element for Root { node.get_focus_state() } fn get_id(&self) -> Option { - self.get_attribute(&ns!(""), &atom!("id")).map(|attr| { - match *attr.r().value() { - AttrValue::Atom(ref val) => val.clone(), - _ => panic!("`id` attribute should be AttrValue::Atom"), - } - }) + self.id_attribute.borrow().clone() } fn get_disabled_state(&self) -> bool { let node = NodeCast::from_ref(&**self); diff --git a/tests/unit/script/size_of.rs b/tests/unit/script/size_of.rs index 1b34e462470..7eec6699f19 100644 --- a/tests/unit/script/size_of.rs +++ b/tests/unit/script/size_of.rs @@ -40,9 +40,9 @@ macro_rules! sizeof_checker ( // Update the sizes here sizeof_checker!(size_event_target, EventTarget, 40); sizeof_checker!(size_node, Node, 168); -sizeof_checker!(size_element, Element, 280); -sizeof_checker!(size_htmlelement, HTMLElement, 296); -sizeof_checker!(size_div, HTMLDivElement, 296); -sizeof_checker!(size_span, HTMLSpanElement, 296); +sizeof_checker!(size_element, Element, 304); +sizeof_checker!(size_htmlelement, HTMLElement, 320); +sizeof_checker!(size_div, HTMLDivElement, 320); +sizeof_checker!(size_span, HTMLSpanElement, 320); sizeof_checker!(size_text, Text, 200); sizeof_checker!(size_characterdata, CharacterData, 200); From 2e9d8a76d15d478b90fffb235ace1293ed329231 Mon Sep 17 00:00:00 2001 From: Ali Sabil Date: Fri, 7 Aug 2015 12:33:06 +0200 Subject: [PATCH 4/4] Use cached element ID in LayoutElement::get_id --- components/layout/wrapper.rs | 2 +- components/script/dom/element.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index d346e97a40e..28e57417c84 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -487,7 +487,7 @@ impl<'le> ::selectors::Element for LayoutElement<'le> { #[inline] fn get_id(&self) -> Option { unsafe { - (*self.element.unsafe_get()).get_attr_atom_for_layout(&ns!(""), &atom!("id")) + (*self.element.id_attribute()).clone() } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 0ca9c3c3f90..bedce2ed975 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -494,6 +494,7 @@ pub trait LayoutElementHelpers { unsafe fn html_element_in_html_document_for_layout(&self) -> bool; #[allow(unsafe_code)] unsafe fn has_attr_for_layout(&self, namespace: &Namespace, name: &Atom) -> bool; + fn id_attribute(&self) -> *const Option; fn style_attribute(&self) -> *const Option; fn local_name(&self) -> &Atom; fn namespace(&self) -> &Namespace; @@ -517,6 +518,13 @@ impl LayoutElementHelpers for LayoutJS { get_attr_for_layout(&*self.unsafe_get(), namespace, name).is_some() } + #[allow(unsafe_code)] + fn id_attribute(&self) -> *const Option { + unsafe { + (*self.unsafe_get()).id_attribute.borrow_for_layout() + } + } + #[allow(unsafe_code)] fn style_attribute(&self) -> *const Option { unsafe {