Regression/change in event handling?


#1

Previously, I was on v0.124.0 and I just updated to v0.139.0. I had logic along the lines of:

editorView.preempt(
        'core:move-up',
        autocomplete.selectPreviousCompletion_.bind(autocomplete))

And in my callback handler:

  selectPreviousCompletion_(e: Event):bool {
    this.component.selectPreviousCompletion();
    return false;
  }

Previously, this was sufficient to let my UI handle the down arrow keypress and would prevent it from being handled by the editor due to the combination of preempt() and return false.

Are there any known changes in this area? Could this be any sort of race condition due to the order in which packages are loaded? Stepping through the jQuery event handling code is pretty gross, so I’m having a tough time debugging this.

The only clue that I have found so far is that I seem to have found myself inside handleCommandEvent() in command-registry.js with the listeners array of size 2. The first element is an InlineListener while the second is a SelectorBasedListener. I believe that I am the first one in the list (good), but immediatePropagationStopped has not been set (bad). This is even true after I added e.stopImmediatePropagation() in my handler.


#2

Note that if I go into the debugger and manually set the value of immediatePropagationStopped on line 250 to true, then things work fine. I think that the event that my handler gets may be a jQuery event rather than the synthetic event created by CommandRegistery, and as such, its implementation of stopImmediatePropagation() isn’t getting the job done. At least that’s my best hypothesis so far.


#3

/cc @nathansobo Has anything changed in this area recently? I can confirm that command-registry.js passes the synthetic event via listener.callback.call(currentTarget, syntheticEvent) and that the next function call is inside the vendored jQuery:

		eventHandle = elemData.handle = function( e ) {
			// Discard the second event of a jQuery.event.trigger() and
			// when an event is called after a page has unloaded
			return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
				jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
				undefined;
		};

The synthetic event is the first thing in arguments, so it makes it to jQuery.event.dispatch(), but the first thing dispatch() does is:

event = jQuery.event.fix( event );

And by the time my handler gets it, I have the bastardized jQuery event, so stopImmediatePropagation() does not work as intended. I can seem to work around this by doing:

e.originalEvent.stopImmediatePropagation();

But I’m not sure how future proof that is.


#4

It might be easier for people here to help if you tell us what it is you’re trying to get done rather than just what you’re trying to do at a low level. Why do you need to handle the down-arrow key press but not just use a key map?