424 lines
11 KiB
JavaScript
424 lines
11 KiB
JavaScript
/** @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;
|
||
})();
|
||
}
|