Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
MozillaCompoundTextInfo: Don't skip ignored objects when determining whether the range covers the end of any ancestors of endObj. #9477
Link to issue number:
Summary of the issue:
In Google Docs (and other web-based editors), braille incorrectly displays "lst end" before the cursor in a list in some cases, even if the cursor is in the middle of the list item.
Description of how this pull request fixes the issue:
In order to display markers at the end of containers in braille (e.g. "lst end" at the end of lists), MozillaCompoundTextInfo needs to check the object at the end of the range (endObj) and its ancestors. If the range is at the end of any of these objects, we mark the associated control field as being at the end of its node. For example, if the range is at the end of a list, we mark the list's control field as being at end of node, which causes braille to display "lst end". However, if the range is not at the end of one of these objects, the range also can't be at the end of any of its ancestors. For example, if the range ends in the middle of a list item, it obviously doesn't cover the end of the list, even if the list item (as a whole) is the last item in the list. In this case, we don't check the remaining ancestors.
Previously, this was failing where there was a single paragraph inside the last list item in a list. The list would be marked as end of node, even if the range ended in the middle of the paragraph, resulting in a spurious "lst end" indicator before the cursor in braille.
This happened because we ignore paragraphs as irrelevant and thus don't generate control fields for them. However, the code which checks whether the range is at the end of endObj or its ancestors only ran if there was a control field. Because the paragraph had no control field, we'd skip it completely, not determining that the range ended in the middle of it and thus aborting the search. We'd then check the next ancestor, and since the paragraph was the last child of the list item which was in turn the last child of the list, we'd mark all of these as end of node, including the list.
To fix this, we now run this check regardless of whether we generated a control field for an object; i.e. regardless of whether we ignored a paragraph.
Also tested the same scenario in Google Docs and confirmed that it works as expected.
Known issues with pull request:
Change log entry:
Sorry; I did my best to explain this in the PR description, but it seems I didn't quite manage it. :( We choose to ignore paragraphs because they aren't useful; they're essentially presentational for our purposes. So, we don't generate a control field for them. This is where field will be None. However, just because we choose to ignore it in terms of control fields doesn't change the fact that there's an object for it. So, we still need to check whether we're at the end of that object. If we are, we won't do anything here because there's no field to annotate. However, if this is *not* the end, we will still break out of the loop, since we're not at the end of any of its ancestors. This is the key change here. Previously, we wouldn't break out of the ancestor loop for a paragraph (because no field), even if we were at the end of that paragraph. It's essential that we break out of the loop here if we're at the end of any object, regardless of whether we chose to generate a field for it.