summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/js/JSNodeCustom.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/bindings/js/JSNodeCustom.cpp')
-rw-r--r--WebCore/bindings/js/JSNodeCustom.cpp33
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;