/** @license React v0.17.0 * scheduler-tracing.development.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; if (process.env.NODE_ENV !== "production") { (function() { 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); // Helps identify side effects in begin-phase lifecycle hooks and setState reducers: // In some cases, StrictMode should also double-render lifecycles. // This can be confusing for tests though, // And it can be bad for performance in production. // This feature flag can be used to control the behavior: // To preserve the "Pause on caught exceptions" behavior of the debugger, we // replay the begin phase of a failed component inside invokeGuardedCallback. // Warn about deprecated, async-unsafe lifecycles; relates to RFC #6: // Gather advanced timing metrics for Profiler subtrees. // Trace which interactions trigger each commit. var enableSchedulerTracing = true; // SSR experiments // Only used in www builds. // Only used in www builds. // Disable javascript: URL strings in href for XSS protection. // React Fire: prevent the value and checked attributes from syncing // with their related DOM properties // These APIs will no longer be "unstable" in the upcoming 16.7 release, // Control this behavior with a flag to support 16.6 minor releases in the meanwhile. // Experimental React Flare event system and event components support. // Experimental Host Component support. // Experimental Scope support. // New API for JSX transforms to target - https://github.com/reactjs/rfcs/pull/107 // We will enforce mocking scheduler with scheduler/unstable_mock at some point. (v17?) // Till then, we warn about the missing mock, but still fallback to a sync mode compatible version // For tests, we flush suspense fallbacks in an act scope; // *except* in some of our own tests, where we test incremental loading states. // Add a callback property to suspense to notify which promises are currently // in the update queue. This allows reporting and tracing of what is causing // the user to see a loading state. // Also allows hydration callbacks to fire when a dehydrated boundary gets // hydrated or deleted. // Part of the simplification of React.createElement so we can eventually move // from React.createElement to React.jsx // https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md var DEFAULT_THREAD_ID = 0; // Counters used to generate unique IDs. var interactionIDCounter = 0; var threadIDCounter = 0; // Set of currently traced interactions. // Interactions "stack"– // Meaning that newly traced interactions are appended to the previously active set. // When an interaction goes out of scope, the previous set (if any) is restored. exports.__interactionsRef = null; // Listener(s) to notify when interactions begin and end. exports.__subscriberRef = null; if (enableSchedulerTracing) { exports.__interactionsRef = { current: new Set() }; exports.__subscriberRef = { current: null }; } function unstable_clear(callback) { if (!enableSchedulerTracing) { return callback(); } var prevInteractions = exports.__interactionsRef.current; exports.__interactionsRef.current = new Set(); try { return callback(); } finally { exports.__interactionsRef.current = prevInteractions; } } function unstable_getCurrent() { if (!enableSchedulerTracing) { return null; } else { return exports.__interactionsRef.current; } } function unstable_getThreadID() { return ++threadIDCounter; } function unstable_trace(name, timestamp, callback) { var threadID = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : DEFAULT_THREAD_ID; if (!enableSchedulerTracing) { return callback(); } var interaction = { __count: 1, id: interactionIDCounter++, name: name, timestamp: timestamp }; var prevInteractions = exports.__interactionsRef.current; // Traced interactions should stack/accumulate. // To do that, clone the current interactions. // The previous set will be restored upon completion. var interactions = new Set(prevInteractions); interactions.add(interaction); exports.__interactionsRef.current = interactions; var subscriber = exports.__subscriberRef.current; var returnValue; try { if (subscriber !== null) { subscriber.onInteractionTraced(interaction); } } finally { try { if (subscriber !== null) { subscriber.onWorkStarted(interactions, threadID); } } finally { try { returnValue = callback(); } finally { exports.__interactionsRef.current = prevInteractions; try { if (subscriber !== null) { subscriber.onWorkStopped(interactions, threadID); } } finally { interaction.__count--; // If no async work was scheduled for this interaction, // Notify subscribers that it's completed. if (subscriber !== null && interaction.__count === 0) { subscriber.onInteractionScheduledWorkCompleted(interaction); } } } } } return returnValue; } function unstable_wrap(callback) { var threadID = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_THREAD_ID; if (!enableSchedulerTracing) { return callback; } var wrappedInteractions = exports.__interactionsRef.current; var subscriber = exports.__subscriberRef.current; if (subscriber !== null) { subscriber.onWorkScheduled(wrappedInteractions, threadID); } // Update the pending async work count for the current interactions. // Update after calling subscribers in case of error. wrappedInteractions.forEach(function (interaction) { interaction.__count++; }); var hasRun = false; function wrapped() { var prevInteractions = exports.__interactionsRef.current; exports.__interactionsRef.current = wrappedInteractions; subscriber = exports.__subscriberRef.current; try { var returnValue; try { if (subscriber !== null) { subscriber.onWorkStarted(wrappedInteractions, threadID); } } finally { try { returnValue = callback.apply(undefined, arguments); } finally { exports.__interactionsRef.current = prevInteractions; if (subscriber !== null) { subscriber.onWorkStopped(wrappedInteractions, threadID); } } } return returnValue; } finally { if (!hasRun) { // We only expect a wrapped function to be executed once, // But in the event that it's executed more than once– // Only decrement the outstanding interaction counts once. hasRun = true; // Update pending async counts for all wrapped interactions. // If this was the last scheduled async work for any of them, // Mark them as completed. wrappedInteractions.forEach(function (interaction) { interaction.__count--; if (subscriber !== null && interaction.__count === 0) { subscriber.onInteractionScheduledWorkCompleted(interaction); } }); } } } wrapped.cancel = function cancel() { subscriber = exports.__subscriberRef.current; try { if (subscriber !== null) { subscriber.onWorkCanceled(wrappedInteractions, threadID); } } finally { // Update pending async counts for all wrapped interactions. // If this was the last scheduled async work for any of them, // Mark them as completed. wrappedInteractions.forEach(function (interaction) { interaction.__count--; if (subscriber && interaction.__count === 0) { subscriber.onInteractionScheduledWorkCompleted(interaction); } }); } }; return wrapped; } var subscribers = null; if (enableSchedulerTracing) { subscribers = new Set(); } function unstable_subscribe(subscriber) { if (enableSchedulerTracing) { subscribers.add(subscriber); if (subscribers.size === 1) { exports.__subscriberRef.current = { onInteractionScheduledWorkCompleted: onInteractionScheduledWorkCompleted, onInteractionTraced: onInteractionTraced, onWorkCanceled: onWorkCanceled, onWorkScheduled: onWorkScheduled, onWorkStarted: onWorkStarted, onWorkStopped: onWorkStopped }; } } } function unstable_unsubscribe(subscriber) { if (enableSchedulerTracing) { subscribers.delete(subscriber); if (subscribers.size === 0) { exports.__subscriberRef.current = null; } } } function onInteractionTraced(interaction) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onInteractionTraced(interaction); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onInteractionScheduledWorkCompleted(interaction) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onInteractionScheduledWorkCompleted(interaction); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onWorkScheduled(interactions, threadID) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onWorkScheduled(interactions, threadID); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onWorkStarted(interactions, threadID) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onWorkStarted(interactions, threadID); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onWorkStopped(interactions, threadID) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onWorkStopped(interactions, threadID); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onWorkCanceled(interactions, threadID) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onWorkCanceled(interactions, threadID); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } exports.unstable_clear = unstable_clear; exports.unstable_getCurrent = unstable_getCurrent; exports.unstable_getThreadID = unstable_getThreadID; exports.unstable_trace = unstable_trace; exports.unstable_wrap = unstable_wrap; exports.unstable_subscribe = unstable_subscribe; exports.unstable_unsubscribe = unstable_unsubscribe; })(); }