Skip to content

Commit 7788cec

Browse files
author
Brian Vaughn
committed
Inlined DevTools event emitter impl
When dispatching an event, if a listener throws- the event emitter should still call other listeners before re-throwing. If we don't do this, certain stores (e.g. ProfilerStore) may miss events and be left in an unknown state.
1 parent a600408 commit 7788cec

File tree

7 files changed

+70
-21
lines changed

7 files changed

+70
-21
lines changed

packages/react-devtools-shared/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
"@reach/menu-button": "^0.1.17",
1212
"@reach/tooltip": "^0.2.2",
1313
"clipboard-js": "^0.3.6",
14-
"events": "^3.0.0",
1514
"local-storage-fallback": "^4.1.1",
1615
"lodash.throttle": "^4.1.1",
1716
"memoize-one": "^3.1.1",

packages/react-devtools-shared/src/backend/agent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @flow
88
*/
99

10-
import EventEmitter from 'events';
10+
import EventEmitter from '../events';
1111
import throttle from 'lodash.throttle';
1212
import {
1313
SESSION_STORAGE_LAST_SELECTION_KEY,

packages/react-devtools-shared/src/bridge.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @flow
88
*/
99

10-
import EventEmitter from 'events';
10+
import EventEmitter from './events';
1111

1212
import type {ComponentFilter, Wall} from './types';
1313
import type {

packages/react-devtools-shared/src/devtools/ProfilerStore.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @flow
88
*/
99

10-
import EventEmitter from 'events';
10+
import EventEmitter from '../events';
1111
import {prepareProfilingDataFrontendFromBackendAndStore} from './views/Profiler/utils';
1212
import ProfilingCache from './ProfilingCache';
1313
import Store from './store';

packages/react-devtools-shared/src/devtools/store.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @flow
88
*/
99

10-
import EventEmitter from 'events';
10+
import EventEmitter from '../events';
1111
import {inspect} from 'util';
1212
import {
1313
TREE_OPERATION_ADD,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
export default class EventEmitter<Events: Object> {
11+
listenersMap: Map<string, Set<Function>> = new Map();
12+
13+
addListener<Event: $Keys<Events>>(
14+
event: Event,
15+
listener: (...$ElementType<Events, Event>) => any,
16+
): void {
17+
let listeners = this.listenersMap.get(event);
18+
if (listeners === undefined) {
19+
listeners = new Set();
20+
21+
this.listenersMap.set(event, listeners);
22+
}
23+
24+
listeners.add(listener);
25+
}
26+
27+
emit<Event: $Keys<Events>>(
28+
event: Event,
29+
...args: $ElementType<Events, Event>
30+
): void {
31+
const listeners = this.listenersMap.get(event);
32+
if (listeners !== undefined) {
33+
let caughtError = null;
34+
35+
listeners.forEach(listener => {
36+
try {
37+
listener.apply(null, args);
38+
} catch (error) {
39+
if (caughtError === null) {
40+
caughtError = error;
41+
}
42+
}
43+
});
44+
45+
if (caughtError !== null) {
46+
throw caughtError;
47+
}
48+
}
49+
}
50+
51+
removeAllListeners(event?: $Keys<Events>): void {
52+
if (event != null) {
53+
this.listenersMap.delete(event);
54+
} else {
55+
this.listenersMap.clear();
56+
}
57+
}
58+
59+
removeListener(event: $Keys<Events>, listener: Function): void {
60+
const listeners = this.listenersMap.get(event);
61+
if (listeners !== undefined) {
62+
listeners.delete(listener);
63+
}
64+
}
65+
}

scripts/flow/react-devtools.js

+1-16
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,4 @@
77
* @flow
88
*/
99

10-
declare module 'events' {
11-
declare class EventEmitter<Events: Object> {
12-
addListener<Event: $Keys<Events>>(
13-
event: Event,
14-
listener: (...$ElementType<Events, Event>) => any,
15-
): void;
16-
emit: <Event: $Keys<Events>>(
17-
event: Event,
18-
...$ElementType<Events, Event>
19-
) => void;
20-
removeListener(event: $Keys<Events>, listener: Function): void;
21-
removeAllListeners(event?: $Keys<Events>): void;
22-
}
23-
24-
declare export default typeof EventEmitter;
25-
}
10+
// No types

0 commit comments

Comments
 (0)