UNPKG

10.6 kBJavaScriptView Raw
1/** @license React v0.13.1
2 * scheduler-tracing.development.js
3 *
4 * Copyright (c) Facebook, Inc. and its affiliates.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE file in the root directory of this source tree.
8 */
9
10'use strict';
11
12
13
14if (process.env.NODE_ENV !== "production") {
15 (function() {
16'use strict';
17
18Object.defineProperty(exports, '__esModule', { value: true });
19
20// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
21
22
23// In some cases, StrictMode should also double-render lifecycles.
24// This can be confusing for tests though,
25// And it can be bad for performance in production.
26// This feature flag can be used to control the behavior:
27
28
29// To preserve the "Pause on caught exceptions" behavior of the debugger, we
30// replay the begin phase of a failed component inside invokeGuardedCallback.
31
32
33// Warn about deprecated, async-unsafe lifecycles; relates to RFC #6:
34
35
36// Gather advanced timing metrics for Profiler subtrees.
37
38
39// Trace which interactions trigger each commit.
40var enableSchedulerTracing = true;
41
42// Only used in www builds.
43 // TODO: true? Here it might just be false.
44
45// Only used in www builds.
46
47
48// Only used in www builds.
49
50
51// React Fire: prevent the value and checked attributes from syncing
52// with their related DOM properties
53
54
55// These APIs will no longer be "unstable" in the upcoming 16.7 release,
56// Control this behavior with a flag to support 16.6 minor releases in the meanwhile.
57
58var DEFAULT_THREAD_ID = 0;
59
60// Counters used to generate unique IDs.
61var interactionIDCounter = 0;
62var threadIDCounter = 0;
63
64// Set of currently traced interactions.
65// Interactions "stack"–
66// Meaning that newly traced interactions are appended to the previously active set.
67// When an interaction goes out of scope, the previous set (if any) is restored.
68exports.__interactionsRef = null;
69
70// Listener(s) to notify when interactions begin and end.
71exports.__subscriberRef = null;
72
73if (enableSchedulerTracing) {
74 exports.__interactionsRef = {
75 current: new Set()
76 };
77 exports.__subscriberRef = {
78 current: null
79 };
80}
81
82function unstable_clear(callback) {
83 if (!enableSchedulerTracing) {
84 return callback();
85 }
86
87 var prevInteractions = exports.__interactionsRef.current;
88 exports.__interactionsRef.current = new Set();
89
90 try {
91 return callback();
92 } finally {
93 exports.__interactionsRef.current = prevInteractions;
94 }
95}
96
97function unstable_getCurrent() {
98 if (!enableSchedulerTracing) {
99 return null;
100 } else {
101 return exports.__interactionsRef.current;
102 }
103}
104
105function unstable_getThreadID() {
106 return ++threadIDCounter;
107}
108
109function unstable_trace(name, timestamp, callback) {
110 var threadID = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : DEFAULT_THREAD_ID;
111
112 if (!enableSchedulerTracing) {
113 return callback();
114 }
115
116 var interaction = {
117 __count: 1,
118 id: interactionIDCounter++,
119 name: name,
120 timestamp: timestamp
121 };
122
123 var prevInteractions = exports.__interactionsRef.current;
124
125 // Traced interactions should stack/accumulate.
126 // To do that, clone the current interactions.
127 // The previous set will be restored upon completion.
128 var interactions = new Set(prevInteractions);
129 interactions.add(interaction);
130 exports.__interactionsRef.current = interactions;
131
132 var subscriber = exports.__subscriberRef.current;
133 var returnValue = void 0;
134
135 try {
136 if (subscriber !== null) {
137 subscriber.onInteractionTraced(interaction);
138 }
139 } finally {
140 try {
141 if (subscriber !== null) {
142 subscriber.onWorkStarted(interactions, threadID);
143 }
144 } finally {
145 try {
146 returnValue = callback();
147 } finally {
148 exports.__interactionsRef.current = prevInteractions;
149
150 try {
151 if (subscriber !== null) {
152 subscriber.onWorkStopped(interactions, threadID);
153 }
154 } finally {
155 interaction.__count--;
156
157 // If no async work was scheduled for this interaction,
158 // Notify subscribers that it's completed.
159 if (subscriber !== null && interaction.__count === 0) {
160 subscriber.onInteractionScheduledWorkCompleted(interaction);
161 }
162 }
163 }
164 }
165 }
166
167 return returnValue;
168}
169
170function unstable_wrap(callback) {
171 var threadID = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_THREAD_ID;
172
173 if (!enableSchedulerTracing) {
174 return callback;
175 }
176
177 var wrappedInteractions = exports.__interactionsRef.current;
178
179 var subscriber = exports.__subscriberRef.current;
180 if (subscriber !== null) {
181 subscriber.onWorkScheduled(wrappedInteractions, threadID);
182 }
183
184 // Update the pending async work count for the current interactions.
185 // Update after calling subscribers in case of error.
186 wrappedInteractions.forEach(function (interaction) {
187 interaction.__count++;
188 });
189
190 var hasRun = false;
191
192 function wrapped() {
193 var prevInteractions = exports.__interactionsRef.current;
194 exports.__interactionsRef.current = wrappedInteractions;
195
196 subscriber = exports.__subscriberRef.current;
197
198 try {
199 var returnValue = void 0;
200
201 try {
202 if (subscriber !== null) {
203 subscriber.onWorkStarted(wrappedInteractions, threadID);
204 }
205 } finally {
206 try {
207 returnValue = callback.apply(undefined, arguments);
208 } finally {
209 exports.__interactionsRef.current = prevInteractions;
210
211 if (subscriber !== null) {
212 subscriber.onWorkStopped(wrappedInteractions, threadID);
213 }
214 }
215 }
216
217 return returnValue;
218 } finally {
219 if (!hasRun) {
220 // We only expect a wrapped function to be executed once,
221 // But in the event that it's executed more than once–
222 // Only decrement the outstanding interaction counts once.
223 hasRun = true;
224
225 // Update pending async counts for all wrapped interactions.
226 // If this was the last scheduled async work for any of them,
227 // Mark them as completed.
228 wrappedInteractions.forEach(function (interaction) {
229 interaction.__count--;
230
231 if (subscriber !== null && interaction.__count === 0) {
232 subscriber.onInteractionScheduledWorkCompleted(interaction);
233 }
234 });
235 }
236 }
237 }
238
239 wrapped.cancel = function cancel() {
240 subscriber = exports.__subscriberRef.current;
241
242 try {
243 if (subscriber !== null) {
244 subscriber.onWorkCanceled(wrappedInteractions, threadID);
245 }
246 } finally {
247 // Update pending async counts for all wrapped interactions.
248 // If this was the last scheduled async work for any of them,
249 // Mark them as completed.
250 wrappedInteractions.forEach(function (interaction) {
251 interaction.__count--;
252
253 if (subscriber && interaction.__count === 0) {
254 subscriber.onInteractionScheduledWorkCompleted(interaction);
255 }
256 });
257 }
258 };
259
260 return wrapped;
261}
262
263var subscribers = null;
264if (enableSchedulerTracing) {
265 subscribers = new Set();
266}
267
268function unstable_subscribe(subscriber) {
269 if (enableSchedulerTracing) {
270 subscribers.add(subscriber);
271
272 if (subscribers.size === 1) {
273 exports.__subscriberRef.current = {
274 onInteractionScheduledWorkCompleted: onInteractionScheduledWorkCompleted,
275 onInteractionTraced: onInteractionTraced,
276 onWorkCanceled: onWorkCanceled,
277 onWorkScheduled: onWorkScheduled,
278 onWorkStarted: onWorkStarted,
279 onWorkStopped: onWorkStopped
280 };
281 }
282 }
283}
284
285function unstable_unsubscribe(subscriber) {
286 if (enableSchedulerTracing) {
287 subscribers.delete(subscriber);
288
289 if (subscribers.size === 0) {
290 exports.__subscriberRef.current = null;
291 }
292 }
293}
294
295function onInteractionTraced(interaction) {
296 var didCatchError = false;
297 var caughtError = null;
298
299 subscribers.forEach(function (subscriber) {
300 try {
301 subscriber.onInteractionTraced(interaction);
302 } catch (error) {
303 if (!didCatchError) {
304 didCatchError = true;
305 caughtError = error;
306 }
307 }
308 });
309
310 if (didCatchError) {
311 throw caughtError;
312 }
313}
314
315function onInteractionScheduledWorkCompleted(interaction) {
316 var didCatchError = false;
317 var caughtError = null;
318
319 subscribers.forEach(function (subscriber) {
320 try {
321 subscriber.onInteractionScheduledWorkCompleted(interaction);
322 } catch (error) {
323 if (!didCatchError) {
324 didCatchError = true;
325 caughtError = error;
326 }
327 }
328 });
329
330 if (didCatchError) {
331 throw caughtError;
332 }
333}
334
335function onWorkScheduled(interactions, threadID) {
336 var didCatchError = false;
337 var caughtError = null;
338
339 subscribers.forEach(function (subscriber) {
340 try {
341 subscriber.onWorkScheduled(interactions, threadID);
342 } catch (error) {
343 if (!didCatchError) {
344 didCatchError = true;
345 caughtError = error;
346 }
347 }
348 });
349
350 if (didCatchError) {
351 throw caughtError;
352 }
353}
354
355function onWorkStarted(interactions, threadID) {
356 var didCatchError = false;
357 var caughtError = null;
358
359 subscribers.forEach(function (subscriber) {
360 try {
361 subscriber.onWorkStarted(interactions, threadID);
362 } catch (error) {
363 if (!didCatchError) {
364 didCatchError = true;
365 caughtError = error;
366 }
367 }
368 });
369
370 if (didCatchError) {
371 throw caughtError;
372 }
373}
374
375function onWorkStopped(interactions, threadID) {
376 var didCatchError = false;
377 var caughtError = null;
378
379 subscribers.forEach(function (subscriber) {
380 try {
381 subscriber.onWorkStopped(interactions, threadID);
382 } catch (error) {
383 if (!didCatchError) {
384 didCatchError = true;
385 caughtError = error;
386 }
387 }
388 });
389
390 if (didCatchError) {
391 throw caughtError;
392 }
393}
394
395function onWorkCanceled(interactions, threadID) {
396 var didCatchError = false;
397 var caughtError = null;
398
399 subscribers.forEach(function (subscriber) {
400 try {
401 subscriber.onWorkCanceled(interactions, threadID);
402 } catch (error) {
403 if (!didCatchError) {
404 didCatchError = true;
405 caughtError = error;
406 }
407 }
408 });
409
410 if (didCatchError) {
411 throw caughtError;
412 }
413}
414
415exports.unstable_clear = unstable_clear;
416exports.unstable_getCurrent = unstable_getCurrent;
417exports.unstable_getThreadID = unstable_getThreadID;
418exports.unstable_trace = unstable_trace;
419exports.unstable_wrap = unstable_wrap;
420exports.unstable_subscribe = unstable_subscribe;
421exports.unstable_unsubscribe = unstable_unsubscribe;
422 })();
423}