diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-08-04 02:27:20 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-08-04 02:27:20 -0500 |
commit | 1837fcbedde8bb1bab7610d131aed0fd3e4f1462 (patch) | |
tree | a1576317c1a8f48fa2d19637f669e03fcaaab116 /components/script/dom | |
parent | 20b9ce6cff2a2e553a1eba4bf74d8f58a96b6e65 (diff) | |
parent | 1ca4a3e32f0b3377ef8acb95ce437233c10d96c8 (diff) | |
download | servo-1837fcbedde8bb1bab7610d131aed0fd3e4f1462.tar.gz servo-1837fcbedde8bb1bab7610d131aed0fd3e4f1462.zip |
Auto merge of #11318 - mitchhentges:1471-cache-tag-name, r=nox
Compute tag_name a maximum of once per document owner
Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data:
- [x] `./mach build -d` does not report any errors
- [X] `./mach test-tidy --faster` does not report any errors
- [X] These changes fix #1471 (github issue number if applicable).
Either:
- [X] These changes do not require tests because no new functionality was added, just a reorganization and caching of existing functionality
Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11318)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/element.rs | 70 |
1 files changed, 59 insertions, 11 deletions
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index c0affb40aea..b9b02183762 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -103,6 +103,7 @@ use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage}; pub struct Element { node: Node, local_name: Atom, + tag_name: TagName, namespace: Namespace, prefix: Option<DOMString>, attrs: DOMRefCell<Vec<JS<Attr>>>, @@ -165,6 +166,7 @@ impl Element { Element { node: Node::new_inherited(document), local_name: local_name, + tag_name: TagName::new(), namespace: namespace, prefix: prefix, attrs: DOMRefCell::new(vec![]), @@ -1367,17 +1369,20 @@ impl ElementMethods for Element { // https://dom.spec.whatwg.org/#dom-element-tagname fn TagName(&self) -> DOMString { - let qualified_name = match self.prefix { - Some(ref prefix) => { - Cow::Owned(format!("{}:{}", &**prefix, &*self.local_name)) - }, - None => Cow::Borrowed(&*self.local_name) - }; - DOMString::from(if self.html_element_in_html_document() { - qualified_name.to_ascii_uppercase() - } else { - qualified_name.into_owned() - }) + let name = self.tag_name.or_init(|| { + let qualified_name = match self.prefix { + Some(ref prefix) => { + Cow::Owned(format!("{}:{}", &**prefix, &*self.local_name)) + }, + None => Cow::Borrowed(&*self.local_name) + }; + if self.html_element_in_html_document() { + Atom::from(qualified_name.to_ascii_uppercase()) + } else { + Atom::from(qualified_name) + } + }); + DOMString::from(&*name) } // https://dom.spec.whatwg.org/#dom-element-id @@ -2219,6 +2224,14 @@ impl VirtualMethods for Element { } } } + + fn adopting_steps(&self, old_doc: &Document) { + self.super_type().unwrap().adopting_steps(old_doc); + + if document_from_node(self).is_html_document() != old_doc.is_html_document() { + self.tag_name.clear(); + } + } } impl<'a> ::selectors::MatchAttrGeneric for Root<Element> { @@ -2691,3 +2704,38 @@ impl AtomicElementFlags { self.0.fetch_or(flags.bits() as usize, Ordering::Relaxed); } } + +/// A holder for an element's "tag name", which will be lazily +/// resolved and cached. Should be reset when the document +/// owner changes. +#[derive(JSTraceable, HeapSizeOf)] +struct TagName { + ptr: DOMRefCell<Option<Atom>>, +} + +impl TagName { + fn new() -> TagName { + TagName { ptr: DOMRefCell::new(None) } + } + + /// Retrieve a copy of the current inner value. If it is `None`, it is + /// initialized with the result of `cb` first. + fn or_init<F>(&self, cb: F) -> Atom + where F: FnOnce() -> Atom + { + match &mut *self.ptr.borrow_mut() { + &mut Some(ref name) => name.clone(), + ptr => { + let name = cb(); + *ptr = Some(name.clone()); + name + } + } + } + + /// Clear the cached tag name, so that it will be re-calculated the + /// next time that `or_init()` is called. + fn clear(&self) { + *self.ptr.borrow_mut() = None; + } +} |