Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,9 @@ private Component getComponentEventSource(int listenOnIndex) {
}

private void fireShortcutEvent(Component component) {
if (lifecycleOwner == null) {
return;
}
if (ancestorsOrSelfAreVisible(lifecycleOwner) && (lifecycleOwner
.getElement().isEnabled()
|| DisabledUpdateMode.ALWAYS.equals(getDisabledUpdateMode()))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,32 @@ public void constructedRegistration_lifecycleOnwerHasInvisibleParent_shorcutEven
Assert.assertNull(event.get());
}

@Test
public void constructedRegistration_lifecycleOwnerRemovedBeforeKeyEvent_noNPE() {
AtomicReference<ShortcutEvent> event = new AtomicReference<>();

for (Component component : listenOn) {
Mockito.when(component.addDetachListener(any()))
.thenReturn(mock(Registration.class));
}

ShortcutRegistration registration = new ShortcutRegistration(
lifecycleOwner, () -> listenOn, event::set, Key.KEY_A);

mockLifecycle(true);
clientResponse();

// Simulate removal: nulls lifecycleOwner, eventListener, etc.
registration.remove();

// Fire KeyDown event after removal — should not throw NPE
listenOn[0].getEventBus()
.fireEvent(new KeyDownEvent(listenOn[0], Key.KEY_A.toString()));

// Shortcut event should not have been fired
Assert.assertNull(event.get());
}

@Test
public void constructedRegistration_lifeCycleOwnerIsDetached_detachListenerIsDeregisteredFromListenOnComponents() {
AtomicReference<ComponentEventListener> detachListener = new AtomicReference<>();
Expand Down
Loading