Bug 396005. Severe performance degredation regression when a11y active. r=surkov, a=dsicore

This commit is contained in:
aaronleventhal@moonset.net 2007-10-01 11:27:13 -07:00
Родитель f24e3ab422
Коммит 656dd5f434
3 изменённых файлов: 58 добавлений и 18 удалений

Просмотреть файл

@ -58,7 +58,7 @@ interface nsIDOMWindow;
*
* @status UNDER_REVIEW
*/
[scriptable, uuid(d118c0e9-b5e7-4671-854a-65b4713d9552)]
[scriptable, uuid(81ddd75f-adbd-4a1c-b87c-6522bcea0596)]
interface nsIAccessibleDocument : nsISupports
{
/**
@ -120,7 +120,8 @@ interface nsIAccessibleDocument : nsISupports
* @return An first nsIAccessible found by crawling up the DOM node
* to the document root.
*/
nsIAccessible getAccessibleInParentChain(in nsIDOMNode aDOMNode);
nsIAccessible getAccessibleInParentChain(in nsIDOMNode aDOMNode,
in boolean aCanCreate);
/**
* A bit flag representing the type of ARIA properties which should be

Просмотреть файл

@ -152,6 +152,12 @@ PRBool nsAccessible::IsTextInterfaceSupportCorrect(nsIAccessible *aAccessible)
{
PRBool foundText = PR_FALSE;
nsCOMPtr<nsIAccessibleDocument> accDoc = do_QueryInterface(aAccessible);
if (accDoc) {
// Don't test for accessible docs, it makes us create accessibles too
// early and fire mutation events before we need to
return PR_TRUE;
}
nsCOMPtr<nsIAccessible> child, nextSibling;
aAccessible->GetFirstChild(getter_AddRefs(child));
while (child) {
@ -584,7 +590,7 @@ NS_IMETHODIMP nsAccessible::GetParent(nsIAccessible ** aParent)
nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
NS_ENSURE_TRUE(docAccessible, NS_ERROR_FAILURE);
return docAccessible->GetAccessibleInParentChain(mDOMNode, aParent);
return docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE, aParent);
}
NS_IMETHODIMP nsAccessible::GetCachedParent(nsIAccessible ** aParent)
@ -1162,7 +1168,7 @@ nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
if (!accessible) {
// No accessible for the node with the point, so find the first
// accessible in the DOM parent chain
accDocument->GetAccessibleInParentChain(relevantNode,
accDocument->GetAccessibleInParentChain(relevantNode, PR_TRUE,
getter_AddRefs(accessible));
if (!accessible) {
NS_IF_ADDREF(*aAccessible = fallbackAnswer);

Просмотреть файл

@ -1301,7 +1301,7 @@ nsDocAccessible::FireTextChangeEventForText(nsIContent *aContent,
return;
nsCOMPtr<nsIAccessible> accessible;
nsresult rv = GetAccessibleInParentChain(node, getter_AddRefs(accessible));
nsresult rv = GetAccessibleInParentChain(node, PR_TRUE, getter_AddRefs(accessible));
if (NS_FAILED(rv) || !accessible)
return;
@ -1567,7 +1567,7 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
if (domNode && domNode != mDOMNode) {
if (!containerAccessible)
GetAccessibleInParentChain(domNode,
GetAccessibleInParentChain(domNode, PR_TRUE,
getter_AddRefs(containerAccessible));
nsCOMPtr<nsIAccessibleTextChangeEvent> textChangeEvent =
@ -1757,15 +1757,39 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
if (!IsNodeRelevant(childNode)) {
return NS_OK; // Don't fire event unless it can be for an attached accessible
}
if (!mIsContentLoaded && mAccessNodeCache.Count() <= 1) {
// Still loading and no accessibles has yet been created other than this
// doc accessible. In this case we optimize
// by not firing SHOW/HIDE/REORDER events for every document mutation
// caused by page load, since AT is not going to want to grab the
// document and listen to these changes until after the page is first loaded
// Leave early, and ensure mAccChildCount stays uninitialized instead of 0,
// which it is if anyone asks for its children right now.
return InvalidateChildren();
if (!mIsContentLoaded) {
// Still loading document
if (mAccessNodeCache.Count() <= 1) {
// Still loading and no accessibles has yet been created other than this
// doc accessible. In this case we optimize
// by not firing SHOW/HIDE/REORDER events for every document mutation
// caused by page load, since AT is not going to want to grab the
// document and listen to these changes until after the page is first loaded
// Leave early, and ensure mAccChildCount stays uninitialized instead of 0,
// which it is if anyone asks for its children right now.
return InvalidateChildren();
}
if (aChangeEventType == nsIAccessibleEvent::EVENT_DOM_CREATE) {
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
nsIEventStateManager *esm = presShell->GetPresContext()->EventStateManager();
NS_ENSURE_TRUE(esm, NS_ERROR_FAILURE);
if (!esm->IsHandlingUserInputExternal()) {
// Adding content during page load, but not caused by user input
// Just invalidate accessible hierarchy and return,
// otherwise the page load time slows down way too much
nsCOMPtr<nsIAccessible> containerAccessible;
GetAccessibleInParentChain(childNode, PR_FALSE, getter_AddRefs(containerAccessible));
if (!containerAccessible) {
containerAccessible = this;
}
nsCOMPtr<nsPIAccessible> privateContainer = do_QueryInterface(containerAccessible);
return privateContainer->InvalidateChildren();
}
// else: user input, so we must fall through and for full handling,
// e.g. fire the mutation events. Note: user input could cause DOM_CREATE
// during page load if user typed into an input field or contentEditable area
}
}
// Update last change state information
@ -1803,7 +1827,7 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
#endif
nsCOMPtr<nsIAccessible> containerAccessible;
GetAccessibleInParentChain(childNode, getter_AddRefs(containerAccessible));
GetAccessibleInParentChain(childNode, PR_TRUE, getter_AddRefs(containerAccessible));
if (!containerAccessible) {
containerAccessible = this;
}
@ -1888,6 +1912,7 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
NS_IMETHODIMP
nsDocAccessible::GetAccessibleInParentChain(nsIDOMNode *aNode,
PRBool aCanCreate,
nsIAccessible **aAccessible)
{
// Find accessible in parent chain of DOM nodes, or return null
@ -1911,8 +1936,16 @@ nsDocAccessible::GetAccessibleInParentChain(nsIDOMNode *aNode,
if (NS_SUCCEEDED(accService->GetRelevantContentNodeFor(currentNode, getter_AddRefs(relevantNode))) && relevantNode) {
currentNode = relevantNode;
}
accService->GetAccessibleInWeakShell(currentNode, mWeakShell, aAccessible);
if (aCanCreate) {
accService->GetAccessibleInWeakShell(currentNode, mWeakShell, aAccessible);
}
else { // Only return cached accessibles, don't create anything
nsCOMPtr<nsIAccessNode> accessNode;
GetCachedAccessNode(currentNode, getter_AddRefs(accessNode)); // AddRefs
if (accessNode) {
CallQueryInterface(accessNode, aAccessible); // AddRefs
}
}
} while (!*aAccessible);
return NS_OK;