diff options
Diffstat (limited to 'WebCore/bindings/js/JSNodeCustom.cpp')
-rw-r--r-- | WebCore/bindings/js/JSNodeCustom.cpp | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp index 2a4aa80..f375ae5 100644 --- a/WebCore/bindings/js/JSNodeCustom.cpp +++ b/WebCore/bindings/js/JSNodeCustom.cpp @@ -148,31 +148,34 @@ void JSNode::markChildren(MarkStack& markStack) return; } - // This is a node outside the document, so find the root of the tree it is in, - // and start marking from there. + // This is a node outside the document. + // Find the the root, and the highest ancestor with a wrapper. Node* root = node; - for (Node* current = m_impl.get(); current; current = current->parentNode()) + Node* outermostNodeWithWrapper = node; + for (Node* current = m_impl.get(); current; current = current->parentNode()) { root = current; + if (hasCachedDOMNodeWrapper(current->document(), current)) + outermostNodeWithWrapper = current; + } - // Nodes in a subtree are marked by the tree's root, so, if the root is already - // marking the tree, we don't need to explicitly mark any other nodes. - if (root->inSubtreeMark()) + // Only nodes that have no ancestors with wrappers mark the subtree. In the common + // case, the root of the detached subtree has a wrapper, so the tree will only + // get marked once. Nodes that aren't outermost need to mark the outermost + // in case it is otherwise unreachable. + if (node != outermostNodeWithWrapper) { + markDOMNodeWrapper(markStack, m_impl->document(), outermostNodeWithWrapper); return; + } // Mark the whole tree subtree. - root->setInSubtreeMark(true); - for (Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) { - JSNode* wrapper = getCachedDOMNodeWrapper(m_impl->document(), nodeToMark); - if (wrapper) - markStack.append(wrapper); - } - root->setInSubtreeMark(false); + for (Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) + markDOMNodeWrapper(markStack, m_impl->document(), nodeToMark); } static ALWAYS_INLINE JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) { ASSERT(node); - ASSERT(!getCachedDOMNodeWrapper(node->document(), node)); + ASSERT(!getCachedDOMNodeWrapper(exec, node->document(), node)); JSNode* wrapper; switch (node->nodeType()) { @@ -239,7 +242,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) if (!node) return jsNull(); - JSNode* wrapper = getCachedDOMNodeWrapper(node->document(), node); + JSNode* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node); if (wrapper) return wrapper; |