UNPKG

11.6 kBJavaScriptView Raw
1/** @license React v0.17.0
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 // In some cases, StrictMode should also double-render lifecycles.
23// This can be confusing for tests though,
24// And it can be bad for performance in production.
25// This feature flag can be used to control the behavior:
26
27 // To preserve the "Pause on caught exceptions" behavior of the debugger, we
28// replay the begin phase of a failed component inside invokeGuardedCallback.
29
30 // Warn about deprecated, async-unsafe lifecycles; relates to RFC #6:
31
32 // Gather advanced timing metrics for Profiler subtrees.
33
34 // Trace which interactions trigger each commit.
35
36var enableSchedulerTracing = true; // SSR experiments
37
38
39 // Only used in www builds.
40
41 // Only used in www builds.
42
43 // Disable javascript: URL strings in href for XSS protection.
44
45 // React Fire: prevent the value and checked attributes from syncing
46// with their related DOM properties
47
48 // These APIs will no longer be "unstable" in the upcoming 16.7 release,
49// Control this behavior with a flag to support 16.6 minor releases in the meanwhile.
50
51
52 // Experimental React Flare event system and event components support.
53
54 // Experimental Host Component support.
55
56 // Experimental Scope support.
57
58 // New API for JSX transforms to target - https://github.com/reactjs/rfcs/pull/107
59
60 // We will enforce mocking scheduler with scheduler/unstable_mock at some point. (v17?)
61// Till then, we warn about the missing mock, but still fallback to a sync mode compatible version
62
63 // For tests, we flush suspense fallbacks in an act scope;
64// *except* in some of our own tests, where we test incremental loading states.
65
66 // Add a callback property to suspense to notify which promises are currently
67// in the update queue. This allows reporting and tracing of what is causing
68// the user to see a loading state.
69// Also allows hydration callbacks to fire when a dehydrated boundary gets
70// hydrated or deleted.
71
72 // Part of the simplification of React.createElement so we can eventually move
73// from React.createElement to React.jsx
74// https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md
75
76var DEFAULT_THREAD_ID = 0; // Counters used to generate unique IDs.
77
78var interactionIDCounter = 0;
79var threadIDCounter = 0; // Set of currently traced interactions.
80// Interactions "stack"–
81// Meaning that newly traced interactions are appended to the previously active set.
82// When an interaction goes out of scope, the previous set (if any) is restored.
83
84exports.__interactionsRef = null; // Listener(s) to notify when interactions begin and end.
85
86exports.__subscriberRef = null;
87
88if (enableSchedulerTracing) {
89 exports.__interactionsRef = {
90 current: new Set()
91 };
92 exports.__subscriberRef = {
93 current: null
94 };
95}
96
97function unstable_clear(callback) {
98 if (!enableSchedulerTracing) {
99 return callback();
100 }
101
102 var prevInteractions = exports.__interactionsRef.current;
103 exports.__interactionsRef.current = new Set();
104
105 try {
106 return callback();
107 } finally {
108 exports.__interactionsRef.current = prevInteractions;
109 }
110}
111function unstable_getCurrent() {
112 if (!enableSchedulerTracing) {
113 return null;
114 } else {
115 return exports.__interactionsRef.current;
116 }
117}
118function unstable_getThreadID() {
119 return ++threadIDCounter;
120}
121function unstable_trace(name, timestamp, callback) {
122 var threadID = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : DEFAULT_THREAD_ID;
123
124 if (!enableSchedulerTracing) {
125 return callback();
126 }
127
128 var interaction = {
129 __count: 1,
130 id: interactionIDCounter++,
131 name: name,
132 timestamp: timestamp
133 };
134 var prevInteractions = exports.__interactionsRef.current; // Traced interactions should stack/accumulate.
135 // To do that, clone the current interactions.
136 // The previous set will be restored upon completion.
137
138 var interactions = new Set(prevInteractions);
139 interactions.add(interaction);
140 exports.__interactionsRef.current = interactions;
141 var subscriber = exports.__subscriberRef.current;
142 var returnValue;
143
144 try {
145 if (subscriber !== null) {
146 subscriber.onInteractionTraced(interaction);
147 }
148 } finally {
149 try {
150 if (subscriber !== null) {
151 subscriber.onWorkStarted(interactions, threadID);
152 }
153 } finally {
154 try {
155 returnValue = callback();
156 } finally {
157 exports.__interactionsRef.current = prevInteractions;
158
159 try {
160 if (subscriber !== null) {
161 subscriber.onWorkStopped(interactions, threadID);
162 }
163 } finally {
164 interaction.__count--; // If no async work was scheduled for this interaction,
165 // Notify subscribers that it's completed.
166
167 if (subscriber !== null && interaction.__count === 0) {
168 subscriber.onInteractionScheduledWorkCompleted(interaction);
169 }
170 }
171 }
172 }
173 }
174
175 return returnValue;
176}
177function unstable_wrap(callback) {
178 var threadID = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_THREAD_ID;
179
180 if (!enableSchedulerTracing) {
181 return callback;
182 }
183
184 var wrappedInteractions = exports.__interactionsRef.current;
185 var subscriber = exports.__subscriberRef.current;
186
187 if (subscriber !== null) {
188 subscriber.onWorkScheduled(wrappedInteractions, threadID);
189 } // Update the pending async work count for the current interactions.
190 // Update after calling subscribers in case of error.
191
192
193 wrappedInteractions.forEach(function (interaction) {
194 interaction.__count++;
195 });
196 var hasRun = false;
197
198 function wrapped() {
199 var prevInteractions = exports.__interactionsRef.current;
200 exports.__interactionsRef.current = wrappedInteractions;
201 subscriber = exports.__subscriberRef.current;
202
203 try {
204 var returnValue;
205
206 try {
207 if (subscriber !== null) {
208 subscriber.onWorkStarted(wrappedInteractions, threadID);
209 }
210 } finally {
211 try {
212 returnValue = callback.apply(undefined, arguments);
213 } finally {
214 exports.__interactionsRef.current = prevInteractions;
215
216 if (subscriber !== null) {
217 subscriber.onWorkStopped(wrappedInteractions, threadID);
218 }
219 }
220 }
221
222 return returnValue;
223 } finally {
224 if (!hasRun) {
225 // We only expect a wrapped function to be executed once,
226 // But in the event that it's executed more than once–
227 // Only decrement the outstanding interaction counts once.
228 hasRun = true; // Update pending async counts for all wrapped interactions.
229 // If this was the last scheduled async work for any of them,
230 // Mark them as completed.
231
232 wrappedInteractions.forEach(function (interaction) {
233 interaction.__count--;
234
235 if (subscriber !== null && interaction.__count === 0) {
236 subscriber.onInteractionScheduledWorkCompleted(interaction);
237 }
238 });
239 }
240 }
241 }
242
243 wrapped.cancel = function cancel() {
244 subscriber = exports.__subscriberRef.current;
245
246 try {
247 if (subscriber !== null) {
248 subscriber.onWorkCanceled(wrappedInteractions, threadID);
249 }
250 } finally {
251 // Update pending async counts for all wrapped interactions.
252 // If this was the last scheduled async work for any of them,
253 // Mark them as completed.
254 wrappedInteractions.forEach(function (interaction) {
255 interaction.__count--;
256
257 if (subscriber && interaction.__count === 0) {
258 subscriber.onInteractionScheduledWorkCompleted(interaction);
259 }
260 });
261 }
262 };
263
264 return wrapped;
265}
266
267var subscribers = null;
268
269if (enableSchedulerTracing) {
270 subscribers = new Set();
271}
272
273function unstable_subscribe(subscriber) {
274 if (enableSchedulerTracing) {
275 subscribers.add(subscriber);
276
277 if (subscribers.size === 1) {
278 exports.__subscriberRef.current = {
279 onInteractionScheduledWorkCompleted: onInteractionScheduledWorkCompleted,
280 onInteractionTraced: onInteractionTraced,
281 onWorkCanceled: onWorkCanceled,
282 onWorkScheduled: onWorkScheduled,
283 onWorkStarted: onWorkStarted,
284 onWorkStopped: onWorkStopped
285 };
286 }
287 }
288}
289function unstable_unsubscribe(subscriber) {
290 if (enableSchedulerTracing) {
291 subscribers.delete(subscriber);
292
293 if (subscribers.size === 0) {
294 exports.__subscriberRef.current = null;
295 }
296 }
297}
298
299function onInteractionTraced(interaction) {
300 var didCatchError = false;
301 var caughtError = null;
302 subscribers.forEach(function (subscriber) {
303 try {
304 subscriber.onInteractionTraced(interaction);
305 } catch (error) {
306 if (!didCatchError) {
307 didCatchError = true;
308 caughtError = error;
309 }
310 }
311 });
312
313 if (didCatchError) {
314 throw caughtError;
315 }
316}
317
318function onInteractionScheduledWorkCompleted(interaction) {
319 var didCatchError = false;
320 var caughtError = null;
321 subscribers.forEach(function (subscriber) {
322 try {
323 subscriber.onInteractionScheduledWorkCompleted(interaction);
324 } catch (error) {
325 if (!didCatchError) {
326 didCatchError = true;
327 caughtError = error;
328 }
329 }
330 });
331
332 if (didCatchError) {
333 throw caughtError;
334 }
335}
336
337function onWorkScheduled(interactions, threadID) {
338 var didCatchError = false;
339 var caughtError = null;
340 subscribers.forEach(function (subscriber) {
341 try {
342 subscriber.onWorkScheduled(interactions, threadID);
343 } catch (error) {
344 if (!didCatchError) {
345 didCatchError = true;
346 caughtError = error;
347 }
348 }
349 });
350
351 if (didCatchError) {
352 throw caughtError;
353 }
354}
355
356function onWorkStarted(interactions, threadID) {
357 var didCatchError = false;
358 var caughtError = null;
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 subscribers.forEach(function (subscriber) {
379 try {
380 subscriber.onWorkStopped(interactions, threadID);
381 } catch (error) {
382 if (!didCatchError) {
383 didCatchError = true;
384 caughtError = error;
385 }
386 }
387 });
388
389 if (didCatchError) {
390 throw caughtError;
391 }
392}
393
394function onWorkCanceled(interactions, threadID) {
395 var didCatchError = false;
396 var caughtError = null;
397 subscribers.forEach(function (subscriber) {
398 try {
399 subscriber.onWorkCanceled(interactions, threadID);
400 } catch (error) {
401 if (!didCatchError) {
402 didCatchError = true;
403 caughtError = error;
404 }
405 }
406 });
407
408 if (didCatchError) {
409 throw caughtError;
410 }
411}
412
413exports.unstable_clear = unstable_clear;
414exports.unstable_getCurrent = unstable_getCurrent;
415exports.unstable_getThreadID = unstable_getThreadID;
416exports.unstable_trace = unstable_trace;
417exports.unstable_wrap = unstable_wrap;
418exports.unstable_subscribe = unstable_subscribe;
419exports.unstable_unsubscribe = unstable_unsubscribe;
420 })();
421}