@samitouri / QOS-React / commits / 8df7afc689

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', () => {