Bug 1405796 - Don't traverse into relocated children in scoped TreeWalker. r=surkov

This commit is contained in:
Eitan Isaacson 2017-12-22 11:25:00 -05:00
parent e6fd22c374
commit 33a8bfe01f
4 changed files with 57 additions and 8 deletions

View File

@ -76,6 +76,8 @@ TreeWalker::Scope(nsIContent* aAnchorNode)
mAnchorNode = aAnchorNode;
mFlags |= eScoped;
bool skipSubtree = false;
Accessible* acc = AccessibleFor(aAnchorNode, 0, &skipSubtree);
if (acc) {
@ -112,6 +114,8 @@ TreeWalker::Seek(nsIContent* aChildNode)
// If ARIA owned child.
Accessible* child = mDoc->GetAccessible(childNode);
if (child && child->IsRelocated()) {
MOZ_ASSERT(!(mFlags & eScoped),
"Walker should not be scoped when seeking into relocated children");
if (child->Parent() != mContext) {
return false;
}
@ -149,12 +153,16 @@ TreeWalker::Next()
}
if (mPhase == eAtDOM || mPhase == eAtARIAOwns) {
mPhase = eAtARIAOwns;
Accessible* child = mDoc->ARIAOwnedAt(mContext, mARIAOwnsIdx);
if (child) {
mARIAOwnsIdx++;
return child;
if (!(mFlags & eScoped)) {
mPhase = eAtARIAOwns;
Accessible* child = mDoc->ARIAOwnedAt(mContext, mARIAOwnsIdx);
if (child) {
mARIAOwnsIdx++;
return child;
}
}
MOZ_ASSERT(!(mFlags & eScoped) || mPhase != eAtARIAOwns,
"Don't walk relocated children in scoped mode");
mPhase = eAtEnd;
return nullptr;
}
@ -230,11 +238,17 @@ TreeWalker::Prev()
}
if (mPhase == eAtEnd) {
mARIAOwnsIdx = mDoc->ARIAOwnedCount(mContext);
mPhase = eAtARIAOwns;
if (mFlags & eScoped) {
mPhase = eAtDOM;
} else {
mPhase = eAtARIAOwns;
mARIAOwnsIdx = mDoc->ARIAOwnedCount(mContext);
}
}
if (mPhase == eAtARIAOwns) {
MOZ_ASSERT(!(mFlags & eScoped),
"Should not walk relocated children in scoped mode");
if (mARIAOwnsIdx > 0) {
return mDoc->ARIAOwnedAt(mContext, --mARIAOwnsIdx);
}

View File

@ -29,7 +29,8 @@ public:
// used to walk the existing tree of the given node
eWalkCache = 1,
// used to walk the context tree starting from given node
eWalkContextTree = 2 | eWalkCache
eWalkContextTree = 2 | eWalkCache,
eScoped = 4
};
/**

View File

@ -1853,6 +1853,7 @@ InsertIterator::Next()
if (finder.Seek(node)) {
mChild = mWalker.Scope(node);
if (mChild) {
MOZ_ASSERT(!mChild->IsRelocated(), "child cannot be aria owned");
mChildBefore = finder.Prev();
return true;
}

View File

@ -218,3 +218,36 @@ addAccessibleTask(`<div id="a"></div><div id="b"></div>`,
testChildrenIds(accDoc, []);
}
);
// Don't allow ordinal child to be placed after aria-owned child (bug 1405796)
addAccessibleTask(`<div id="container"><div id="a">Hello</div></div>
<div><div id="c">There</div><div id="d">There</div></div>`,
async function(browser, accDoc) {
let containerAcc = findAccessibleChildByID(accDoc, "container");
testChildrenIds(containerAcc, ["a"]);
await contentSpawnMutation(browser, MOVE, function() {
document.getElementById("container").setAttribute("aria-owns", "c");
});
testChildrenIds(containerAcc, ["a", "c"]);
await contentSpawnMutation(browser, MOVE, function() {
let span = document.createElement("span");
document.getElementById("container").appendChild(span);
let b = document.createElement("div");
b.id = "b";
document.getElementById("container").appendChild(b);
});
testChildrenIds(containerAcc, ["a", "b", "c"]);
await contentSpawnMutation(browser, MOVE, function() {
document.getElementById("container").setAttribute("aria-owns", "c d");
});
testChildrenIds(containerAcc, ["a", "b", "c", "d"]);
}
);