Selection.extend throws NS_ERROR_FAILURE when called from keypress callback




a year ago
a year ago


(Reporter: vlasov.r, Unassigned)


49 Branch

Firefox Tracking Flags

(Not tracked)



(1 attachment)



a year ago
Created attachment 8810135 [details]

User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0
Build ID: 20161019084923

Steps to reproduce:

Wrote JavaScript to extend existing selection in paragraph 2 into the previous paragraph (paragraph 1) when keyboard selection reached the left-most character in paragraph 2 (focusOffset===0).  I was selecting text right-to-left by keyboard (with Shift+LeftArrow).

Actual results:

NS_ERROR_FAILURE in browser console (at line 12 in attached file)

However, if I select (right-to-left) in paragraph 2 up to the left-most character, but before hitting Shift+LeftArrow on more time I release all keys and call selection.extend() by clicking on the button, then IT WORKS FINE: I can continue selecting text through (the end of) paragraph 1 by resuming the Shift+LeftArrow

Expected results:

Extending the selection from the keypress callback should behave the same as when extending the selection from the button.  In both cases I call the same function.
Trying to call selection.extend() through setTimeout did not help (still generated NS_ERROR_FAILURE when setTimeout was invoked in the keypress callback)

Please see code in small HTML file attached - no other files are necessary

Comment 1

a year ago
What are the steps to reproduce with the HTML file? Only clicking the "extend" button and checking the browser console?
Flags: needinfo?(vlasov.r)

Comment 2

a year ago
Thank you for looking into this.

To reproduce:
1. Click in between Y and Z in the second paragraph.
2. While holding down Shift click the left arrow THREE times.
The third click should generate NS_ERROR_FAILURE.

To show the different behavior:
1. Click in between Y and Z in the second paragraph.
2. While holding down Shift click the left arrow TWO times.
3. Release Shift.
4. Click on the "Extend" button.
5. Hold down Shift and press LeftArrow a number of times.
The caret should now be in the first paragraph and the selection "continues" there, with the selection in the second paragraph being left untouched.

Both scenarios call the same JavaScript function in the HTML but the second scenario does not throw the exception.
Flags: needinfo?(vlasov.r)


a year ago
Component: Untriaged → DOM
Boris, your fingerprints are on some of this code. Can you take a quick look, please?
Flags: needinfo?(bzbarsky)
I've looked at it some, but not really the actual details.

In any case, in Extend() we have this block:

  if (!IsValidSelectionPoint(mFrameSelection, &aParentNode)) {

and we take that early return.  IsValidSelectionPoint() checks that the given parent node is a descendant of the "ancestor limiter" of the mFrameSelection.  In this case the "ancestor limiter" comes back as <p id="p2"> and the aParentNode is <div id="div1">, which is not a descendant of that <p>, so we throw.

When clicking the button, there is no "ancestor limiter" in the mFrameSelection, so it can be extended to any point in the DOM.

Looks like we set up an ancestor limiter on a selection when there is a focused editor (in this case a focused contenteditable field); the limiter is set to the root of that editor.  Presumably the intent is to not have normal keyboard selection operations leak out of the contenteditable area while it has focus.
Flags: needinfo?(bzbarsky)
Yeah, looks like this check was initially added to fix bug 123033 which involved selection leaking out of a text control.
I suppose we could skip the sanity checks for cases when the extend() call comes from script, not internals.  We'd just have to make sure there aren't any invariants getting violated in the process...
Component: DOM → Selection
Ever confirmed: true
Priority: -- → P2
You need to log in before you can comment on or make changes to this bug.