Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fresh] Track mounted roots via DevTools Hook #15928

Merged
merged 4 commits into from
Jun 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 34 additions & 14 deletions packages/react-reconciler/src/ReactFiberHotReloading.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,32 @@ export type Family = {|
current: any,
|};

export type HotUpdate = {|
resolveFamily: (any => Family | void) | null,
export type RefreshUpdate = {|
staleFamilies: Set<Family>,
updatedFamilies: Set<Family>,
|};

let resolveFamily: (any => Family | void) | null = null;
// Resolves type to a family.
type RefreshHandler = any => Family | void;

// Used by React Refresh runtime through DevTools Global Hook.
export type SetRefreshHandler = (handler: RefreshHandler | null) => void;
export type ScheduleRefresh = (root: FiberRoot, update: RefreshUpdate) => void;
export type FindHostInstancesForRefresh = (
root: FiberRoot,
families: Array<Family>,
) => Set<Instance>;

let resolveFamily: RefreshHandler | null = null;
// $FlowFixMe Flow gets confused by a WeakSet feature check below.
let failedBoundaries: WeakSet<Fiber> | null = null;

export let setRefreshHandler = (handler: RefreshHandler | null): void => {
if (__DEV__) {
resolveFamily = handler;
}
};

export function resolveFunctionForHotReloading(type: any): any {
if (__DEV__) {
if (resolveFamily === null) {
Expand Down Expand Up @@ -192,7 +208,7 @@ export function isCompatibleFamilyForHotReloading(
export function markFailedErrorBoundaryForHotReloading(fiber: Fiber) {
if (__DEV__) {
if (resolveFamily === null) {
// Not hot reloading.
// Hot reloading is disabled.
return;
}
if (typeof WeakSet !== 'function') {
Expand All @@ -205,12 +221,16 @@ export function markFailedErrorBoundaryForHotReloading(fiber: Fiber) {
}
}

export function scheduleHotUpdate(root: FiberRoot, hotUpdate: HotUpdate): void {
export let scheduleRefresh: ScheduleRefresh = (
root: FiberRoot,
update: RefreshUpdate,
): void => {
if (__DEV__) {
// TODO: warn if its identity changes over time?
resolveFamily = hotUpdate.resolveFamily;

const {staleFamilies, updatedFamilies} = hotUpdate;
if (resolveFamily === null) {
// Hot reloading is disabled.
return;
}
const {staleFamilies, updatedFamilies} = update;
flushPassiveEffects();
flushSync(() => {
scheduleFibersWithFamiliesRecursively(
Expand All @@ -220,7 +240,7 @@ export function scheduleHotUpdate(root: FiberRoot, hotUpdate: HotUpdate): void {
);
});
}
}
};

function scheduleFibersWithFamiliesRecursively(
fiber: Fiber,
Expand Down Expand Up @@ -292,10 +312,10 @@ function scheduleFibersWithFamiliesRecursively(
}
}

export function findHostInstancesForHotUpdate(
export let findHostInstancesForRefresh: FindHostInstancesForRefresh = (
root: FiberRoot,
families: Array<Family>,
): Set<Instance> {
): Set<Instance> => {
if (__DEV__) {
const hostInstances = new Set();
const types = new Set(families.map(family => family.current));
Expand All @@ -307,10 +327,10 @@ export function findHostInstancesForHotUpdate(
return hostInstances;
} else {
throw new Error(
'Did not expect findHostInstancesForHotUpdate to be called in production.',
'Did not expect findHostInstancesForRefresh to be called in production.',
);
}
}
};

function findHostInstancesForMatchingFibersRecursively(
fiber: Fiber,
Expand Down
13 changes: 7 additions & 6 deletions packages/react-reconciler/src/ReactFiberReconciler.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ import {Sync} from './ReactFiberExpirationTime';
import {revertPassiveEffectsChange} from 'shared/ReactFeatureFlags';
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
import {
scheduleHotUpdate,
findHostInstancesForHotUpdate,
scheduleRefresh,
setRefreshHandler,
findHostInstancesForRefresh,
} from './ReactFiberHotReloading';

type OpaqueRoot = FiberRoot;
Expand Down Expand Up @@ -475,10 +476,6 @@ export function injectIntoDevTools(devToolsConfig: DevToolsConfig): boolean {

return injectInternals({
...devToolsConfig,
findHostInstancesForHotUpdate: __DEV__
? findHostInstancesForHotUpdate
: null,
scheduleHotUpdate: __DEV__ ? scheduleHotUpdate : null,
overrideHookState,
overrideProps,
setSuspenseHandler,
Expand All @@ -498,5 +495,9 @@ export function injectIntoDevTools(devToolsConfig: DevToolsConfig): boolean {
}
return findFiberByHostInstance(instance);
},
// React Refresh
findHostInstancesForRefresh: __DEV__ ? findHostInstancesForRefresh : null,
scheduleRefresh: __DEV__ ? scheduleRefresh : null,
setRefreshHandler: __DEV__ ? setRefreshHandler : null,
});
}