aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-08-04 02:27:20 -0500
committerGitHub <noreply@github.com>2016-08-04 02:27:20 -0500
commit1837fcbedde8bb1bab7610d131aed0fd3e4f1462 (patch)
treea1576317c1a8f48fa2d19637f669e03fcaaab116 /components/script/dom
parent20b9ce6cff2a2e553a1eba4bf74d8f58a96b6e65 (diff)
parent1ca4a3e32f0b3377ef8acb95ce437233c10d96c8 (diff)
downloadservo-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.rs70
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;
+ }
+}