Index: Source/web/WebFrameImpl.cpp |
diff --git a/Source/web/WebFrameImpl.cpp b/Source/web/WebFrameImpl.cpp |
index 487675737c5866caeae933894a3d329cbf423a31..80c0872ed419b65f2515389be62fbef57ea371b7 100644 |
--- a/Source/web/WebFrameImpl.cpp |
+++ b/Source/web/WebFrameImpl.cpp |
@@ -647,68 +647,90 @@ void WebFrameImpl::setOpener(const WebFrame* webFrame) |
void WebFrameImpl::appendChild(WebFrame* child) |
{ |
- // FIXME: Implement after this revision rolls into Chrome. |
+ // FIXME: Original code asserts that the frames have the same Page. We |
+ // should add an equivalent check... figure out what. |
+ WebFrameImpl* childImpl = toWebFrameImpl(child); |
+ childImpl->m_parent = this; |
+ WebFrameImpl* oldLast = m_lastChild; |
+ m_lastChild = childImpl; |
+ |
+ if (oldLast) { |
+ childImpl->m_previousSibling = oldLast; |
+ oldLast->m_nextSibling = childImpl; |
+ } else { |
+ m_firstChild = childImpl; |
+ } |
+ // FIXME: Not sure if this is a legitimate assert. |
+ ASSERT(frame()); |
+ frame()->tree().invalidateScopedChildCount(); |
} |
void WebFrameImpl::removeChild(WebFrame* child) |
{ |
- // FIXME: Implement after this revision rolls into Chrome. |
+ WebFrameImpl* childImpl = toWebFrameImpl(child); |
+ childImpl->m_parent = 0; |
+ |
+ if (m_firstChild == childImpl) |
+ m_firstChild = childImpl->m_nextSibling; |
+ else |
+ childImpl->m_previousSibling->m_nextSibling = childImpl->m_nextSibling; |
+ |
+ if (m_lastChild == childImpl) |
+ m_lastChild = childImpl->m_previousSibling; |
+ else |
+ childImpl->m_nextSibling->m_previousSibling = childImpl->m_previousSibling; |
+ |
+ childImpl->m_previousSibling = childImpl->m_nextSibling = 0; |
+ // FIXME: Not sure if this is a legitimate assert. |
+ ASSERT(frame()); |
+ frame()->tree().invalidateScopedChildCount(); |
} |
WebFrame* WebFrameImpl::parent() const |
{ |
- if (!frame()) |
- return 0; |
- return fromFrame(frame()->tree().parent()); |
+ return m_parent; |
} |
WebFrame* WebFrameImpl::top() const |
{ |
- if (!frame()) |
- return 0; |
- return fromFrame(frame()->tree().top()); |
+ WebFrameImpl* frame = const_cast<WebFrameImpl*>(this); |
+ for (WebFrameImpl* parent = frame; parent; parent = parent->m_parent) |
+ frame = parent; |
+ return frame; |
} |
-WebFrame* WebFrameImpl::firstChild() const |
+WebFrame* WebFrameImpl::previousSibling() const |
{ |
- if (!frame()) |
- return 0; |
- return fromFrame(frame()->tree().firstChild()); |
+ return m_previousSibling; |
} |
-WebFrame* WebFrameImpl::lastChild() const |
+WebFrame* WebFrameImpl::nextSibling() const |
{ |
- if (!frame()) |
- return 0; |
- return fromFrame(frame()->tree().lastChild()); |
+ return m_nextSibling; |
} |
-WebFrame* WebFrameImpl::nextSibling() const |
+WebFrame* WebFrameImpl::firstChild() const |
{ |
- if (!frame()) |
- return 0; |
- return fromFrame(frame()->tree().nextSibling()); |
+ return m_firstChild; |
} |
-WebFrame* WebFrameImpl::previousSibling() const |
+WebFrame* WebFrameImpl::lastChild() const |
{ |
- if (!frame()) |
- return 0; |
- return fromFrame(frame()->tree().previousSibling()); |
+ return m_lastChild; |
} |
-WebFrame* WebFrameImpl::traverseNext(bool wrap) const |
+WebFrame* WebFrameImpl::traversePrevious(bool wrap) const |
{ |
if (!frame()) |
return 0; |
- return fromFrame(frame()->tree().traverseNextWithWrap(wrap)); |
+ return fromFrame(frame()->tree().traversePreviousWithWrap(wrap)); |
} |
-WebFrame* WebFrameImpl::traversePrevious(bool wrap) const |
+WebFrame* WebFrameImpl::traverseNext(bool wrap) const |
{ |
if (!frame()) |
return 0; |
- return fromFrame(frame()->tree().traversePreviousWithWrap(wrap)); |
+ return fromFrame(frame()->tree().traverseNextWithWrap(wrap)); |
} |
WebFrame* WebFrameImpl::findChildByName(const WebString& name) const |
@@ -2093,6 +2115,11 @@ WebFrameImpl* WebFrameImpl::create(WebFrameClient* client, long long embedderIde |
WebFrameImpl::WebFrameImpl(WebFrameClient* client, long long embedderIdentifier) |
: m_frameInit(WebFrameInit::create(this, embedderIdentifier)) |
+ , m_parent(0) |
+ , m_previousSibling(0) |
+ , m_nextSibling(0) |
+ , m_firstChild(0) |
+ , m_lastChild(0) |
, m_client(client) |
, m_permissionClient(0) |
, m_currentActiveMatchFrame(0) |
@@ -2151,8 +2178,7 @@ PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request |
childFrame->tree().setName(request.frameName()); |
- frame()->tree().appendChild(childFrame); |
- |
+ // FIXME: This comment is not quite accurate anymore. |
// Frame::init() can trigger onload event in the parent frame, |
// which may detach this frame and trigger a null-pointer access |
// in FrameTree::removeChild. Move init() after appendChild call |