1
+ 'use strict' ;
2
+
3
+ Object . defineProperty ( exports , "__esModule" , {
4
+ value : true
5
+ } ) ;
6
+ exports . isPromise = undefined ;
7
+ exports . default = reactTreeWalker ;
8
+
9
+ var _react = require ( 'react' ) ;
10
+
11
+ // Lifted from https://github.com/sindresorhus/p-reduce
12
+ // Thanks @sindresorhus !
13
+ var pReduce = function pReduce ( iterable , reducer , initVal ) {
14
+ return new Promise ( function ( resolve , reject ) {
15
+ var iterator = iterable [ Symbol . iterator ] ( ) ;
16
+ var i = 0 ;
17
+
18
+ var next = function next ( total ) {
19
+ var el = iterator . next ( ) ;
20
+
21
+ if ( el . done ) {
22
+ resolve ( total ) ;
23
+ return ;
24
+ }
25
+
26
+ Promise . all ( [ total , el . value ] ) . then ( function ( value ) {
27
+ // eslint-disable-next-line no-plusplus
28
+ next ( reducer ( value [ 0 ] , value [ 1 ] , i ++ ) ) ;
29
+ } ) . catch ( reject ) ;
30
+ } ;
31
+
32
+ next ( initVal ) ;
33
+ } ) ;
34
+ } ;
35
+
36
+ // Lifted from https://github.com/sindresorhus/p-map-series
37
+ // Thanks @sindresorhus !
38
+ /* eslint-disable no-console */
39
+
40
+ // Inspired by the awesome work done by the Apollo team.
41
+ // See https://github.com/apollostack/react-apollo/blob/master/src/server.ts
42
+ // This version has been adapted to be promise based.
43
+
44
+ // eslint-disable-next-line import/no-extraneous-dependencies
45
+ var pMapSeries = function pMapSeries ( iterable , iterator ) {
46
+ var ret = [ ] ;
47
+
48
+ return pReduce ( iterable , function ( a , b , i ) {
49
+ return Promise . resolve ( iterator ( b , i ) ) . then ( function ( val ) {
50
+ ret . push ( val ) ;
51
+ } ) ;
52
+ } ) . then ( function ( ) {
53
+ return ret ;
54
+ } ) ;
55
+ } ;
56
+
57
+ var isPromise = exports . isPromise = function isPromise ( x ) {
58
+ return x != null && typeof x . then === 'function' ;
59
+ } ;
60
+
61
+ // Recurse an React Element tree, running visitor on each element.
62
+ // If visitor returns `false`, don't call the element's render function
63
+ // or recurse into its child elements
64
+ function reactTreeWalker ( element , visitor , context ) {
65
+ return new Promise ( function ( resolve ) {
66
+ var doVisit = function doVisit ( getChildren , visitorResult , childContext , isChildren ) {
67
+ var doTraverse = function doTraverse ( shouldContinue ) {
68
+ if ( ! shouldContinue ) {
69
+ // We recieved a false, which indicates a desire to stop traversal.
70
+ resolve ( ) ;
71
+ }
72
+
73
+ var child = getChildren ( ) ;
74
+ var theChildContext = typeof childContext === 'function' ? childContext ( ) : childContext ;
75
+
76
+ if ( child == null ) {
77
+ // If no children then we can't traverse. We've reached the leaf.
78
+ resolve ( ) ;
79
+ } else if ( isChildren ) {
80
+ // If its a react Children collection we need to breadth-first
81
+ // traverse each of them.
82
+ var mapper = function mapper ( aChild ) {
83
+ return aChild ? reactTreeWalker ( aChild , visitor , theChildContext ) : undefined ;
84
+ } ;
85
+ // pMapSeries allows us to do depth-first traversal. Thanks @sindresorhus!
86
+ pMapSeries ( _react . Children . map ( child , function ( cur ) {
87
+ return cur ;
88
+ } ) , mapper ) . then ( resolve ) ;
89
+ } else {
90
+ // Otherwise we pass the individual child to the next recursion.
91
+ reactTreeWalker ( child , visitor , theChildContext ) . then ( resolve ) ;
92
+ }
93
+ } ;
94
+
95
+ if ( visitorResult === false ) {
96
+ // Visitor returned false, indicating a desire to not traverse.
97
+ resolve ( ) ;
98
+ } else if ( isPromise ( visitorResult ) ) {
99
+ // We need to execute the result and pass it's result through to our
100
+ // continuer.
101
+ visitorResult . then ( doTraverse ) . catch ( function ( e ) {
102
+ console . log ( 'Error occurred in Promise based visitor result provided to react-tree-walker.' ) ;
103
+ if ( e ) {
104
+ console . log ( e ) ;
105
+ if ( e . stack ) {
106
+ console . log ( e . stack ) ;
107
+ }
108
+ }
109
+ } ) ;
110
+ } else {
111
+ doTraverse ( true ) ;
112
+ }
113
+ } ;
114
+
115
+ // Is this element a Component?
116
+ if ( typeof element . type === 'function' ) {
117
+ var Component = element . type ;
118
+ var props = Object . assign ( { } , Component . defaultProps , element . props ) ;
119
+
120
+ // Is this a class component? (http://bit.ly/2j9Ifk3)
121
+ var isReactClassComponent = Component . prototype && ( Component . prototype . isReactComponent || Component . prototype . isPureReactComponent ) ;
122
+
123
+ if ( isReactClassComponent ) {
124
+ // React class component
125
+
126
+ var instance = new Component ( props , context ) ;
127
+
128
+ // In case the user doesn't pass these to super in the constructor
129
+ instance . props = instance . props || props ;
130
+ instance . context = instance . context || context ;
131
+
132
+ // Make the setState synchronous.
133
+ instance . setState = function ( newState ) {
134
+ instance . state = Object . assign ( { } , instance . state , newState ) ;
135
+ } ;
136
+
137
+ doVisit ( function ( ) {
138
+ // Call componentWillMount if it exists.
139
+ if ( instance . componentWillMount ) {
140
+ instance . componentWillMount ( ) ;
141
+ }
142
+
143
+ return instance . render ( ) ;
144
+ } , visitor ( element , instance , context ) , function ( ) {
145
+ return (
146
+ // Ensure the child context is initialised if it is available. We will
147
+ // need to pass it down the tree.
148
+ instance . getChildContext ? Object . assign ( { } , context , instance . getChildContext ( ) ) : context
149
+ ) ;
150
+ } ) ;
151
+ } else {
152
+ // Stateless Functional Component
153
+ doVisit ( function ( ) {
154
+ return Component ( props , context ) ;
155
+ } , visitor ( element , null , context ) , context ) ;
156
+ }
157
+ } else {
158
+ // This must be a basic element, such as a string or dom node.
159
+ doVisit ( function ( ) {
160
+ return element . props && element . props . children ? element . props . children : undefined ;
161
+ } , visitor ( element , null , context ) , context , true ) ;
162
+ }
163
+ } ) ;
164
+ }
0 commit comments