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;
|
|||
|
})();
|
|||
|
}
|