1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | 'use strict';
|
13 |
|
14 | var _prodInvariant = require('./reactProdInvariant');
|
15 |
|
16 | var ReactCurrentOwner = require('./ReactCurrentOwner');
|
17 |
|
18 | var invariant = require('fbjs/lib/invariant');
|
19 | var warning = require('fbjs/lib/warning');
|
20 |
|
21 | function isNative(fn) {
|
22 |
|
23 | var funcToString = Function.prototype.toString;
|
24 | var hasOwnProperty = Object.prototype.hasOwnProperty;
|
25 | var reIsNative = RegExp('^' + funcToString
|
26 |
|
27 | .call(hasOwnProperty)
|
28 |
|
29 | .replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
|
30 |
|
31 | .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');
|
32 | try {
|
33 | var source = funcToString.call(fn);
|
34 | return reIsNative.test(source);
|
35 | } catch (err) {
|
36 | return false;
|
37 | }
|
38 | }
|
39 |
|
40 | var canUseCollections =
|
41 |
|
42 | typeof Array.from === 'function' &&
|
43 |
|
44 | typeof Map === 'function' && isNative(Map) &&
|
45 |
|
46 | Map.prototype != null && typeof Map.prototype.keys === 'function' && isNative(Map.prototype.keys) &&
|
47 |
|
48 | typeof Set === 'function' && isNative(Set) &&
|
49 |
|
50 | Set.prototype != null && typeof Set.prototype.keys === 'function' && isNative(Set.prototype.keys);
|
51 |
|
52 | var setItem;
|
53 | var getItem;
|
54 | var removeItem;
|
55 | var getItemIDs;
|
56 | var addRoot;
|
57 | var removeRoot;
|
58 | var getRootIDs;
|
59 |
|
60 | if (canUseCollections) {
|
61 | var itemMap = new Map();
|
62 | var rootIDSet = new Set();
|
63 |
|
64 | setItem = function (id, item) {
|
65 | itemMap.set(id, item);
|
66 | };
|
67 | getItem = function (id) {
|
68 | return itemMap.get(id);
|
69 | };
|
70 | removeItem = function (id) {
|
71 | itemMap['delete'](id);
|
72 | };
|
73 | getItemIDs = function () {
|
74 | return Array.from(itemMap.keys());
|
75 | };
|
76 |
|
77 | addRoot = function (id) {
|
78 | rootIDSet.add(id);
|
79 | };
|
80 | removeRoot = function (id) {
|
81 | rootIDSet['delete'](id);
|
82 | };
|
83 | getRootIDs = function () {
|
84 | return Array.from(rootIDSet.keys());
|
85 | };
|
86 | } else {
|
87 | var itemByKey = {};
|
88 | var rootByKey = {};
|
89 |
|
90 |
|
91 |
|
92 | var getKeyFromID = function (id) {
|
93 | return '.' + id;
|
94 | };
|
95 | var getIDFromKey = function (key) {
|
96 | return parseInt(key.substr(1), 10);
|
97 | };
|
98 |
|
99 | setItem = function (id, item) {
|
100 | var key = getKeyFromID(id);
|
101 | itemByKey[key] = item;
|
102 | };
|
103 | getItem = function (id) {
|
104 | var key = getKeyFromID(id);
|
105 | return itemByKey[key];
|
106 | };
|
107 | removeItem = function (id) {
|
108 | var key = getKeyFromID(id);
|
109 | delete itemByKey[key];
|
110 | };
|
111 | getItemIDs = function () {
|
112 | return Object.keys(itemByKey).map(getIDFromKey);
|
113 | };
|
114 |
|
115 | addRoot = function (id) {
|
116 | var key = getKeyFromID(id);
|
117 | rootByKey[key] = true;
|
118 | };
|
119 | removeRoot = function (id) {
|
120 | var key = getKeyFromID(id);
|
121 | delete rootByKey[key];
|
122 | };
|
123 | getRootIDs = function () {
|
124 | return Object.keys(rootByKey).map(getIDFromKey);
|
125 | };
|
126 | }
|
127 |
|
128 | var unmountedIDs = [];
|
129 |
|
130 | function purgeDeep(id) {
|
131 | var item = getItem(id);
|
132 | if (item) {
|
133 | var childIDs = item.childIDs;
|
134 |
|
135 | removeItem(id);
|
136 | childIDs.forEach(purgeDeep);
|
137 | }
|
138 | }
|
139 |
|
140 | function describeComponentFrame(name, source, ownerName) {
|
141 | return '\n in ' + (name || 'Unknown') + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');
|
142 | }
|
143 |
|
144 | function getDisplayName(element) {
|
145 | if (element == null) {
|
146 | return '#empty';
|
147 | } else if (typeof element === 'string' || typeof element === 'number') {
|
148 | return '#text';
|
149 | } else if (typeof element.type === 'string') {
|
150 | return element.type;
|
151 | } else {
|
152 | return element.type.displayName || element.type.name || 'Unknown';
|
153 | }
|
154 | }
|
155 |
|
156 | function describeID(id) {
|
157 | var name = ReactComponentTreeHook.getDisplayName(id);
|
158 | var element = ReactComponentTreeHook.getElement(id);
|
159 | var ownerID = ReactComponentTreeHook.getOwnerID(id);
|
160 | var ownerName;
|
161 | if (ownerID) {
|
162 | ownerName = ReactComponentTreeHook.getDisplayName(ownerID);
|
163 | }
|
164 | process.env.NODE_ENV !== 'production' ? warning(element, 'ReactComponentTreeHook: Missing React element for debugID %s when ' + 'building stack', id) : void 0;
|
165 | return describeComponentFrame(name, element && element._source, ownerName);
|
166 | }
|
167 |
|
168 | var ReactComponentTreeHook = {
|
169 | onSetChildren: function (id, nextChildIDs) {
|
170 | var item = getItem(id);
|
171 | !item ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Item must have been set') : _prodInvariant('144') : void 0;
|
172 | item.childIDs = nextChildIDs;
|
173 |
|
174 | for (var i = 0; i < nextChildIDs.length; i++) {
|
175 | var nextChildID = nextChildIDs[i];
|
176 | var nextChild = getItem(nextChildID);
|
177 | !nextChild ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected hook events to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('140') : void 0;
|
178 | !(nextChild.childIDs != null || typeof nextChild.element !== 'object' || nextChild.element == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onSetChildren() to fire for a container child before its parent includes it in onSetChildren().') : _prodInvariant('141') : void 0;
|
179 | !nextChild.isMounted ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('71') : void 0;
|
180 | if (nextChild.parentID == null) {
|
181 | nextChild.parentID = id;
|
182 |
|
183 |
|
184 |
|
185 | }
|
186 | !(nextChild.parentID === id) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onBeforeMountComponent() parent and onSetChildren() to be consistent (%s has parents %s and %s).', nextChildID, nextChild.parentID, id) : _prodInvariant('142', nextChildID, nextChild.parentID, id) : void 0;
|
187 | }
|
188 | },
|
189 | onBeforeMountComponent: function (id, element, parentID) {
|
190 | var item = {
|
191 | element: element,
|
192 | parentID: parentID,
|
193 | text: null,
|
194 | childIDs: [],
|
195 | isMounted: false,
|
196 | updateCount: 0
|
197 | };
|
198 | setItem(id, item);
|
199 | },
|
200 | onBeforeUpdateComponent: function (id, element) {
|
201 | var item = getItem(id);
|
202 | if (!item || !item.isMounted) {
|
203 |
|
204 |
|
205 | return;
|
206 | }
|
207 | item.element = element;
|
208 | },
|
209 | onMountComponent: function (id) {
|
210 | var item = getItem(id);
|
211 | !item ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Item must have been set') : _prodInvariant('144') : void 0;
|
212 | item.isMounted = true;
|
213 | var isRoot = item.parentID === 0;
|
214 | if (isRoot) {
|
215 | addRoot(id);
|
216 | }
|
217 | },
|
218 | onUpdateComponent: function (id) {
|
219 | var item = getItem(id);
|
220 | if (!item || !item.isMounted) {
|
221 |
|
222 |
|
223 | return;
|
224 | }
|
225 | item.updateCount++;
|
226 | },
|
227 | onUnmountComponent: function (id) {
|
228 | var item = getItem(id);
|
229 | if (item) {
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 | item.isMounted = false;
|
236 | var isRoot = item.parentID === 0;
|
237 | if (isRoot) {
|
238 | removeRoot(id);
|
239 | }
|
240 | }
|
241 | unmountedIDs.push(id);
|
242 | },
|
243 | purgeUnmountedComponents: function () {
|
244 | if (ReactComponentTreeHook._preventPurging) {
|
245 |
|
246 | return;
|
247 | }
|
248 |
|
249 | for (var i = 0; i < unmountedIDs.length; i++) {
|
250 | var id = unmountedIDs[i];
|
251 | purgeDeep(id);
|
252 | }
|
253 | unmountedIDs.length = 0;
|
254 | },
|
255 | isMounted: function (id) {
|
256 | var item = getItem(id);
|
257 | return item ? item.isMounted : false;
|
258 | },
|
259 | getCurrentStackAddendum: function (topElement) {
|
260 | var info = '';
|
261 | if (topElement) {
|
262 | var name = getDisplayName(topElement);
|
263 | var owner = topElement._owner;
|
264 | info += describeComponentFrame(name, topElement._source, owner && owner.getName());
|
265 | }
|
266 |
|
267 | var currentOwner = ReactCurrentOwner.current;
|
268 | var id = currentOwner && currentOwner._debugID;
|
269 |
|
270 | info += ReactComponentTreeHook.getStackAddendumByID(id);
|
271 | return info;
|
272 | },
|
273 | getStackAddendumByID: function (id) {
|
274 | var info = '';
|
275 | while (id) {
|
276 | info += describeID(id);
|
277 | id = ReactComponentTreeHook.getParentID(id);
|
278 | }
|
279 | return info;
|
280 | },
|
281 | getChildIDs: function (id) {
|
282 | var item = getItem(id);
|
283 | return item ? item.childIDs : [];
|
284 | },
|
285 | getDisplayName: function (id) {
|
286 | var element = ReactComponentTreeHook.getElement(id);
|
287 | if (!element) {
|
288 | return null;
|
289 | }
|
290 | return getDisplayName(element);
|
291 | },
|
292 | getElement: function (id) {
|
293 | var item = getItem(id);
|
294 | return item ? item.element : null;
|
295 | },
|
296 | getOwnerID: function (id) {
|
297 | var element = ReactComponentTreeHook.getElement(id);
|
298 | if (!element || !element._owner) {
|
299 | return null;
|
300 | }
|
301 | return element._owner._debugID;
|
302 | },
|
303 | getParentID: function (id) {
|
304 | var item = getItem(id);
|
305 | return item ? item.parentID : null;
|
306 | },
|
307 | getSource: function (id) {
|
308 | var item = getItem(id);
|
309 | var element = item ? item.element : null;
|
310 | var source = element != null ? element._source : null;
|
311 | return source;
|
312 | },
|
313 | getText: function (id) {
|
314 | var element = ReactComponentTreeHook.getElement(id);
|
315 | if (typeof element === 'string') {
|
316 | return element;
|
317 | } else if (typeof element === 'number') {
|
318 | return '' + element;
|
319 | } else {
|
320 | return null;
|
321 | }
|
322 | },
|
323 | getUpdateCount: function (id) {
|
324 | var item = getItem(id);
|
325 | return item ? item.updateCount : 0;
|
326 | },
|
327 |
|
328 |
|
329 | getRootIDs: getRootIDs,
|
330 | getRegisteredIDs: getItemIDs
|
331 | };
|
332 |
|
333 | module.exports = ReactComponentTreeHook; |
\ | No newline at end of file |