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