Reapply Check for event listener in props instead of bank (#8292)
* Reapply Check for event listener in props instead of bank (#8192) This reverts the previous revert. * Don't throw on falsy event listeners Some code relies on passing null. This restores the earlier behavior.
Sebastian Markbåge committed
Nov 15, 2016 at 18:16 UTC
dde670fd36d5f98769c54683fe04a63975f13247
15 files changed
+248
-491
scripts/fiber/tests-failing.txt
+4
-5
@@ -103,8 +103,6 @@ src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
103
* should validate against invalid styles
104
* should track input values
105
* should track textarea values
106
-* should execute custom event plugin listening behavior
107
-* should handle null and missing properly with event hooks
106
* should warn for children on void elements
107
* should support custom elements which extend native elements
108
* should warn against children for void elements
@@ -112,7 +110,6 @@ src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
110
* should validate against multiple children props
111
* should validate against invalid styles
112
* should report component containing invalid styles
115
-* should clean up listeners
113
* should clean up input value tracking
114
* should clean up input textarea tracking
115
* should throw when an invalid tag name is used
@@ -289,13 +286,11 @@ src/renderers/dom/stack/server/__tests__/ReactServerRendering-test.js
286
* should generate simple markup for self-closing tags
287
* should generate simple markup for attribute with `>` symbol
288
* should generate comment markup for component returns null
292
-* should not register event listeners
289
* should render composite components
290
* should only execute certain lifecycle methods
291
* should have the correct mounting behavior
292
* should not put checksum and React ID on components
293
* should not put checksum and React ID on text components
298
-* should not register event listeners
294
* should only execute certain lifecycle methods
295
* allows setState in componentWillMount without using DOM
296
* renders components with different batching strategies
@@ -410,6 +405,10 @@ src/renderers/shared/shared/__tests__/ReactTreeTraversal-test.js
405
* should leave to the window
406
* should leave to the window from the shallowest
407
408
+src/renderers/shared/shared/event/__tests__/EventPluginHub-test.js
409
+* should prevent non-function listeners, at dispatch
410
+* should not prevent null listeners, at dispatch
411
+
412
src/renderers/shared/stack/reconciler/__tests__/ReactComponent-test.js
413
* should throw on invalid render targets
414
* should throw when supplying a ref outside of render method
scripts/fiber/tests-passing.txt
-4
@@ -962,9 +962,6 @@ src/renderers/shared/shared/__tests__/ReactTreeTraversal-test.js
962
* should not traverse if enter/leave the same node
963
* should determine the first common ancestor correctly
964
965
-src/renderers/shared/shared/event/__tests__/EventPluginHub-test.js
966
-* should prevent non-function listeners
967
-
965
src/renderers/shared/shared/event/__tests__/EventPluginRegistry-test.js
966
* should be able to inject ordering before plugins
967
* should be able to inject plugins before and after ordering
@@ -1077,7 +1074,6 @@ src/renderers/shared/stack/reconciler/__tests__/ReactErrorBoundaries-test.js
1074
* propagates errors on retry on mounting
1075
* propagates errors inside boundary during componentWillMount
1076
* propagates errors inside boundary while rendering error state
1080
-* does not register event handlers for unmounted children
1077
* does not call componentWillUnmount when aborting initial mount
1078
* resets refs if mounting aborts
1079
* successfully mounts if no error occurs
src/renderers/dom/shared/ReactBrowserEventEmitter.js
-10
@@ -163,16 +163,6 @@ function getListeningForDocument(mountAt) {
163
return alreadyListeningTo[mountAt[topListenersIDKey]];
164
}
165
166
-/**
167
- * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For
168
- * example:
169
- *
170
- * EventPluginHub.putListener('myID', 'onClick', myFunction);
171
- *
172
- * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'.
173
- *
174
- * @internal
175
- */
166
var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
167
168
/**
src/renderers/dom/shared/__tests__/ReactBrowserEventEmitter-test.js
+175
-126
@@ -15,8 +15,9 @@ var EventListener;
15
var EventPluginHub;
16
var EventPluginRegistry;
17
var React;
18
-var ReactBrowserEventEmitter;
18
+var ReactDOM;
19
var ReactDOMComponentTree;
20
+var ReactBrowserEventEmitter;
21
var ReactTestUtils;
22
var TapEventPlugin;
23
@@ -43,18 +44,17 @@ var GRANDPARENT;
44
var PARENT;
45
var CHILD;
46
47
+var getListener;
48
+var putListener;
49
+var deleteAllListeners;
50
+
51
function registerSimpleTestHandler() {
47
- EventPluginHub.putListener(getInternal(CHILD), ON_CLICK_KEY, LISTENER);
48
- var listener = EventPluginHub.getListener(getInternal(CHILD), ON_CLICK_KEY);
52
+ putListener(CHILD, ON_CLICK_KEY, LISTENER);
53
+ var listener = getListener(CHILD, ON_CLICK_KEY);
54
expect(listener).toEqual(LISTENER);
50
- return EventPluginHub.getListener(getInternal(CHILD), ON_CLICK_KEY);
51
-}
52
-
53
-function getInternal(node) {
54
- return ReactDOMComponentTree.getInstanceFromNode(node);
55
+ return getListener(CHILD, ON_CLICK_KEY);
56
}
57
57
-
58
describe('ReactBrowserEventEmitter', () => {
59
beforeEach(() => {
60
jest.resetModuleRegistry();
@@ -63,18 +63,67 @@ describe('ReactBrowserEventEmitter', () => {
63
EventPluginHub = require('EventPluginHub');
64
EventPluginRegistry = require('EventPluginRegistry');
65
React = require('React');
66
- ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
66
+ ReactDOM = require('ReactDOM');
67
ReactDOMComponentTree = require('ReactDOMComponentTree');
68
+ ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
69
ReactTestUtils = require('ReactTestUtils');
70
TapEventPlugin = require('TapEventPlugin');
71
71
- ReactTestUtils.renderIntoDocument(
72
- <div ref={(c) => GRANDPARENT = c}>
73
- <div ref={(c) => PARENT = c}>
74
- <div ref={(c) => CHILD = c} />
75
- </div>
76
- </div>
77
- );
72
+ var container = document.createElement('div');
73
+
74
+ var GRANDPARENT_PROPS = {};
75
+ var PARENT_PROPS = {};
76
+ var CHILD_PROPS = {};
77
+
78
+ function renderTree() {
79
+ ReactDOM.render(
80
+ <div ref={(c) => GRANDPARENT = c} {...GRANDPARENT_PROPS}>
81
+ <div ref={(c) => PARENT = c} {...PARENT_PROPS}>
82
+ <div ref={(c) => CHILD = c} {...CHILD_PROPS} />
83
+ </div>
84
+ </div>,
85
+ container
86
+ );
87
+ }
88
+
89
+ renderTree();
90
+
91
+ getListener = function(node, eventName) {
92
+ var inst = ReactDOMComponentTree.getInstanceFromNode(node);
93
+ return EventPluginHub.getListener(
94
+ inst,
95
+ eventName
96
+ );
97
+ };
98
+ putListener = function(node, eventName, listener) {
99
+ switch (node) {
100
+ case CHILD:
101
+ CHILD_PROPS[eventName] = listener;
102
+ break;
103
+ case PARENT:
104
+ PARENT_PROPS[eventName] = listener;
105
+ break;
106
+ case GRANDPARENT:
107
+ GRANDPARENT_PROPS[eventName] = listener;
108
+ break;
109
+ }
110
+ // Rerender with new event listeners
111
+ renderTree();
112
+ };
113
+ deleteAllListeners = function(node) {
114
+ switch (node) {
115
+ case CHILD:
116
+ CHILD_PROPS = {};
117
+ break;
118
+ case PARENT:
119
+ PARENT_PROPS = {};
120
+ break;
121
+ case GRANDPARENT:
122
+ GRANDPARENT_PROPS = {};
123
+ break;
124
+ }
125
+ renderTree();
126
+ };
127
128
idCallOrder = [];
129
tapMoveThreshold = TapEventPlugin.tapMoveThreshold;
@@ -85,20 +134,20 @@ describe('ReactBrowserEventEmitter', () => {
134
135
it('should store a listener correctly', () => {
136
registerSimpleTestHandler();
88
- var listener = EventPluginHub.getListener(getInternal(CHILD), ON_CLICK_KEY);
137
+ var listener = getListener(CHILD, ON_CLICK_KEY);
138
expect(listener).toBe(LISTENER);
139
});
140
141
it('should retrieve a listener correctly', () => {
142
registerSimpleTestHandler();
94
- var listener = EventPluginHub.getListener(getInternal(CHILD), ON_CLICK_KEY);
143
+ var listener = getListener(CHILD, ON_CLICK_KEY);
144
expect(listener).toEqual(LISTENER);
145
});
146
147
it('should clear all handlers when asked to', () => {
148
registerSimpleTestHandler();
100
- EventPluginHub.deleteAllListeners(getInternal(CHILD));
101
- var listener = EventPluginHub.getListener(getInternal(CHILD), ON_CLICK_KEY);
149
+ deleteAllListeners(CHILD);
150
+ var listener = getListener(CHILD, ON_CLICK_KEY);
151
expect(listener).toBe(undefined);
152
});
153
@@ -122,153 +171,153 @@ describe('ReactBrowserEventEmitter', () => {
171
);
172
173
it('should bubble simply', () => {
125
- EventPluginHub.putListener(
126
- getInternal(CHILD),
174
+ putListener(
175
+ CHILD,
176
ON_CLICK_KEY,
128
- recordID.bind(null, getInternal(CHILD))
177
+ recordID.bind(null, CHILD)
178
);
130
- EventPluginHub.putListener(
131
- getInternal(PARENT),
179
+ putListener(
180
+ PARENT,
181
ON_CLICK_KEY,
133
- recordID.bind(null, getInternal(PARENT))
182
+ recordID.bind(null, PARENT)
183
);
135
- EventPluginHub.putListener(
136
- getInternal(GRANDPARENT),
184
+ putListener(
185
+ GRANDPARENT,
186
ON_CLICK_KEY,
138
- recordID.bind(null, getInternal(GRANDPARENT))
187
+ recordID.bind(null, GRANDPARENT)
188
);
189
ReactTestUtils.Simulate.click(CHILD);
190
expect(idCallOrder.length).toBe(3);
142
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
143
- expect(idCallOrder[1]).toBe(getInternal(PARENT));
144
- expect(idCallOrder[2]).toBe(getInternal(GRANDPARENT));
191
+ expect(idCallOrder[0]).toBe(CHILD);
192
+ expect(idCallOrder[1]).toBe(PARENT);
193
+ expect(idCallOrder[2]).toBe(GRANDPARENT);
194
});
195
196
it('should continue bubbling if an error is thrown', () => {
148
- EventPluginHub.putListener(
149
- getInternal(CHILD),
197
+ putListener(
198
+ CHILD,
199
ON_CLICK_KEY,
151
- recordID.bind(null, getInternal(CHILD))
200
+ recordID.bind(null, CHILD)
201
);
153
- EventPluginHub.putListener(
154
- getInternal(PARENT),
202
+ putListener(
203
+ PARENT,
204
ON_CLICK_KEY,
205
function() {
157
- recordID(getInternal(PARENT));
206
+ recordID(PARENT);
207
throw new Error('Handler interrupted');
208
}
209
);
161
- EventPluginHub.putListener(
162
- getInternal(GRANDPARENT),
210
+ putListener(
211
+ GRANDPARENT,
212
ON_CLICK_KEY,
164
- recordID.bind(null, getInternal(GRANDPARENT))
213
+ recordID.bind(null, GRANDPARENT)
214
);
215
expect(function() {
216
ReactTestUtils.Simulate.click(CHILD);
217
}).toThrow();
218
expect(idCallOrder.length).toBe(3);
170
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
171
- expect(idCallOrder[1]).toBe(getInternal(PARENT));
172
- expect(idCallOrder[2]).toBe(getInternal(GRANDPARENT));
219
+ expect(idCallOrder[0]).toBe(CHILD);
220
+ expect(idCallOrder[1]).toBe(PARENT);
221
+ expect(idCallOrder[2]).toBe(GRANDPARENT);
222
});
223
224
it('should set currentTarget', () => {
176
- EventPluginHub.putListener(
177
- getInternal(CHILD),
225
+ putListener(
226
+ CHILD,
227
ON_CLICK_KEY,
228
function(event) {
180
- recordID(getInternal(CHILD));
229
+ recordID(CHILD);
230
expect(event.currentTarget).toBe(CHILD);
231
}
232
);
184
- EventPluginHub.putListener(
185
- getInternal(PARENT),
233
+ putListener(
234
+ PARENT,
235
ON_CLICK_KEY,
236
function(event) {
188
- recordID(getInternal(PARENT));
237
+ recordID(PARENT);
238
expect(event.currentTarget).toBe(PARENT);
239
}
240
);
192
- EventPluginHub.putListener(
193
- getInternal(GRANDPARENT),
241
+ putListener(
242
+ GRANDPARENT,
243
ON_CLICK_KEY,
244
function(event) {
196
- recordID(getInternal(GRANDPARENT));
245
+ recordID(GRANDPARENT);
246
expect(event.currentTarget).toBe(GRANDPARENT);
247
}
248
);
249
ReactTestUtils.Simulate.click(CHILD);
250
expect(idCallOrder.length).toBe(3);
202
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
203
- expect(idCallOrder[1]).toBe(getInternal(PARENT));
204
- expect(idCallOrder[2]).toBe(getInternal(GRANDPARENT));
251
+ expect(idCallOrder[0]).toBe(CHILD);
252
+ expect(idCallOrder[1]).toBe(PARENT);
253
+ expect(idCallOrder[2]).toBe(GRANDPARENT);
254
});
255
256
it('should support stopPropagation()', () => {
208
- EventPluginHub.putListener(
209
- getInternal(CHILD),
257
+ putListener(
258
+ CHILD,
259
ON_CLICK_KEY,
211
- recordID.bind(null, getInternal(CHILD))
260
+ recordID.bind(null, CHILD)
261
);
213
- EventPluginHub.putListener(
214
- getInternal(PARENT),
262
+ putListener(
263
+ PARENT,
264
ON_CLICK_KEY,
216
- recordIDAndStopPropagation.bind(null, getInternal(PARENT))
265
+ recordIDAndStopPropagation.bind(null, PARENT)
266
);
218
- EventPluginHub.putListener(
219
- getInternal(GRANDPARENT),
267
+ putListener(
268
+ GRANDPARENT,
269
ON_CLICK_KEY,
221
- recordID.bind(null, getInternal(GRANDPARENT))
270
+ recordID.bind(null, GRANDPARENT)
271
);
272
ReactTestUtils.Simulate.click(CHILD);
273
expect(idCallOrder.length).toBe(2);
225
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
226
- expect(idCallOrder[1]).toBe(getInternal(PARENT));
274
+ expect(idCallOrder[0]).toBe(CHILD);
275
+ expect(idCallOrder[1]).toBe(PARENT);
276
});
277
278
it('should stop after first dispatch if stopPropagation', () => {
230
- EventPluginHub.putListener(
231
- getInternal(CHILD),
279
+ putListener(
280
+ CHILD,
281
ON_CLICK_KEY,
233
- recordIDAndStopPropagation.bind(null, getInternal(CHILD))
282
+ recordIDAndStopPropagation.bind(null, CHILD)
283
);
235
- EventPluginHub.putListener(
236
- getInternal(PARENT),
284
+ putListener(
285
+ PARENT,
286
ON_CLICK_KEY,
238
- recordID.bind(null, getInternal(PARENT))
287
+ recordID.bind(null, PARENT)
288
);
240
- EventPluginHub.putListener(
241
- getInternal(GRANDPARENT),
289
+ putListener(
290
+ GRANDPARENT,
291
ON_CLICK_KEY,
243
- recordID.bind(null, getInternal(GRANDPARENT))
292
+ recordID.bind(null, GRANDPARENT)
293
);
294
ReactTestUtils.Simulate.click(CHILD);
295
expect(idCallOrder.length).toBe(1);
247
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
296
+ expect(idCallOrder[0]).toBe(CHILD);
297
});
298
299
it('should not stopPropagation if false is returned', () => {
251
- EventPluginHub.putListener(
252
- getInternal(CHILD),
300
+ putListener(
301
+ CHILD,
302
ON_CLICK_KEY,
254
- recordIDAndReturnFalse.bind(null, getInternal(CHILD))
303
+ recordIDAndReturnFalse.bind(null, CHILD)
304
);
256
- EventPluginHub.putListener(
257
- getInternal(PARENT),
305
+ putListener(
306
+ PARENT,
307
ON_CLICK_KEY,
259
- recordID.bind(null, getInternal(PARENT))
308
+ recordID.bind(null, PARENT)
309
);
261
- EventPluginHub.putListener(
262
- getInternal(GRANDPARENT),
310
+ putListener(
311
+ GRANDPARENT,
312
ON_CLICK_KEY,
264
- recordID.bind(null, getInternal(GRANDPARENT))
313
+ recordID.bind(null, GRANDPARENT)
314
);
315
spyOn(console, 'error');
316
ReactTestUtils.Simulate.click(CHILD);
317
expect(idCallOrder.length).toBe(3);
269
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
270
- expect(idCallOrder[1]).toBe(getInternal(PARENT));
271
- expect(idCallOrder[2]).toBe(getInternal(GRANDPARENT));
318
+ expect(idCallOrder[0]).toBe(CHILD);
319
+ expect(idCallOrder[1]).toBe(PARENT);
320
+ expect(idCallOrder[2]).toBe(GRANDPARENT);
321
expectDev(console.error.calls.count()).toEqual(0);
322
});
323
@@ -284,15 +333,15 @@ describe('ReactBrowserEventEmitter', () => {
333
it('should invoke handlers that were removed while bubbling', () => {
334
var handleParentClick = jest.fn();
335
var handleChildClick = function(event) {
287
- EventPluginHub.deleteAllListeners(getInternal(PARENT));
336
+ deleteAllListeners(PARENT);
337
};
289
- EventPluginHub.putListener(
290
- getInternal(CHILD),
338
+ putListener(
339
+ CHILD,
340
ON_CLICK_KEY,
341
handleChildClick
342
);
294
- EventPluginHub.putListener(
295
- getInternal(PARENT),
343
+ putListener(
344
+ PARENT,
345
ON_CLICK_KEY,
346
handleParentClick
347
);
@@ -303,14 +352,14 @@ describe('ReactBrowserEventEmitter', () => {
352
it('should not invoke newly inserted handlers while bubbling', () => {
353
var handleParentClick = jest.fn();
354
var handleChildClick = function(event) {
306
- EventPluginHub.putListener(
307
- getInternal(PARENT),
355
+ putListener(
356
+ PARENT,
357
ON_CLICK_KEY,
358
handleParentClick
359
);
360
};
312
- EventPluginHub.putListener(
313
- getInternal(CHILD),
361
+ putListener(
362
+ CHILD,
363
ON_CLICK_KEY,
364
handleChildClick
365
);
@@ -319,21 +368,21 @@ describe('ReactBrowserEventEmitter', () => {
368
});
369
370
it('should have mouse enter simulated by test utils', () => {
322
- EventPluginHub.putListener(
323
- getInternal(CHILD),
371
+ putListener(
372
+ CHILD,
373
ON_MOUSE_ENTER_KEY,
325
- recordID.bind(null, getInternal(CHILD))
374
+ recordID.bind(null, CHILD)
375
);
376
ReactTestUtils.Simulate.mouseEnter(CHILD);
377
expect(idCallOrder.length).toBe(1);
329
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
378
+ expect(idCallOrder[0]).toBe(CHILD);
379
});
380
381
it('should infer onTouchTap from a touchStart/End', () => {
333
- EventPluginHub.putListener(
334
- getInternal(CHILD),
382
+ putListener(
383
+ CHILD,
384
ON_TOUCH_TAP_KEY,
336
- recordID.bind(null, getInternal(CHILD))
385
+ recordID.bind(null, CHILD)
386
);
387
ReactTestUtils.SimulateNative.touchStart(
388
CHILD,
@@ -344,14 +393,14 @@ describe('ReactBrowserEventEmitter', () => {
393
ReactTestUtils.nativeTouchData(0, 0)
394
);
395
expect(idCallOrder.length).toBe(1);
347
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
396
+ expect(idCallOrder[0]).toBe(CHILD);
397
});
398
399
it('should infer onTouchTap from when dragging below threshold', () => {
351
- EventPluginHub.putListener(
352
- getInternal(CHILD),
400
+ putListener(
401
+ CHILD,
402
ON_TOUCH_TAP_KEY,
354
- recordID.bind(null, getInternal(CHILD))
403
+ recordID.bind(null, CHILD)
404
);
405
ReactTestUtils.SimulateNative.touchStart(
406
CHILD,
@@ -362,14 +411,14 @@ describe('ReactBrowserEventEmitter', () => {
411
ReactTestUtils.nativeTouchData(0, tapMoveThreshold - 1)
412
);
413
expect(idCallOrder.length).toBe(1);
365
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
414
+ expect(idCallOrder[0]).toBe(CHILD);
415
});
416
417
it('should not onTouchTap from when dragging beyond threshold', () => {
369
- EventPluginHub.putListener(
370
- getInternal(CHILD),
418
+ putListener(
419
+ CHILD,
420
ON_TOUCH_TAP_KEY,
372
- recordID.bind(null, getInternal(CHILD))
421
+ recordID.bind(null, CHILD)
422
);
423
ReactTestUtils.SimulateNative.touchStart(
424
CHILD,
@@ -423,20 +472,20 @@ describe('ReactBrowserEventEmitter', () => {
472
});
473
474
it('should bubble onTouchTap', () => {
426
- EventPluginHub.putListener(
427
- getInternal(CHILD),
475
+ putListener(
476
+ CHILD,
477
ON_TOUCH_TAP_KEY,
429
- recordID.bind(null, getInternal(CHILD))
478
+ recordID.bind(null, CHILD)
479
);
431
- EventPluginHub.putListener(
432
- getInternal(PARENT),
480
+ putListener(
481
+ PARENT,
482
ON_TOUCH_TAP_KEY,
434
- recordID.bind(null, getInternal(PARENT))
483
+ recordID.bind(null, PARENT)
484
);
436
- EventPluginHub.putListener(
437
- getInternal(GRANDPARENT),
485
+ putListener(
486
+ GRANDPARENT,
487
ON_TOUCH_TAP_KEY,
439
- recordID.bind(null, getInternal(GRANDPARENT))
488
+ recordID.bind(null, GRANDPARENT)
489
);
490
ReactTestUtils.SimulateNative.touchStart(
491
CHILD,
@@ -447,9 +496,9 @@ describe('ReactBrowserEventEmitter', () => {
496
ReactTestUtils.nativeTouchData(0, 0)
497
);
498
expect(idCallOrder.length).toBe(3);
450
- expect(idCallOrder[0]).toBe(getInternal(CHILD));
451
- expect(idCallOrder[1]).toBe(getInternal(PARENT));
452
- expect(idCallOrder[2]).toBe(getInternal(GRANDPARENT));
499
+ expect(idCallOrder[0]).toBe(CHILD);
500
+ expect(idCallOrder[1]).toBe(PARENT);
501
+ expect(idCallOrder[2]).toBe(GRANDPARENT);
502
});
503
504
it('should not crash ensureScrollValueMonitoring when createEvent returns null', () => {
src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
-80
@@ -972,61 +972,6 @@ describe('ReactDOMComponent', () => {
972
expect(tracker.getValue()).toEqual('foo');
973
});
974
975
- it('should execute custom event plugin listening behavior', () => {
976
- var SimpleEventPlugin = require('SimpleEventPlugin');
977
-
978
- SimpleEventPlugin.didPutListener = jest.fn();
979
- SimpleEventPlugin.willDeleteListener = jest.fn();
980
-
981
- var container = document.createElement('div');
982
- ReactDOM.render(
983
- <div onClick={() => true} />,
984
- container
985
- );
986
-
987
- expect(SimpleEventPlugin.didPutListener.mock.calls.length).toBe(1);
988
-
989
- ReactDOM.unmountComponentAtNode(container);
990
-
991
- expect(SimpleEventPlugin.willDeleteListener.mock.calls.length).toBe(1);
992
- });
993
-
994
- it('should handle null and missing properly with event hooks', () => {
995
- var SimpleEventPlugin = require('SimpleEventPlugin');
996
-
997
- SimpleEventPlugin.didPutListener = jest.fn();
998
- SimpleEventPlugin.willDeleteListener = jest.fn();
999
- var container = document.createElement('div');
1000
-
1001
- ReactDOM.render(<div onClick={false} />, container);
1002
- expect(SimpleEventPlugin.didPutListener.mock.calls.length).toBe(0);
1003
- expect(SimpleEventPlugin.willDeleteListener.mock.calls.length).toBe(0);
1004
-
1005
- ReactDOM.render(<div onClick={null} />, container);
1006
- expect(SimpleEventPlugin.didPutListener.mock.calls.length).toBe(0);
1007
- expect(SimpleEventPlugin.willDeleteListener.mock.calls.length).toBe(0);
1008
-
1009
- ReactDOM.render(<div onClick={() => 'apple'} />, container);
1010
- expect(SimpleEventPlugin.didPutListener.mock.calls.length).toBe(1);
1011
- expect(SimpleEventPlugin.willDeleteListener.mock.calls.length).toBe(0);
1012
-
1013
- ReactDOM.render(<div onClick={() => 'banana'} />, container);
1014
- expect(SimpleEventPlugin.didPutListener.mock.calls.length).toBe(2);
1015
- expect(SimpleEventPlugin.willDeleteListener.mock.calls.length).toBe(0);
1016
-
1017
- ReactDOM.render(<div onClick={null} />, container);
1018
- expect(SimpleEventPlugin.didPutListener.mock.calls.length).toBe(2);
1019
- expect(SimpleEventPlugin.willDeleteListener.mock.calls.length).toBe(1);
1020
-
1021
- ReactDOM.render(<div />, container);
1022
- expect(SimpleEventPlugin.didPutListener.mock.calls.length).toBe(2);
1023
- expect(SimpleEventPlugin.willDeleteListener.mock.calls.length).toBe(1);
1024
-
1025
- ReactDOM.unmountComponentAtNode(container);
1026
- expect(SimpleEventPlugin.didPutListener.mock.calls.length).toBe(2);
1027
- expect(SimpleEventPlugin.willDeleteListener.mock.calls.length).toBe(1);
1028
- });
1029
-
975
it('should warn for children on void elements', () => {
976
class X extends React.Component {
977
render() {
@@ -1157,31 +1102,6 @@ describe('ReactDOMComponent', () => {
1102
});
1103
1104
describe('unmountComponent', () => {
1160
- it('should clean up listeners', () => {
1161
- var EventPluginHub = require('EventPluginHub');
1162
- var ReactDOMComponentTree = require('ReactDOMComponentTree');
1163
-
1164
- var container = document.createElement('div');
1165
- document.body.appendChild(container);
1166
-
1167
- var callback = function() {};
1168
- var instance = <div onClick={callback} />;
1169
- instance = ReactDOM.render(instance, container);
1170
-
1171
- var rootNode = ReactDOM.findDOMNode(instance);
1172
- var inst = ReactDOMComponentTree.getInstanceFromNode(rootNode);
1173
- expect(
1174
- EventPluginHub.getListener(inst, 'onClick')
1175
- ).toBe(callback);
1176
- expect(rootNode).toBe(ReactDOM.findDOMNode(instance));
1177
-
1178
- ReactDOM.unmountComponentAtNode(container);
1179
-
1180
- expect(
1181
- EventPluginHub.getListener(inst, 'onClick')
1182
- ).toBe(undefined);
1183
- });
1184
-
1105
it('should clean up input value tracking', () => {
1106
var container = document.createElement('div');
1107
var node = ReactDOM.render(<input type="text" defaultValue="foo"/>, container);
src/renderers/dom/stack/client/ReactDOMComponent.js
+3
-46
@@ -19,7 +19,6 @@ var DOMLazyTree = require('DOMLazyTree');
19
var DOMNamespaces = require('DOMNamespaces');
20
var DOMProperty = require('DOMProperty');
21
var DOMPropertyOperations = require('DOMPropertyOperations');
22
-var EventPluginHub = require('EventPluginHub');
22
var EventPluginRegistry = require('EventPluginRegistry');
23
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
24
var ReactDOMComponentFlags = require('ReactDOMComponentFlags');
@@ -43,7 +42,6 @@ var warning = require('warning');
42
var didWarnShadyDOM = false;
43
44
var Flags = ReactDOMComponentFlags;
46
-var deleteListener = EventPluginHub.deleteListener;
45
var getNode = ReactDOMComponentTree.getNodeFromInstance;
46
var listenTo = ReactBrowserEventEmitter.listenTo;
47
var registrationNameModules = EventPluginRegistry.registrationNameModules;
@@ -205,30 +203,6 @@ function assertValidProps(component, props) {
203
);
204
}
205
208
-function enqueuePutListener(inst, registrationName, listener, transaction) {
209
- if (transaction instanceof ReactServerRenderingTransaction) {
210
- return;
211
- }
212
- if (__DEV__) {
213
- // IE8 has no API for event capturing and the `onScroll` event doesn't
214
- // bubble.
215
- warning(
216
- registrationName !== 'onScroll' || isEventSupported('scroll', true),
217
- 'This browser doesn\'t support the `onScroll` event'
218
- );
219
- }
220
- var containerInfo = inst._hostContainerInfo;
221
- var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;
222
- var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;
223
- listenTo(registrationName, doc);
224
- transaction.getReactMountReady().enqueue(putListener, {
225
- inst: inst,
226
- registrationName: registrationName,
227
- listener: listener,
228
- });
229
-}
230
-
231
-// TODO: This is coming from future #8192. Dedupe this and enqueuePutListener.
206
function ensureListeningTo(inst, registrationName, transaction) {
207
if (transaction instanceof ReactServerRenderingTransaction) {
208
return;
@@ -247,15 +221,6 @@ function ensureListeningTo(inst, registrationName, transaction) {
221
listenTo(registrationName, doc);
222
}
223
250
-function putListener() {
251
- var listenerToPut = this;
252
- EventPluginHub.putListener(
253
- listenerToPut.inst,
254
- listenerToPut.registrationName,
255
- listenerToPut.listener
256
- );
257
-}
258
-
224
function inputPostMount() {
225
var inst = this;
226
ReactDOMInput.postMountWrapper(inst);
@@ -792,7 +757,7 @@ ReactDOMComponent.Mixin = {
757
}
758
if (registrationNameModules.hasOwnProperty(propKey)) {
759
if (propValue) {
795
- enqueuePutListener(this, propKey, propValue, transaction);
760
+ ensureListeningTo(this, propKey, transaction);
761
}
762
} else {
763
if (propKey === STYLE) {
@@ -1047,12 +1012,7 @@ ReactDOMComponent.Mixin = {
1012
}
1013
this._previousStyleCopy = null;
1014
} else if (registrationNameModules.hasOwnProperty(propKey)) {
1050
- if (lastProps[propKey]) {
1051
- // Only call deleteListener if there was a listener previously or
1052
- // else willDeleteListener gets called when there wasn't actually a
1053
- // listener (e.g., onClick={null})
1054
- deleteListener(this, propKey);
1055
- }
1015
+ // Do nothing for event names.
1016
} else if (isCustomComponent(this._tag, lastProps)) {
1017
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
1018
DOMPropertyOperations.deleteValueForAttribute(
@@ -1113,9 +1073,7 @@ ReactDOMComponent.Mixin = {
1073
}
1074
} else if (registrationNameModules.hasOwnProperty(propKey)) {
1075
if (nextProp) {
1116
- enqueuePutListener(this, propKey, nextProp, transaction);
1117
- } else if (lastProp) {
1118
- deleteListener(this, propKey);
1076
+ ensureListeningTo(this, propKey, transaction);
1077
}
1078
} else if (isCustomComponentTag) {
1079
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
@@ -1264,7 +1222,6 @@ ReactDOMComponent.Mixin = {
1222
1223
this.unmountChildren(safely, skipLifecycle);
1224
ReactDOMComponentTree.uncacheNode(this);
1267
- EventPluginHub.deleteAllListeners(this);
1225
this._rootNodeID = 0;
1226
this._domID = 0;
1227
this._wrapperState = null;
src/renderers/dom/stack/server/__tests__/ReactServerRendering-test.js
+1
-19
@@ -85,15 +85,7 @@ describe('ReactServerRendering', () => {
85
expect(response).toBe('<!-- react-empty: 1 -->');
86
});
87
88
- it('should not register event listeners', () => {
89
- var EventPluginHub = require('EventPluginHub');
90
- var cb = jest.fn();
91
-
92
- ReactServerRendering.renderToString(
93
- <span onClick={cb}>hello world</span>
94
- );
95
- expect(EventPluginHub.__getListenerBank()).toEqual({});
96
- });
88
+ // TODO: Test that listeners are not registered onto any document/container.
89
90
it('should render composite components', () => {
91
class Parent extends React.Component {
@@ -322,16 +314,6 @@ describe('ReactServerRendering', () => {
314
expect(response).toBe('<span>hello world</span>');
315
});
316
325
- it('should not register event listeners', () => {
326
- var EventPluginHub = require('EventPluginHub');
327
- var cb = jest.fn();
328
-
329
- ReactServerRendering.renderToStaticMarkup(
330
- <span onClick={cb}>hello world</span>
331
- );
332
- expect(EventPluginHub.__getListenerBank()).toEqual({});
333
- });
334
-
317
it('should only execute certain lifecycle methods', () => {
318
function runTest() {
319
var lifecycle = [];
src/renderers/native/ReactNativeBaseComponent.js
-43
@@ -14,18 +14,12 @@
14
var NativeMethodsMixin = require('NativeMethodsMixin');
15
var ReactNativeAttributePayload = require('ReactNativeAttributePayload');
16
var ReactNativeComponentTree = require('ReactNativeComponentTree');
17
-var ReactNativeEventEmitter = require('ReactNativeEventEmitter');
17
var ReactNativeTagHandles = require('ReactNativeTagHandles');
18
var ReactMultiChild = require('ReactMultiChild');
19
var UIManager = require('UIManager');
20
21
var deepFreezeAndThrowOnMutationInDev = require('deepFreezeAndThrowOnMutationInDev');
22
24
-var registrationNames = ReactNativeEventEmitter.registrationNames;
25
-var putListener = ReactNativeEventEmitter.putListener;
26
-var deleteListener = ReactNativeEventEmitter.deleteListener;
27
-var deleteAllListeners = ReactNativeEventEmitter.deleteAllListeners;
28
-
23
type ReactNativeBaseComponentViewConfig = {
24
validAttributes: Object;
25
uiViewClassName: string;
@@ -57,7 +51,6 @@ ReactNativeBaseComponent.Mixin = {
51
52
unmountComponent: function(safely, skipLifecycle) {
53
ReactNativeComponentTree.uncacheNode(this);
60
- deleteAllListeners(this);
54
this.unmountChildren(safely, skipLifecycle);
55
this._rootNodeID = 0;
56
},
@@ -123,44 +116,9 @@ ReactNativeBaseComponent.Mixin = {
116
);
117
}
118
126
- this._reconcileListenersUponUpdate(
127
- prevElement.props,
128
- nextElement.props
129
- );
119
this.updateChildren(nextElement.props.children, transaction, context);
120
},
121
133
- /**
134
- * @param {object} initialProps Native component props.
135
- */
136
- _registerListenersUponCreation: function(initialProps) {
137
- for (var key in initialProps) {
138
- // NOTE: The check for `!props[key]`, is only possible because this method
139
- // registers listeners the *first* time a component is created.
140
- if (registrationNames[key] && initialProps[key]) {
141
- var listener = initialProps[key];
142
- putListener(this, key, listener);
143
- }
144
- }
145
- },
146
-
147
- /**
148
- * Reconciles event listeners, adding or removing if necessary.
149
- * @param {object} prevProps Native component props including events.
150
- * @param {object} nextProps Next native component props including events.
151
- */
152
- _reconcileListenersUponUpdate: function(prevProps, nextProps) {
153
- for (var key in nextProps) {
154
- if (registrationNames[key] && (nextProps[key] !== prevProps[key])) {
155
- if (nextProps[key]) {
156
- putListener(this, key, nextProps[key]);
157
- } else {
158
- deleteListener(this, key);
159
- }
160
- }
161
- }
162
- },
163
-
122
/**
123
* Currently this still uses IDs for reconciliation so this can return null.
124
*
@@ -207,7 +165,6 @@ ReactNativeBaseComponent.Mixin = {
165
166
ReactNativeComponentTree.precacheNode(this, tag);
167
210
- this._registerListenersUponCreation(this._currentElement.props);
168
this.initializeChildren(
169
this._currentElement.props.children,
170
tag,
src/renderers/native/ReactNativeEventEmitter.js
-15
@@ -78,29 +78,14 @@ var removeTouchesAtIndices = function(
78
return rippedOut;
79
};
80
81
-/**
82
- * `ReactNativeEventEmitter` is used to attach top-level event listeners. For example:
83
- *
84
- * ReactNativeEventEmitter.putListener('myID', 'onClick', myFunction);
85
- *
86
- * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'.
87
- *
88
- * @internal
89
- */
81
var ReactNativeEventEmitter = {
82
83
...ReactEventEmitterMixin,
84
85
registrationNames: EventPluginRegistry.registrationNameModules,
86
96
- putListener: EventPluginHub.putListener,
97
-
87
getListener: EventPluginHub.getListener,
88
100
- deleteListener: EventPluginHub.deleteListener,
101
-
102
- deleteAllListeners: EventPluginHub.deleteAllListeners,
103
-
89
/**
90
* Internal version of `receiveEvent` in terms of normalized (non-tag)
91
* `rootNodeID`.
src/renderers/shared/shared/event/EventPluginHub.js
+7
-97
@@ -19,11 +19,6 @@ var accumulateInto = require('accumulateInto');
19
var forEachAccumulated = require('forEachAccumulated');
20
var invariant = require('invariant');
21
22
-/**
23
- * Internal store for event listeners
24
- */
25
-var listenerBank = {};
26
-
22
/**
23
* Internal queue of events that have accumulated their dispatches and are
24
* waiting to have their dispatches executed.
@@ -53,12 +48,6 @@ var executeDispatchesAndReleaseTopLevel = function(e) {
48
return executeDispatchesAndRelease(e, false);
49
};
50
56
-var getDictionaryKey = function(inst) {
57
- // Prevents V8 performance issue:
58
- // https://github.com/facebook/react/pull/7232
59
- return '.' + inst._rootNodeID;
60
-};
61
-
51
/**
52
* This is a unified interface for event plugins to be installed and configured.
53
*
@@ -102,87 +91,19 @@ var EventPluginHub = {
91
},
92
93
/**
105
- * Stores `listener` at `listenerBank[registrationName][key]`. Is idempotent.
106
- *
94
* @param {object} inst The instance, which is the source of events.
95
* @param {string} registrationName Name of listener (e.g. `onClick`).
109
- * @param {function} listener The callback to store.
96
+ * @return {?function} The stored callback.
97
*/
111
- putListener: function(inst, registrationName, listener) {
98
+ getListener: function(inst, registrationName) {
99
+ var listener = inst._currentElement.props[registrationName];
100
invariant(
113
- typeof listener === 'function',
101
+ !listener || typeof listener === 'function',
102
'Expected %s listener to be a function, instead got type %s',
115
- registrationName, typeof listener
103
+ registrationName,
104
+ typeof listener
105
);
117
-
118
- var key = getDictionaryKey(inst);
119
- var bankForRegistrationName =
120
- listenerBank[registrationName] || (listenerBank[registrationName] = {});
121
- bankForRegistrationName[key] = listener;
122
-
123
- var PluginModule =
124
- EventPluginRegistry.registrationNameModules[registrationName];
125
- if (PluginModule && PluginModule.didPutListener) {
126
- PluginModule.didPutListener(inst, registrationName, listener);
127
- }
128
- },
129
-
130
- /**
131
- * @param {object} inst The instance, which is the source of events.
132
- * @param {string} registrationName Name of listener (e.g. `onClick`).
133
- * @return {?function} The stored callback.
134
- */
135
- getListener: function(inst, registrationName) {
136
- var bankForRegistrationName = listenerBank[registrationName];
137
- var key = getDictionaryKey(inst);
138
- return bankForRegistrationName && bankForRegistrationName[key];
139
- },
140
-
141
- /**
142
- * Deletes a listener from the registration bank.
143
- *
144
- * @param {object} inst The instance, which is the source of events.
145
- * @param {string} registrationName Name of listener (e.g. `onClick`).
146
- */
147
- deleteListener: function(inst, registrationName) {
148
- var PluginModule =
149
- EventPluginRegistry.registrationNameModules[registrationName];
150
- if (PluginModule && PluginModule.willDeleteListener) {
151
- PluginModule.willDeleteListener(inst, registrationName);
152
- }
153
-
154
- var bankForRegistrationName = listenerBank[registrationName];
155
- // TODO: This should never be null -- when is it?
156
- if (bankForRegistrationName) {
157
- var key = getDictionaryKey(inst);
158
- delete bankForRegistrationName[key];
159
- }
160
- },
161
-
162
- /**
163
- * Deletes all listeners for the DOM element with the supplied ID.
164
- *
165
- * @param {object} inst The instance, which is the source of events.
166
- */
167
- deleteAllListeners: function(inst) {
168
- var key = getDictionaryKey(inst);
169
- for (var registrationName in listenerBank) {
170
- if (!listenerBank.hasOwnProperty(registrationName)) {
171
- continue;
172
- }
173
-
174
- if (!listenerBank[registrationName][key]) {
175
- continue;
176
- }
177
-
178
- var PluginModule =
179
- EventPluginRegistry.registrationNameModules[registrationName];
180
- if (PluginModule && PluginModule.willDeleteListener) {
181
- PluginModule.willDeleteListener(inst, registrationName);
182
- }
183
-
184
- delete listenerBank[registrationName][key];
185
- }
106
+ return listener;
107
},
108
109
/**
@@ -260,17 +181,6 @@ var EventPluginHub = {
181
ReactErrorUtils.rethrowCaughtError();
182
},
183
263
- /**
264
- * These are needed for tests only. Do not use!
265
- */
266
- __purge: function() {
267
- listenerBank = {};
268
- },
269
-
270
- __getListenerBank: function() {
271
- return listenerBank;
272
- },
273
-
184
};
185
186
module.exports = EventPluginHub;
src/renderers/shared/shared/event/EventPluginRegistry.js
+1
-2
@@ -130,8 +130,7 @@ function publishEventForPlugin(
130
}
131
132
/**
133
- * Publishes a registration name that is used to identify dispatched events and
134
- * can be used with `EventPluginHub.putListener` to register listeners.
133
+ * Publishes a registration name that is used to identify dispatched events.
134
*
135
* @param {string} registrationName Registration name to add.
136
* @param {object} PluginModule Plugin publishing the event.
src/renderers/shared/shared/event/PluginModuleType.js
-9
@@ -36,14 +36,5 @@ export type PluginModule<NativeEvent> = {
36
nativeTarget: NativeEvent,
37
nativeEventTarget: EventTarget,
38
) => null | ReactSyntheticEvent,
39
- didPutListener?: (
40
- inst: ReactInstance,
41
- registrationName: string,
42
- listener: () => void,
43
- ) => void,
44
- willDeleteListener?: (
45
- inst: ReactInstance,
46
- registrationName: string,
47
- ) => void,
39
tapMoveThreshold?: number,
40
};
src/renderers/shared/shared/event/__tests__/EventPluginHub-test.js
+19
-7
@@ -14,21 +14,33 @@
14
jest.mock('isEventSupported');
15
16
describe('EventPluginHub', () => {
17
- var EventPluginHub;
18
- var isEventSupported;
17
+ var React;
18
+ var ReactTestUtils;
19
20
beforeEach(() => {
21
jest.resetModuleRegistry();
22
- EventPluginHub = require('EventPluginHub');
23
- isEventSupported = require('isEventSupported');
24
- isEventSupported.mockReturnValueOnce(false);
22
+ React = require('React');
23
+ ReactTestUtils = require('ReactTestUtils');
24
});
25
27
- it('should prevent non-function listeners', () => {
26
+ it('should prevent non-function listeners, at dispatch', () => {
27
+ var node = ReactTestUtils.renderIntoDocument(
28
+ <div onClick="not a function" />
29
+ );
30
expect(function() {
29
- EventPluginHub.putListener(1, 'onClick', 'not a function');
31
+ ReactTestUtils.SimulateNative.click(node);
32
}).toThrowError(
33
'Expected onClick listener to be a function, instead got type string'
34
);
35
});
36
+
37
+ it('should not prevent null listeners, at dispatch', () => {
38
+ var node = ReactTestUtils.renderIntoDocument(
39
+ <div onClick={null} />
40
+ );
41
+ expect(function() {
42
+ ReactTestUtils.SimulateNative.click(node);
43
+ }).not.toThrow();
44
+ });
45
+
46
});
src/renderers/shared/shared/event/eventPlugins/__tests__/ResponderEventPlugin-test.js
+38
-8
@@ -233,7 +233,7 @@ var registerTestHandlers = function(eventTestConfig, readableIDToID) {
233
}
234
return config.returnVal;
235
}.bind(null, readableID, nodeConfig);
236
- EventPluginHub.putListener(getInstanceFromNode(id), registrationName, handler);
236
+ putListener(getInstanceFromNode(id), registrationName, handler);
237
}
238
};
239
for (var eventName in eventTestConfig) {
@@ -258,9 +258,6 @@ var registerTestHandlers = function(eventTestConfig, readableIDToID) {
258
return runs;
259
};
260
261
-
262
-
263
-
261
var run = function(config, hierarchyConfig, nativeEventConfig) {
262
var max = NA;
263
var searchForMax = function(nodeConfig) {
@@ -309,10 +306,30 @@ var PARENT_HOST_NODE = { };
306
var CHILD_HOST_NODE = { };
307
var CHILD_HOST_NODE2 = { };
308
312
-var GRANDPARENT_INST = { _hostParent: null, _rootNodeID: '1', _hostNode: GRANDPARENT_HOST_NODE };
313
-var PARENT_INST = { _hostParent: GRANDPARENT_INST, _rootNodeID: '2', _hostNode: PARENT_HOST_NODE };
314
-var CHILD_INST = { _hostParent: PARENT_INST, _rootNodeID: '3', _hostNode: CHILD_HOST_NODE };
315
-var CHILD_INST2 = { _hostParent: PARENT_INST, _rootNodeID: '4', _hostNode: CHILD_HOST_NODE2 };
309
+var GRANDPARENT_INST = {
310
+ _hostParent: null,
311
+ _rootNodeID: '1',
312
+ _hostNode: GRANDPARENT_HOST_NODE,
313
+ _currentElement: { props: {} },
314
+};
315
+var PARENT_INST = {
316
+ _hostParent: GRANDPARENT_INST,
317
+ _rootNodeID: '2',
318
+ _hostNode: PARENT_HOST_NODE,
319
+ _currentElement: { props: {} },
320
+};
321
+var CHILD_INST = {
322
+ _hostParent: PARENT_INST,
323
+ _rootNodeID: '3',
324
+ _hostNode: CHILD_HOST_NODE,
325
+ _currentElement: { props: {} },
326
+};
327
+var CHILD_INST2 = {
328
+ _hostParent: PARENT_INST,
329
+ _rootNodeID: '4',
330
+ _hostNode: CHILD_HOST_NODE2,
331
+ _currentElement: { props: {} },
332
+};
333
334
GRANDPARENT_HOST_NODE._reactInstance = GRANDPARENT_INST;
335
PARENT_HOST_NODE._reactInstance = PARENT_INST;
@@ -339,6 +356,14 @@ function getNodeFromInstance(inst) {
356
return inst._hostNode;
357
}
358
359
+function putListener(node, registrationName, handler) {
360
+ node._currentElement.props[registrationName] = handler;
361
+}
362
+
363
+function deleteAllListeners(node) {
364
+ node._currentElement.props = {};
365
+}
366
+
367
describe('ResponderEventPlugin', () => {
368
369
beforeEach(() => {
@@ -348,6 +373,11 @@ describe('ResponderEventPlugin', () => {
373
EventPluginUtils = require('EventPluginUtils');
374
ResponderEventPlugin = require('ResponderEventPlugin');
375
376
+ deleteAllListeners(GRANDPARENT_INST);
377
+ deleteAllListeners(PARENT_INST);
378
+ deleteAllListeners(CHILD_INST);
379
+ deleteAllListeners(CHILD_INST2);
380
+
381
EventPluginUtils.injection.injectComponentTree({
382
getInstanceFromNode,
383
getNodeFromInstance,
src/renderers/shared/stack/reconciler/__tests__/ReactErrorBoundaries-test.js
-20
@@ -879,26 +879,6 @@ describe('ReactErrorBoundaries', () => {
879
]);
880
});
881
882
- it('does not register event handlers for unmounted children', () => {
883
- var EventPluginHub = require('EventPluginHub');
884
- var container = document.createElement('div');
885
- EventPluginHub.putListener = jest.fn();
886
- ReactDOM.render(
887
- <ErrorBoundary>
888
- <button onClick={() => {}}>Click me</button>
889
- <BrokenRender />
890
- </ErrorBoundary>,
891
- container
892
- );
893
- expect(EventPluginHub.putListener).not.toBeCalled();
894
-
895
- log.length = 0;
896
- ReactDOM.unmountComponentAtNode(container);
897
- expect(log).toEqual([
898
- 'ErrorBoundary componentWillUnmount',
899
- ]);
900
- });
901
-
882
it('does not call componentWillUnmount when aborting initial mount', () => {
883
var container = document.createElement('div');
884
ReactDOM.render(