Regression 'preview' vs 'cdn' - "Uncaught DOMException: Failed to execute 'setPointerCapture' on 'Element': No active pointer with the given id is found."

Hi,
I am running tests against ‘cdn’ every day, and against ‘preview’ once a week. This week the ‘preview’ specs failed with

Uncaught DOMException: Failed to execute 'setPointerCapture' on 'Element': No active pointer with the given id is found.
    at HTMLCanvasElement._pointerDownEvent (https://preview.babylonjs.com/babylon.js:16:3630713)
    at triggerMouseEvent (http://localhost:8887/assets/ext/babylon-scene/rotate_event_recorder_spec.self-8ddc89fdf81ff3e9ac8a8d94d65d770f.js?body=1:9:10)
    at Object.<anonymous> (http://localhost:8887/assets/ext/babylon-scene/rotate_event_recorder_spec.self-8ddc89fdf81ff3e9ac8a8d94d65d770f.js?body=1:54:5)
    at attemptSync (http://localhost:8887/assets/jasmine/2.3.4.self-9be648c9d006c86c9f0638e38413a010.js?body=1:1790:24)
    at QueueRunner.run (http://localhost:8887/assets/jasmine/2.3.4.self-9be648c9d006c86c9f0638e38413a010.js?body=1:1778:9)
    at QueueRunner.execute (http://localhost:8887/assets/jasmine/2.3.4.self-9be648c9d006c86c9f0638e38413a010.js?body=1:1763:10)
    at Spec.queueRunnerFactory (http://localhost:8887/assets/jasmine/2.3.4.self-9be648c9d006c86c9f0638e38413a010.js?body=1:628:35)
    at Spec.execute (http://localhost:8887/assets/jasmine/2.3.4.self-9be648c9d006c86c9f0638e38413a010.js?body=1:354:10)
    at Object.fn (http://localhost:8887/assets/jasmine/2.3.4.self-9be648c9d006c86c9f0638e38413a010.js?body=1:2361:37)
    at attemptAsync (http://localhost:8887/assets/jasmine/2.3.4.self-9be648c9d006c86c9f0638e38413a010.js?body=1:1820:24)

The method that seems to be causing the error is:

  function triggerMouseEvent(node, eventType) {
    node.tabIndex = -1;
    node.focus();
    const clickEvent = document.createEvent("MouseEvents");
    clickEvent.initEvent(eventType, true, true);
    node.dispatchEvent(clickEvent);
  }

In the spec I was creating new BABYLON.Engine. I changed it to new BABYLON.NullEngine, but then I get

TypeError: Cannot set property 'tabIndex' of undefined
TypeError: Cannot set property 'tabIndex' of undefined
    at triggerMouseEvent (http://localhost:8887/assets/ext/babylon-scene/rotate_event_recorder_spec.self-45ec601bc9e8a927461ae11405d31517.js?body=1:5:19)

What I have in the production code is a listener that records how the user moves the mouse and click and pings the server with this information from time to time.

It looks like this


    this._observer = this._scene.onPointerObservable.add((eventData, eventState) => {
      if (eventData.type == BABYLON.PointerEventTypes.POINTERDOWN) {
        this.onSceneMouseDown(eventData);
      } else if (eventData.type == BABYLON.PointerEventTypes.POINTERUP) {
        this.onSceneMouseUp(eventData);
      }
    });

If this is not a regression from the ‘cdn’ version then how should I test this behavior with the new ‘preview’

Thanks.

1 Like

Adding @PolygonalSun and @bghgary, I think there has been some changes lately regarding pointers and ids.

So recently, code was added to set/release pointer capture on any pointer inputs (mouse or touch) that were incoming, which requires a pointerId. The issue that you’re seeing is because you’re dispatching a MouseEvent, which doesn’t have this property.

With respect to this issue, what I can do is to add an additional check for the pointerId before setting the pointer capture. For your tests, it might be worth looking into using PointerEvent (which inherits MouseEvent) unless you explicitly need to use MouseEvent. I don’t think that document.createEvent supports PointerEvent creation so you will need to use a constructor instead:

function triggerMouseEvent(node, eventType) {
    node.tabIndex = -1;
    node.focus();
    // pointerId is not set in this example but should default to 0
    // It should be noted that when the mouse triggers an event, it will have a pointerId 1 in Chrome (and Chromium browsers)
    // It should also have a pointerId of 0 for Firefox and I think Safari.
    const clickEvent = new PointerEvent(eventType, {bubbles: true, cancelable: true});
    node.dispatchEvent(clickEvent);
  }

I’ll update this thread when my changes have been merged.

1 Like

I don’t need MouseEvent. Tried PointerEvent, but it does not work. Same error

  function triggerMouseEvent(node, eventType) {
    node.tabIndex = -1;
    node.focus();
    const clickEvent = new PointerEvent(eventType, {bubbles: true, cancelable: true});
    node.dispatchEvent(clickEvent);
  }

What happens if you try manually defining the pointerId as 1?

const clickEvent = new PointerEvent(eventType, {pointerId: 1, bubbles: true, cancelable: true});

It works. Both for ‘cdn’ and ‘preview’

Thanks.

I will send PointerEvent in the specs.

I’ve added some additional code to the DeviceInputSystem to check for pointerId’s and handle events that are missing one: DeviceInputSystem: Add checks for pointer events with no pointerId by PolygonalSun · Pull Request #10405 · BabylonJS/Babylon.js (github.com)