UNPKG

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