Skip to content

Commit

Permalink
feat(events): check if event instanceof MouseEvent
Browse files Browse the repository at this point in the history
check if event is instance of MouseEvent in map_event.ts
same for event.ts

Fix 5464
  • Loading branch information
Theo-dev-3D committed Feb 13, 2025
1 parent b2fd19e commit 36eadfd
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Avoid setting marker opacity twice. ([#5441](https://github.com/maplibre/maplibre-gl-js/pull/5441))
- Fix rendering Japanese symbols which are accidentally ignored. ([#5421](https://github.com/maplibre/maplibre-gl-js/pull/5421)
- Add a check for MouseEvent, to avoid errors when bot were crawling on website using Event instance instead of MouseEvent instance for types like mouseover, mouseout etc.. ([#5466](https://github.com/maplibre/maplibre-gl-js/pull/5466)).
- _...Add new stuff here..._

### 🐞 Bug fixes
Expand Down
1 change: 1 addition & 0 deletions src/ui/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ export class MapMouseEvent extends Event implements MapLibreEvent<MouseEvent> {
_defaultPrevented: boolean;

constructor(type: string, map: Map, originalEvent: MouseEvent, data: any = {}) {
originalEvent = originalEvent instanceof MouseEvent ? originalEvent : new MouseEvent(type, originalEvent);
const point = DOM.mousePos(map.getCanvas(), originalEvent);
const lngLat = map.unproject(point);
super(type, extend({point, lngLat, originalEvent}, data));
Expand Down
25 changes: 25 additions & 0 deletions src/ui/handler/map_event.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,29 @@ describe('map events', () => {
simulate.contextmenu(map.getCanvas(), {target, button: 2, clientX: 10, clientY: 10}); // triggered only after mouseup
expect(contextmenu).toHaveBeenCalledTimes(0);
});

test('MapMouseEvent constructor does not throw error with Event instance instead of MouseEvent as originalEvent param', () => {
const map = createMap();
const target = map.getCanvasContainer();

expect(()=> {
target.dispatchEvent(new Event('mousedown'));
target.dispatchEvent(new Event('mouseup'));
target.dispatchEvent(new Event('click'));
target.dispatchEvent(new Event('dblclick'));
target.dispatchEvent(new Event('mousemove'));
target.dispatchEvent(new Event('mouseover'));
target.dispatchEvent(new Event('mouseenter'));
target.dispatchEvent(new Event('mouseleave'));
target.dispatchEvent(new Event('mouseout'));
target.dispatchEvent(new Event('contextmenu'));
target.dispatchEvent(new Event('wheel'));

target.dispatchEvent(new Event('touchstart'));
target.dispatchEvent(new Event('touchmove'));
target.dispatchEvent(new Event('touchmoveWindow'));
target.dispatchEvent(new Event('touchend'));
target.dispatchEvent(new Event('touchcancel'));
}).not.toThrow();
});
});
20 changes: 12 additions & 8 deletions src/ui/handler_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {DragPanHandler} from './handler/shim/drag_pan';
import {DragRotateHandler} from './handler/shim/drag_rotate';
import {TwoFingersTouchZoomRotateHandler} from './handler/shim/two_fingers_touch';
import {CooperativeGesturesHandler} from './handler/cooperative_gestures';
import {extend} from '../util/util';
import {extend, isPointableEvent, isTouchableEvent, isTouchableOrPointableType} from '../util/util';
import {browser} from '../util/browser';
import Point from '@mapbox/point-geometry';
import {type MapControlsDeltas} from '../geo/projection/camera_helper';
Expand Down Expand Up @@ -377,12 +377,6 @@ export class HandlerManager {
const mergedHandlerResult: HandlerResult = {needsRenderFrame: false};
const eventsInProgress: EventsInProgress = {};
const activeHandlers = {};
const eventTouches = (e as TouchEvent).touches;

const mapTouches = eventTouches ? this._getMapTouches(eventTouches) : undefined;
const points = mapTouches ?
DOM.touchPos(this._map.getCanvas(), mapTouches) :
DOM.mousePos(this._map.getCanvas(), ((e as MouseEvent)));

for (const {handlerName, handler, allowed} of this._handlers) {
if (!handler.isEnabled()) continue;
Expand All @@ -393,7 +387,17 @@ export class HandlerManager {

} else {
if (handler[eventName || e.type]) {
data = handler[eventName || e.type](e, points, mapTouches);
if (isPointableEvent(e, eventName || e.type)){
const point = DOM.mousePos(this._map.getCanvas(), e);
data = handler[eventName || e.type](e, point);
} else if (isTouchableEvent(e, eventName || e.type)) {
const eventTouches = (e as TouchEvent).touches;
const mapTouches = this._getMapTouches(eventTouches);
const points = DOM.touchPos(this._map.getCanvas(), mapTouches);
data = handler[eventName || e.type](e, points, mapTouches);
} else if (!isTouchableOrPointableType(eventName || e.type)) {
data = handler[eventName || e.type](e);
}
this.mergeHandlerResult(mergedHandlerResult, eventsInProgress, data, handlerName, inputEvent);
if (data && data.needsRenderFrame) {
this._triggerRenderFrame();
Expand Down
35 changes: 35 additions & 0 deletions src/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {WorkerGlobalScopeInterface} from './web_worker';
import {mat3, mat4, quat, vec2, type vec3, type vec4} from 'gl-matrix';
import {pixelsToTileUnits} from '../source/pixels_to_tile_units';
import {type OverscaledTileID} from '../source/tile_id';
import type {Event} from './evented';

/**
* Returns a new 64 bit float vec4 of zeroes.
Expand Down Expand Up @@ -1035,3 +1036,37 @@ export const MAX_TILE_ZOOM = 25;
export const MIN_TILE_ZOOM = 0;

export const MAX_VALID_LATITUDE = 85.051129;

const touchableEvents = {
touchstart: true,
touchmove: true,
touchmoveWindow: true,
touchend: true,
touchcancel: true
};

const pointableEvents = {
dblclick: true,
click: true,
mouseover: true,
mouseout: true,
mousedown: true,
mousemove: true,
mousemoveWindow: true,
mouseup: true,
mouseupWindow: true,
contextmenu: true,
wheel: true
};

export function isTouchableEvent(event: Event, eventType: string): boolean {
return touchableEvents[eventType] && 'touches' in event;
}

export function isPointableEvent(event: Event, eventType: string): event is MouseEvent {
return pointableEvents[eventType] && (event instanceof MouseEvent || event instanceof WheelEvent);
}

export function isTouchableOrPointableType(eventType: string): boolean {
return touchableEvents[eventType] || pointableEvents[eventType];
}

0 comments on commit 36eadfd

Please sign in to comment.