Skip to content

Commit 7f691d7

Browse files
authored
Fix geteventlisteners being loaded twice (#56)
* Prevent stack overflow for geteventlisteners hook * Fix geteventlisteners import to work with HMR as well
1 parent 55a35d2 commit 7f691d7

File tree

2 files changed

+59
-64
lines changed

2 files changed

+59
-64
lines changed
Lines changed: 58 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,76 @@
1-
// Taken and modified from https://github.com/colxi/getEventListeners to be compiled into ES5, allowing running in older browsers
2-
31
/**
42
* Monkey-patches `Element`'s `addEventListener` & `removeEventListener` and adds `getEventListeners`.
53
* This later allows the renderer to emit any event handlers attached to React-wrapped components as Angular Outputs:
6-
```html
7-
<my-component (arbitraryEvent)="onEventHandler($event)"></my-component>
8-
```
9-
*/
10-
export function initHooks() {
11-
// save the original methods before overwriting them
12-
Element.prototype['_addEventListener'] = Element.prototype.addEventListener;
13-
Element.prototype['_removeEventListener'] = Element.prototype.removeEventListener;
4+
* ```html
5+
* <my-component (arbitraryEvent)="onEventHandler($event)"></my-component>
6+
* ```
7+
*
8+
* @note Taken and modified from https://github.com/colxi/getEventListeners to be compiled into ES5, allowing running in older browsers
9+
**/
10+
11+
Element.prototype['_addEventListener'] = Element.prototype.addEventListener;
12+
Element.prototype['_removeEventListener'] = Element.prototype.removeEventListener;
1413

15-
Element.prototype.addEventListener = function<K extends keyof ElementEventMap>(
16-
type: K,
17-
listener: (this: Element, ev: ElementEventMap[K]) => any,
18-
options?: boolean | AddEventListenerOptions
19-
): void {
20-
if (options === undefined) options = false;
14+
Element.prototype.addEventListener = function<K extends keyof ElementEventMap>(
15+
type: K,
16+
listener: (this: Element, ev: ElementEventMap[K]) => any,
17+
options?: boolean | AddEventListenerOptions
18+
): void {
19+
if (options === undefined) options = false;
2120

22-
// declare listener
23-
this._addEventListener(type, listener, options);
21+
// declare listener
22+
this._addEventListener(type, listener, options);
2423

25-
if (!this.eventListenerList) this.eventListenerList = {};
26-
if (!this.eventListenerList[type]) this.eventListenerList[type] = [];
24+
if (!this.eventListenerList) this.eventListenerList = {};
25+
if (!this.eventListenerList[type]) this.eventListenerList[type] = [];
2726

28-
// add listener to event tracking list
29-
this.eventListenerList[type].push({
30-
type: type,
31-
listener: listener,
32-
useCapture: options,
33-
});
34-
};
27+
// add listener to event tracking list
28+
this.eventListenerList[type].push({
29+
type: type,
30+
listener: listener,
31+
useCapture: options,
32+
});
33+
};
3534

36-
Element.prototype.removeEventListener = function<K extends keyof ElementEventMap>(
37-
type: K,
38-
listener: (this: Element, ev: ElementEventMap[K]) => any,
39-
options?: boolean | EventListenerOptions
40-
): void {
41-
if (options === undefined) options = false;
35+
Element.prototype.removeEventListener = function<K extends keyof ElementEventMap>(
36+
type: K,
37+
listener: (this: Element, ev: ElementEventMap[K]) => any,
38+
options?: boolean | EventListenerOptions
39+
): void {
40+
if (options === undefined) options = false;
4241

43-
// remove listener
44-
this._removeEventListener(type, listener, options);
42+
// remove listener
43+
this._removeEventListener(type, listener, options);
4544

46-
if (!this.eventListenerList) this.eventListenerList = {};
47-
if (!this.eventListenerList[type]) this.eventListenerList[type] = [];
45+
if (!this.eventListenerList) this.eventListenerList = {};
46+
if (!this.eventListenerList[type]) this.eventListenerList[type] = [];
4847

49-
// Find the event in the list, If a listener is registered twice, one
50-
// with capture and one without, remove each one separately. Removal of
51-
// a capturing listener does not affect a non-capturing version of the
52-
// same listener, and vice versa.
53-
for (let i = 0; i < this.eventListenerList[type].length; i++) {
54-
if (
55-
this.eventListenerList[type][i].listener === listener &&
56-
this.eventListenerList[type][i].useCapture === options
57-
) {
58-
this.eventListenerList[type].splice(i, 1);
59-
break;
60-
}
48+
// Find the event in the list, If a listener is registered twice, one
49+
// with capture and one without, remove each one separately. Removal of
50+
// a capturing listener does not affect a non-capturing version of the
51+
// same listener, and vice versa.
52+
for (let i = 0; i < this.eventListenerList[type].length; i++) {
53+
if (
54+
this.eventListenerList[type][i].listener === listener &&
55+
this.eventListenerList[type][i].useCapture === options
56+
) {
57+
this.eventListenerList[type].splice(i, 1);
58+
break;
6159
}
62-
// if no more events of the removed event type are left,remove the group
63-
if (this.eventListenerList[type].length == 0) delete this.eventListenerList[type];
64-
};
60+
}
61+
// if no more events of the removed event type are left,remove the group
62+
if (this.eventListenerList[type].length == 0) delete this.eventListenerList[type];
63+
};
6564

66-
Element.prototype.getEventListeners = function<K extends keyof ElementEventMap>(type?: K) {
67-
if (!this.eventListenerList) this.eventListenerList = {};
65+
Element.prototype.getEventListeners = function<K extends keyof ElementEventMap>(type?: K) {
66+
if (!this.eventListenerList) this.eventListenerList = {};
6867

69-
// return requested listeners type or all them
70-
if (type === undefined) return this.eventListenerList;
71-
return this.eventListenerList[type];
72-
};
68+
// return requested listeners type or all them
69+
if (type === undefined) return this.eventListenerList;
70+
return this.eventListenerList[type];
71+
};
7372

74-
/*
73+
/*
7574
Element.prototype.clearEventListeners = function(a){
7675
if(!this.eventListenerList)
7776
this.eventListenerList = {};
@@ -88,4 +87,3 @@ export function initHooks() {
8887
}
8988
};
9089
*/
91-
}

libs/core/src/lib/renderer/renderer.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Disguise } from './components/Disguise';
88
import { ReactContent } from './react-content';
99
import { isReactNode, ReactNode } from './react-node';
1010
import { registerElement } from './registry';
11-
import { initHooks as initGetEventListeners } from './geteventlisteners';
11+
import './geteventlisteners';
1212

1313
const DEBUG = false;
1414

@@ -84,9 +84,6 @@ export class ReactRenderer implements Renderer2 {
8484
};
8585

8686
constructor(public readonly rootRenderer: AngularReactRendererFactory) {
87-
// Attach hooks to event handlers so we can intercept and re-emit any event handlers passed to React-wrapper components
88-
initGetEventListeners();
89-
9087
// These two elements are essential for the whole experience to be smooth for the user - register them from the get-go.
9188
registerElement('ReactContent', () => ReactContent);
9289
registerElement('Disguise', () => Disguise);

0 commit comments

Comments
 (0)