Merge React[DOM/Native]TreeTraversal
These two implementations are identical. Except for some invariants for some reason. Since this relies on an implementation detail of the internal component tree rather than an implementation detail of the renderer, we might as well merge them and remove the injection.
Sebastian Markbage committed
Oct 25, 2016 at 14:37 UTC
8df7afc689de7929ed4a5ec4f581b94abb963914
7 files changed
+38
-186
src/renderers/dom/shared/ReactDOMInjection.js
-2
@@ -22,7 +22,6 @@ var EventPluginUtils = require('EventPluginUtils');
22
var HTMLDOMPropertyConfig = require('HTMLDOMPropertyConfig');
23
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
24
var ReactDOMComponentTree = require('ReactDOMComponentTree');
25
-var ReactDOMTreeTraversal = require('ReactDOMTreeTraversal');
25
var ReactEventListener = require('ReactEventListener');
26
var SVGDOMPropertyConfig = require('SVGDOMPropertyConfig');
27
var SelectEventPlugin = require('SelectEventPlugin');
@@ -48,7 +47,6 @@ function inject() {
47
*/
48
EventPluginHub.injection.injectEventPluginOrder(DOMEventPluginOrder);
49
EventPluginUtils.injection.injectComponentTree(ReactDOMComponentTree);
51
- EventPluginUtils.injection.injectTreeTraversal(ReactDOMTreeTraversal);
50
51
/**
52
* Some important event plugins included by default (without having to require
src/renderers/dom/shared/ReactDOMTreeTraversal.js
deleted
-134
@@ -1,134 +0,0 @@
1
-/**
2
- * Copyright 2015-present, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- *
9
- * @providesModule ReactDOMTreeTraversal
10
- */
11
-
12
-'use strict';
13
-
14
-var invariant = require('invariant');
15
-
16
-/**
17
- * Return the lowest common ancestor of A and B, or null if they are in
18
- * different trees.
19
- */
20
-function getLowestCommonAncestor(instA, instB) {
21
- invariant('_hostNode' in instA, 'getNodeFromInstance: Invalid argument.');
22
- invariant('_hostNode' in instB, 'getNodeFromInstance: Invalid argument.');
23
-
24
- var depthA = 0;
25
- for (var tempA = instA; tempA; tempA = tempA._hostParent) {
26
- depthA++;
27
- }
28
- var depthB = 0;
29
- for (var tempB = instB; tempB; tempB = tempB._hostParent) {
30
- depthB++;
31
- }
32
-
33
- // If A is deeper, crawl up.
34
- while (depthA - depthB > 0) {
35
- instA = instA._hostParent;
36
- depthA--;
37
- }
38
-
39
- // If B is deeper, crawl up.
40
- while (depthB - depthA > 0) {
41
- instB = instB._hostParent;
42
- depthB--;
43
- }
44
-
45
- // Walk in lockstep until we find a match.
46
- var depth = depthA;
47
- while (depth--) {
48
- if (instA === instB) {
49
- return instA;
50
- }
51
- instA = instA._hostParent;
52
- instB = instB._hostParent;
53
- }
54
- return null;
55
-}
56
-
57
-/**
58
- * Return if A is an ancestor of B.
59
- */
60
-function isAncestor(instA, instB) {
61
- invariant('_hostNode' in instA, 'isAncestor: Invalid argument.');
62
- invariant('_hostNode' in instB, 'isAncestor: Invalid argument.');
63
-
64
- while (instB) {
65
- if (instB === instA) {
66
- return true;
67
- }
68
- instB = instB._hostParent;
69
- }
70
- return false;
71
-}
72
-
73
-/**
74
- * Return the parent instance of the passed-in instance.
75
- */
76
-function getParentInstance(inst) {
77
- invariant('_hostNode' in inst, 'getParentInstance: Invalid argument.');
78
-
79
- return inst._hostParent;
80
-}
81
-
82
-/**
83
- * Simulates the traversal of a two-phase, capture/bubble event dispatch.
84
- */
85
-function traverseTwoPhase(inst, fn, arg) {
86
- var path = [];
87
- while (inst) {
88
- path.push(inst);
89
- inst = inst._hostParent;
90
- }
91
- var i;
92
- for (i = path.length; i-- > 0;) {
93
- fn(path[i], 'captured', arg);
94
- }
95
- for (i = 0; i < path.length; i++) {
96
- fn(path[i], 'bubbled', arg);
97
- }
98
-}
99
-
100
-/**
101
- * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
102
- * should would receive a `mouseEnter` or `mouseLeave` event.
103
- *
104
- * Does not invoke the callback on the nearest common ancestor because nothing
105
- * "entered" or "left" that element.
106
- */
107
-function traverseEnterLeave(from, to, fn, argFrom, argTo) {
108
- var common = from && to ? getLowestCommonAncestor(from, to) : null;
109
- var pathFrom = [];
110
- while (from && from !== common) {
111
- pathFrom.push(from);
112
- from = from._hostParent;
113
- }
114
- var pathTo = [];
115
- while (to && to !== common) {
116
- pathTo.push(to);
117
- to = to._hostParent;
118
- }
119
- var i;
120
- for (i = 0; i < pathFrom.length; i++) {
121
- fn(pathFrom[i], 'bubbled', argFrom);
122
- }
123
- for (i = pathTo.length; i-- > 0;) {
124
- fn(pathTo[i], 'captured', argTo);
125
- }
126
-}
127
-
128
-module.exports = {
129
- isAncestor: isAncestor,
130
- getLowestCommonAncestor: getLowestCommonAncestor,
131
- getParentInstance: getParentInstance,
132
- traverseTwoPhase: traverseTwoPhase,
133
- traverseEnterLeave: traverseEnterLeave,
134
-};
src/renderers/native/ReactNativeInjection.js
-2
@@ -27,7 +27,6 @@ var ReactNativeComponentTree = require('ReactNativeComponentTree');
27
var ReactNativeEventEmitter = require('ReactNativeEventEmitter');
28
var ReactNativeEventPluginOrder = require('ReactNativeEventPluginOrder');
29
var ReactNativeGlobalResponderHandler = require('ReactNativeGlobalResponderHandler');
30
-var ReactNativeTreeTraversal = require('ReactNativeTreeTraversal');
30
var ResponderEventPlugin = require('ResponderEventPlugin');
31
32
function inject() {
@@ -41,7 +40,6 @@ function inject() {
40
*/
41
EventPluginHub.injection.injectEventPluginOrder(ReactNativeEventPluginOrder);
42
EventPluginUtils.injection.injectComponentTree(ReactNativeComponentTree);
44
- EventPluginUtils.injection.injectTreeTraversal(ReactNativeTreeTraversal);
43
44
ResponderEventPlugin.injection.injectGlobalResponderHandler(
45
ReactNativeGlobalResponderHandler
src/renderers/shared/shared/ReactTreeTraversal.js
renamed
+1
-3
@@ -6,13 +6,11 @@
6
* LICENSE file in the root directory of this source tree. An additional grant
7
* of patent rights can be found in the PATENTS file in the same directory.
8
*
9
- * @providesModule ReactNativeTreeTraversal
9
+ * @providesModule ReactTreeTraversal
10
*/
11
12
'use strict';
13
14
-// Same as ReactDOMTreeTraversal without the invariants.
15
-
14
/**
15
* Return the lowest common ancestor of A and B, or null if they are in
16
* different trees.
src/renderers/shared/shared/__tests__/ReactTreeTraversal-test.js
renamed
+15
-15
@@ -50,8 +50,8 @@ function renderParentIntoDocument() {
50
return ReactTestUtils.renderIntoDocument(<ParentComponent />);
51
}
52
53
-describe('ReactDOMTreeTraversal', () => {
54
- var ReactDOMTreeTraversal;
53
+describe('ReactTreeTraversal', () => {
54
+ var ReactTreeTraversal;
55
56
var aggregatedArgs;
57
function argAggregator(inst, phase, arg) {
@@ -67,14 +67,14 @@ describe('ReactDOMTreeTraversal', () => {
67
}
68
69
beforeEach(() => {
70
- ReactDOMTreeTraversal = require('ReactDOMTreeTraversal');
70
+ ReactTreeTraversal = require('ReactTreeTraversal');
71
aggregatedArgs = [];
72
});
73
74
describe('traverseTwoPhase', () => {
75
it('should not traverse when traversing outside DOM', () => {
76
var expectedAggregation = [];
77
- ReactDOMTreeTraversal.traverseTwoPhase(null, argAggregator, ARG);
77
+ ReactTreeTraversal.traverseTwoPhase(null, argAggregator, ARG);
78
expect(aggregatedArgs).toEqual(expectedAggregation);
79
});
80
@@ -92,7 +92,7 @@ describe('ReactDOMTreeTraversal', () => {
92
{node: parent.refs.P_P1, phase: 'bubbled', arg: ARG},
93
{node: parent.refs.P, phase: 'bubbled', arg: ARG},
94
];
95
- ReactDOMTreeTraversal.traverseTwoPhase(target, argAggregator, ARG);
95
+ ReactTreeTraversal.traverseTwoPhase(target, argAggregator, ARG);
96
expect(aggregatedArgs).toEqual(expectedAggregation);
97
});
98
@@ -103,7 +103,7 @@ describe('ReactDOMTreeTraversal', () => {
103
{node: parent.refs.P, phase: 'captured', arg: ARG},
104
{node: parent.refs.P, phase: 'bubbled', arg: ARG},
105
];
106
- ReactDOMTreeTraversal.traverseTwoPhase(target, argAggregator, ARG);
106
+ ReactTreeTraversal.traverseTwoPhase(target, argAggregator, ARG);
107
expect(aggregatedArgs).toEqual(expectedAggregation);
108
});
109
});
@@ -112,7 +112,7 @@ describe('ReactDOMTreeTraversal', () => {
112
it('should not traverse when enter/leaving outside DOM', () => {
113
var target = null;
114
var expectedAggregation = [];
115
- ReactDOMTreeTraversal.traverseEnterLeave(
115
+ ReactTreeTraversal.traverseEnterLeave(
116
target, target, argAggregator, ARG, ARG2
117
);
118
expect(aggregatedArgs).toEqual(expectedAggregation);
@@ -123,7 +123,7 @@ describe('ReactDOMTreeTraversal', () => {
123
var leave = getInst(parent.refs.P_P1_C1.refs.DIV_1);
124
var enter = getInst(parent.refs.P_P1_C1.refs.DIV_1);
125
var expectedAggregation = [];
126
- ReactDOMTreeTraversal.traverseEnterLeave(
126
+ ReactTreeTraversal.traverseEnterLeave(
127
leave, enter, argAggregator, ARG, ARG2
128
);
129
expect(aggregatedArgs).toEqual(expectedAggregation);
@@ -138,7 +138,7 @@ describe('ReactDOMTreeTraversal', () => {
138
// enter/leave shouldn't fire anything on the parent
139
{node: parent.refs.P_P1_C1.refs.DIV_2, phase: 'captured', arg: ARG2},
140
];
141
- ReactDOMTreeTraversal.traverseEnterLeave(
141
+ ReactTreeTraversal.traverseEnterLeave(
142
leave, enter, argAggregator, ARG, ARG2
143
);
144
expect(aggregatedArgs).toEqual(expectedAggregation);
@@ -151,7 +151,7 @@ describe('ReactDOMTreeTraversal', () => {
151
var expectedAggregation = [
152
{node: parent.refs.P_P1_C1.refs.DIV_1, phase: 'bubbled', arg: ARG},
153
];
154
- ReactDOMTreeTraversal.traverseEnterLeave(
154
+ ReactTreeTraversal.traverseEnterLeave(
155
leave, enter, argAggregator, ARG, ARG2
156
);
157
expect(aggregatedArgs).toEqual(expectedAggregation);
@@ -166,7 +166,7 @@ describe('ReactDOMTreeTraversal', () => {
166
{node: parent.refs.P_P1, phase: 'captured', arg: ARG2},
167
{node: parent.refs.P_P1_C1.refs.DIV, phase: 'captured', arg: ARG2},
168
];
169
- ReactDOMTreeTraversal.traverseEnterLeave(
169
+ ReactTreeTraversal.traverseEnterLeave(
170
leave, enter, argAggregator, ARG, ARG2
171
);
172
expect(aggregatedArgs).toEqual(expectedAggregation);
@@ -179,7 +179,7 @@ describe('ReactDOMTreeTraversal', () => {
179
var expectedAggregation = [
180
{node: parent.refs.P, phase: 'captured', arg: ARG2},
181
];
182
- ReactDOMTreeTraversal.traverseEnterLeave(
182
+ ReactTreeTraversal.traverseEnterLeave(
183
leave, enter, argAggregator, ARG, ARG2
184
);
185
expect(aggregatedArgs).toEqual(expectedAggregation);
@@ -194,7 +194,7 @@ describe('ReactDOMTreeTraversal', () => {
194
{node: parent.refs.P_P1, phase: 'bubbled', arg: ARG},
195
{node: parent.refs.P, phase: 'bubbled', arg: ARG},
196
];
197
- ReactDOMTreeTraversal.traverseEnterLeave(
197
+ ReactTreeTraversal.traverseEnterLeave(
198
leave, enter, argAggregator, ARG, ARG2
199
);
200
expect(aggregatedArgs).toEqual(expectedAggregation);
@@ -209,7 +209,7 @@ describe('ReactDOMTreeTraversal', () => {
209
{node: parent.refs.P_P1, phase: 'bubbled', arg: ARG},
210
{node: parent.refs.P, phase: 'bubbled', arg: ARG},
211
];
212
- ReactDOMTreeTraversal.traverseEnterLeave(
212
+ ReactTreeTraversal.traverseEnterLeave(
213
leave, enter, argAggregator, ARG, ARG2
214
);
215
expect(aggregatedArgs).toEqual(expectedAggregation);
@@ -261,7 +261,7 @@ describe('ReactDOMTreeTraversal', () => {
261
var i;
262
for (i = 0; i < ancestors.length; i++) {
263
var plan = ancestors[i];
264
- var firstCommon = ReactDOMTreeTraversal.getLowestCommonAncestor(
264
+ var firstCommon = ReactTreeTraversal.getLowestCommonAncestor(
265
getInst(plan.one),
266
getInst(plan.two)
267
);
src/renderers/shared/shared/event/EventPluginUtils.js
+6
-16
@@ -11,6 +11,7 @@
11
12
'use strict';
13
14
+var ReactTreeTraversal = require('ReactTreeTraversal');
15
var ReactErrorUtils = require('ReactErrorUtils');
16
17
var invariant = require('invariant');
@@ -25,7 +26,6 @@ var warning = require('warning');
26
* and actual node references.
27
*/
28
var ComponentTree;
28
-var TreeTraversal;
29
var injection = {
30
injectComponentTree: function(Injected) {
31
ComponentTree = Injected;
@@ -39,16 +39,6 @@ var injection = {
39
);
40
}
41
},
42
- injectTreeTraversal: function(Injected) {
43
- TreeTraversal = Injected;
44
- if (__DEV__) {
45
- warning(
46
- Injected && Injected.isAncestor && Injected.getLowestCommonAncestor,
47
- 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' +
48
- 'module is missing isAncestor or getLowestCommonAncestor.'
49
- );
50
- }
51
- },
42
};
43
44
function isEndish(topLevelType) {
@@ -237,19 +227,19 @@ var EventPluginUtils = {
227
return ComponentTree.getNodeFromInstance(node);
228
},
229
isAncestor: function(a, b) {
240
- return TreeTraversal.isAncestor(a, b);
230
+ return ReactTreeTraversal.isAncestor(a, b);
231
},
232
getLowestCommonAncestor: function(a, b) {
243
- return TreeTraversal.getLowestCommonAncestor(a, b);
233
+ return ReactTreeTraversal.getLowestCommonAncestor(a, b);
234
},
235
getParentInstance: function(inst) {
246
- return TreeTraversal.getParentInstance(inst);
236
+ return ReactTreeTraversal.getParentInstance(inst);
237
},
238
traverseTwoPhase: function(target, fn, arg) {
249
- return TreeTraversal.traverseTwoPhase(target, fn, arg);
239
+ return ReactTreeTraversal.traverseTwoPhase(target, fn, arg);
240
},
241
traverseEnterLeave: function(from, to, fn, argFrom, argTo) {
252
- return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);
242
+ return ReactTreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);
243
},
244
245
injection: injection,
src/renderers/shared/shared/event/eventPlugins/__tests__/ResponderEventPlugin-test.js
+16
-14
@@ -408,20 +408,9 @@ describe('ResponderEventPlugin', () => {
408
beforeEach(() => {
409
jest.resetModuleRegistry();
410
411
- EventPluginHub = require('EventPluginHub');
412
- EventPluginUtils = require('EventPluginUtils');
413
- ResponderEventPlugin = require('ResponderEventPlugin');
414
-
415
- EventPluginUtils.injection.injectComponentTree({
416
- getInstanceFromNode: function(id) {
417
- return idToInstance[id];
418
- },
419
- getNodeFromInstance: function(inst) {
420
- return inst._rootNodeID;
421
- },
422
- });
423
-
424
- EventPluginUtils.injection.injectTreeTraversal({
411
+ // Inline mock
412
+ const ReactTreeTraversal = require('ReactTreeTraversal');
413
+ Object.assign(ReactTreeTraversal, {
414
isAncestor: function(a, b) {
415
return isAncestorIDOf(a._rootNodeID, b._rootNodeID);
416
},
@@ -443,6 +432,19 @@ describe('ResponderEventPlugin', () => {
432
);
433
},
434
});
435
+
436
+ EventPluginHub = require('EventPluginHub');
437
+ EventPluginUtils = require('EventPluginUtils');
438
+ ResponderEventPlugin = require('ResponderEventPlugin');
439
+
440
+ EventPluginUtils.injection.injectComponentTree({
441
+ getInstanceFromNode: function(id) {
442
+ return idToInstance[id];
443
+ },
444
+ getNodeFromInstance: function(inst) {
445
+ return inst._rootNodeID;
446
+ },
447
+ });
448
});
449
450
it('should do nothing when no one wants to respond', () => {