mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 1268320 - stop event tree processing if the document goes shutdown, r=yzen
This commit is contained in:
parent
b067cf32c4
commit
db7566fedf
@ -181,12 +181,15 @@ TreeMutation::Done()
|
||||
// EventTree
|
||||
|
||||
void
|
||||
EventTree::Process()
|
||||
EventTree::Process(const RefPtr<DocAccessible>& aDeathGrip)
|
||||
{
|
||||
while (mFirst) {
|
||||
// Skip a node and its subtree if its container is not in the document.
|
||||
if (mFirst->mContainer->IsInDocument()) {
|
||||
mFirst->Process();
|
||||
mFirst->Process(aDeathGrip);
|
||||
if (aDeathGrip->IsDefunct()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mFirst = mFirst->mNext.forget();
|
||||
}
|
||||
@ -195,6 +198,7 @@ EventTree::Process()
|
||||
"No container, no events");
|
||||
MOZ_ASSERT(!mContainer || !mContainer->IsDefunct(),
|
||||
"Processing events for defunct container");
|
||||
MOZ_ASSERT(!mFireReorder || mContainer, "No target for reorder event");
|
||||
|
||||
// Fire mutation events.
|
||||
uint32_t eventsCount = mDependentEvents.Length();
|
||||
@ -202,10 +206,18 @@ EventTree::Process()
|
||||
AccMutationEvent* mtEvent = mDependentEvents[jdx];
|
||||
MOZ_ASSERT(mtEvent->mEventRule != AccEvent::eDoNotEmit,
|
||||
"The event shouldn't be presented in the tree");
|
||||
MOZ_ASSERT(mtEvent->Document(), "No document for event target");
|
||||
|
||||
nsEventShell::FireEvent(mtEvent);
|
||||
if (aDeathGrip->IsDefunct()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mtEvent->mTextChangeEvent) {
|
||||
nsEventShell::FireEvent(mtEvent->mTextChangeEvent);
|
||||
if (aDeathGrip->IsDefunct()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mtEvent->IsHide()) {
|
||||
@ -221,18 +233,20 @@ EventTree::Process()
|
||||
if (mtEvent->mAccessible->ARIARole() == roles::MENUPOPUP) {
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
|
||||
mtEvent->mAccessible);
|
||||
if (aDeathGrip->IsDefunct()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AccHideEvent* hideEvent = downcast_accEvent(mtEvent);
|
||||
if (hideEvent->NeedsShutdown()) {
|
||||
mtEvent->Document()->ShutdownChildrenInSubtree(mtEvent->mAccessible);
|
||||
aDeathGrip->ShutdownChildrenInSubtree(mtEvent->mAccessible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fire reorder event at last.
|
||||
if (mFireReorder) {
|
||||
MOZ_ASSERT(mContainer);
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_REORDER, mContainer);
|
||||
mContainer->Document()->MaybeNotifyOfValueChange(mContainer);
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ private:
|
||||
/**
|
||||
* Processes the event queue and fires events.
|
||||
*/
|
||||
void Process();
|
||||
void Process(const RefPtr<DocAccessible>& aDeathGrip);
|
||||
|
||||
/**
|
||||
* Return an event subtree for the given accessible.
|
||||
|
@ -401,7 +401,9 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
// events causes script to run.
|
||||
mObservingState = eRefreshProcessing;
|
||||
|
||||
mEventTree.Process();
|
||||
RefPtr<DocAccessible> deathGrip(mDocument);
|
||||
mEventTree.Process(deathGrip);
|
||||
deathGrip = nullptr;
|
||||
|
||||
ProcessEventQueue();
|
||||
|
||||
|
@ -377,6 +377,58 @@
|
||||
}
|
||||
}
|
||||
|
||||
function hideNDestroyDoc()
|
||||
{
|
||||
this.txt = null;
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, function() { return this.txt; }.bind(this))
|
||||
];
|
||||
|
||||
this.invoke = function hideNDestroyDoc_invoke()
|
||||
{
|
||||
this.txt = getAccessible('c5').firstChild.firstChild;
|
||||
this.txt.DOMNode.parentNode.removeChild(this.txt.DOMNode);
|
||||
}
|
||||
|
||||
this.check = function hideNDestroyDoc_check()
|
||||
{
|
||||
getNode('c5').parentNode.removeChild(getNode('c5'));
|
||||
}
|
||||
|
||||
this.getID = function hideNDestroyDoc_getID()
|
||||
{
|
||||
return "remove text node and destroy a document on hide event";
|
||||
}
|
||||
}
|
||||
|
||||
function hideHideNDestroyDoc()
|
||||
{
|
||||
this.target = null;
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, function() { return this.target; }.bind(this))
|
||||
];
|
||||
|
||||
this.invoke = function hideHideNDestroyDoc_invoke()
|
||||
{
|
||||
var doc = getAccessible('c6').firstChild;
|
||||
var l1 = doc.firstChild;
|
||||
this.target = l1.firstChild;
|
||||
var l2 = doc.lastChild;
|
||||
l1.DOMNode.removeChild(l1.DOMNode.firstChild);
|
||||
l2.DOMNode.removeChild(l2.DOMNode.firstChild);
|
||||
}
|
||||
|
||||
this.check = function hideHideNDestroyDoc_check()
|
||||
{
|
||||
getNode('c6').parentNode.removeChild(getNode('c6'));
|
||||
}
|
||||
|
||||
this.getID = function hideHideNDestroyDoc_getID()
|
||||
{
|
||||
return "remove text nodes (2 events in the queue) and destroy a document on first hide event";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Target getters.
|
||||
*/
|
||||
@ -507,6 +559,8 @@
|
||||
gQueue.push(new insertReferredElm("testContainer3"));
|
||||
gQueue.push(new showHiddenParentOfVisibleChild());
|
||||
|
||||
gQueue.push(new hideNDestroyDoc());
|
||||
gQueue.push(new hideHideNDestroyDoc());
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -569,7 +623,10 @@
|
||||
|
||||
<div id="c4">
|
||||
<div style="visibility:hidden" id="c4_middle">
|
||||
<div style="visibility:visible" id="c4_child"></div>
|
||||
</div>
|
||||
<div style="visibility:visible" id="c4_child"></div>
|
||||
</div>
|
||||
|
||||
<iframe id="c5" src="data:text/html,hey"></iframe>
|
||||
<iframe id="c6" src="data:text/html,<label>l</label><label>l</label>"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user