RFR: 8176270: Adding ChangeListener to TextField.selectedTextProperty causes StringOutOfBoundsException

Jeanette Winzenburg fastegal at openjdk.java.net
Sun Feb 9 14:42:44 UTC 2020


On Fri, 7 Feb 2020 18:24:32 GMT, Kevin Rushforth <kcr at openjdk.org> wrote:

>> This is a WIP PR. Requesting for comments.
>> 
>> I could not replicate the test given at https://bugs.openjdk.java.net/browse/JDK-8176270 without TestFX. I nevertheless let my try to replicate the @Test things in here.
>> 
>> The fix is just a wild guess without really understanding the side effects of `.addListener`.
> 
> I left comments inline. This will need changes. Also, you will need to provide a test that fails without the fix and passes with the fix.

Didn't dig at the reason for the throwing, just a comment on how to add a failing test:  we can replace the actual typing (in the TestFx context) by programmatically replacing the selection, something like

      /** 
        * Test for JDK-8176270: register changeListener on selectedText, select at
        * end of text and replace selection throws.
        */
       @Test 
       public void addingChangeListener() {
            VBox vBox = new VBox();
            TextField textField = new TextField();
            textField.setText("1234 5678");
            vBox.getChildren().add(textField);
            textField.selectedTextProperty()
                 .addListener((o, ov, nv) -> {});

            Scene scene = new Scene(vBox);
            Stage stage = new Stage();
            stage.setScene(scene);
            stage.show();
        
           textField.positionCaret(5);
            // select 2nd word
           textField.selectNextWord();
           textField.replaceSelection("d");
        }

Similarly, an invalidationListener that access the selectedText throws, while an invalidationListener not accessing the selected is fine. So it looks like a one-off when evaluating the actual selection during the process, somehow it's not yet ready ..

To make the error show up on the test thread, replace the uncaughtExceptionHandler before (and cleanup after):

    @Before public void setup() throws Exception {
        Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> {
            if (throwable instanceof RuntimeException) {
                throw (RuntimeException)throwable;
            } else {
                Thread.currentThread().getThreadGroup().uncaughtException(thread, throwable);
            }
        });
        textInput = (TextInputControl) type.newInstance();
    }


    @After public void cleanup() {
        Thread.currentThread().setUncaughtExceptionHandler(null);
    }

-------------

PR: https://git.openjdk.java.net/jfx/pull/73


More information about the openjfx-dev mailing list