You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
423 lines
11 KiB
423 lines
11 KiB
/** @license React v0.18.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 render-phase lifecycle hooks and setState |
|
// reducers by double invoking them in Strict Mode. |
|
|
|
// 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 legacy 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 |
|
|
|
|
|
|
|
|
|
|
|
// Flag to turn event.target and event.currentTarget in ReactNative from a reactTag to a component instance |
|
|
|
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; |
|
})(); |
|
}
|
|
|