Skip to content

Commit

Permalink
prepare devTool
Browse files Browse the repository at this point in the history
  • Loading branch information
MrWangJustToDo committed Mar 5, 2024
1 parent 2ab6808 commit d30c1c1
Show file tree
Hide file tree
Showing 13 changed files with 147 additions and 329 deletions.
10 changes: 9 additions & 1 deletion packages/myreact-dom/src/client/mount/hydrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { initialFiberNode, MyReactFiberNode } from "@my-react/react-reconciler";

import { ClientDomDispatch } from "@my-react-dom-client/renderDispatch";
import { prepareRenderPlatform } from "@my-react-dom-client/renderPlatform";
import { checkRehydrate, checkRoot, enableASyncHydrate, prepareDevContainer, startRender, startRenderAsync } from "@my-react-dom-shared";
import { autoSetDevTools, checkRehydrate, checkRoot, enableASyncHydrate, prepareDevContainer, startRender, startRenderAsync } from "@my-react-dom-shared";

import { onceLog, onceLogConcurrentMode, onceLogLegacyLifeCycleMode, onceLogPerformanceWarn } from "./render";

Expand Down Expand Up @@ -36,8 +36,12 @@ const hydrateSync = (element: MyReactElement, container: RenderContainer, cb?: (

container.__container__ = renderDispatch;

renderDispatch.enableASyncHydrate = false;

renderDispatch.isHydrateRender = true;

autoSetDevTools(renderDispatch, renderPlatform);

initialFiberNode(fiber, renderDispatch);

startRender(fiber, renderDispatch, true);
Expand Down Expand Up @@ -66,8 +70,12 @@ const hydrateAsync = async (element: MyReactElement, container: RenderContainer,

container.__container__ = renderDispatch;

renderDispatch.enableASyncHydrate = true;

renderDispatch.isHydrateRender = true;

autoSetDevTools(renderDispatch, renderPlatform);

initialFiberNode(fiber, renderDispatch);

await startRenderAsync(fiber, renderDispatch, true);
Expand Down
6 changes: 5 additions & 1 deletion packages/myreact-dom/src/client/mount/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { include, once, STATE_TYPE } from "@my-react/react-shared";
import { ClientDomDispatch } from "@my-react-dom-client/renderDispatch";
import { prepareRenderPlatform } from "@my-react-dom-client/renderPlatform";
import { unmountComponentAtNode } from "@my-react-dom-client/tools";
import { checkRoot, prepareDevContainer, startRender } from "@my-react-dom-shared";
import { autoSetDevTools, checkRoot, prepareDevContainer, startRender } from "@my-react-dom-shared";

import type { LikeJSX } from "@my-react/react";
import type { CustomRenderPlatform } from "@my-react/react-reconciler";
Expand Down Expand Up @@ -129,8 +129,12 @@ export const render = (element: LikeJSX, _container: Partial<RenderContainer>, c

container.__container__ = renderDispatch;

renderDispatch.enableASyncHydrate = false;

renderDispatch.isClientRender = true;

autoSetDevTools(renderDispatch, renderPlatform);

initialFiberNode(fiber, renderDispatch);

startRender(fiber, renderDispatch);
Expand Down
6 changes: 4 additions & 2 deletions packages/myreact-dom/src/client/renderDispatch/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export class ClientDomDispatch extends CustomRenderDispatch {

performanceLogTimeLimit = asyncUpdateTimeLimit.current;

enableASyncHydrate = enableASyncHydrate.current;

patchToCommitAppend?: (_fiber: MyReactFiberNode) => void;

patchToCommitUpdate?: (_fiber: MyReactFiberNode) => void;
Expand Down Expand Up @@ -89,7 +91,7 @@ export class ClientDomDispatch extends CustomRenderDispatch {
clearNode(_fiber);
}
resolveLazyElement(_fiber: MyReactFiberNode): MyReactElementNode {
if (enableASyncHydrate.current) {
if (this.enableASyncHydrate) {
return resolveLazyElementLatest(_fiber, this);
} else {
return resolveLazyElementLegacy(_fiber, this);
Expand Down Expand Up @@ -146,7 +148,7 @@ if (__DEV__) {
const rootElement = createElement(rootElementType, rootElementProps);

const get = async () => {
if (enableASyncHydrate.current) {
if (this.enableASyncHydrate) {
const _re = enableScopeTreeLog.current;

enableScopeTreeLog.current = false;
Expand Down
12 changes: 8 additions & 4 deletions packages/myreact-dom/src/client/tools/hmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import { isServer } from "@my-react-dom-shared";

const { enableHMRForDev } = __my_react_shared__;

const HMR_FIELD = "__@my-react/hmr__";

/**
* @internal
*/
export const initGlobalHMR = () => {
if (__DEV__ && !isServer && enableHMRForDev.current) {
if (globalThis["__@my-react/hmr__"]) {
console.error(`[@my-react/react-dom] current environment already have a HMR runtime, maybe current environment have multiple version of '@my-react/react-dom'`);
if (globalThis[HMR_FIELD]) {
console.error(
`[@my-react/react-dom] current environment already have a HMR runtime, maybe current environment have multiple version of '@my-react/react-dom'`
);
} else {
globalThis["__@my-react/hmr__"] = {};
globalThis[HMR_FIELD] = {};

try {
initHMR(globalThis["__@my-react/hmr__"]);
initHMR(globalThis[HMR_FIELD]);
} catch (e) {
if (__DEV__) {
console.error(`[@my-react/react-dom] initHMR failed, error: ${(e as Error).message}`);
Expand Down
4 changes: 4 additions & 0 deletions packages/myreact-dom/src/noop/renderDispatch/noopDispatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export class NoopLegacyRenderDispatch extends CustomRenderDispatch {

isServerRender: boolean;

enableASyncHydrate = false;

renderTime: number | null;

hydrateTime: number | null;
Expand Down Expand Up @@ -104,6 +106,8 @@ export class NoopLatestRenderDispatch extends CustomRenderDispatch {

isServerRender: boolean;

enableASyncHydrate = true;

renderTime: number | null;

hydrateTime: number | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export class ServerDomDispatch extends CustomRenderDispatch {

isServerRender: boolean;

enableASyncHydrate = false;

renderTime: number | null;

hydrateTime: number | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export class LegacyServerStreamDispatch extends CustomRenderDispatch {

isServerRender: boolean;

enableASyncHydrate = false;

renderTime: number | null;

hydrateTime: number | null;
Expand Down Expand Up @@ -140,6 +142,8 @@ export class LatestServerStreamDispatch extends CustomRenderDispatch {

isServerRender: boolean;

enableASyncHydrate = true;

renderTime: number | null;

hydrateTime: number | null;
Expand Down
8 changes: 6 additions & 2 deletions packages/myreact-dom/src/shared/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
debugWithNode,
devErrorWithFiber,
devWarnWithFiber,
getCurrentDispatchFromFiber,
onceErrorWithKeyAndFiber,
onceWarnWithKeyAndFiber,
unmountFiber,
Expand All @@ -15,8 +16,8 @@ import { HighLight, debounce } from "@my-react-dom-client/tools";
import { latestNoopRender, legacyNoopRender } from "@my-react-dom-noop/mount/render";
import { PlainElement, ContainerElement, CommentStartElement } from "@my-react-dom-server/api";


import {
enableASyncHydrate,
enableControlComponent,
enableDOMField,
enableEventSystem,
Expand All @@ -31,6 +32,7 @@ import type { LikeJSX } from "@my-react/react";
import type { CustomRenderDispatch, MyReactFiberNodeDev } from "@my-react/react-reconciler";
import type { RenderContainer } from "@my-react-dom-client/mount";
import type { CommentEndElement, TextElement } from "@my-react-dom-server/api";
import type { LatestServerStreamDispatch, LegacyServerStreamDispatch, ServerDomDispatch } from "@my-react-dom-server/renderDispatch";

const { enableOptimizeTreeLog, enableScopeTreeLog } = __my_react_shared__;

Expand Down Expand Up @@ -126,8 +128,10 @@ export const prepareDevContainer = (renderDispatch: ClientDomDispatch) => {

if (!isValidElement(element)) return;

const renderDispatch = getCurrentDispatchFromFiber(this) as ClientDomDispatch | ServerDomDispatch | LegacyServerStreamDispatch | LatestServerStreamDispatch;

const get = async () => {
if (enableASyncHydrate.current) {
if (renderDispatch.enableASyncHydrate) {
const _re = enableScopeTreeLog.current;

enableScopeTreeLog.current = false;
Expand Down
38 changes: 38 additions & 0 deletions packages/myreact-dom/src/shared/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { initHMR } from "@my-react/react-reconciler";

import type { CustomRenderDispatch, CustomRenderPlatform } from "@my-react/react-reconciler";

export type DevToolRuntime = (dispatch: CustomRenderDispatch, platform: CustomRenderPlatform, hmrRuntime: typeof initHMR) => void;

export const setDevTools = (devToolRuntime: DevToolRuntime, dispatch: CustomRenderDispatch, platform: CustomRenderPlatform) => {
try {
devToolRuntime(dispatch, platform, initHMR);
} catch (e) {
if (__DEV__) {
console.error("devToolRuntime failed:", e);
}
void 0;
}
};

export const DEV_TOOL_RUNTIME_FIELD = "__MY_REACT_DEVTOOL_RUNTIME__";

export const DISPATCH_FIELD = "__@my-react/dispatch__";

export const autoSetDevTools = (dispatch: CustomRenderDispatch, platform: CustomRenderPlatform) => {
const runtime = globalThis[DEV_TOOL_RUNTIME_FIELD];

if (runtime) {
setDevTools(runtime, dispatch, platform);
}

if (typeof globalThis !== "undefined") {
if (Array.isArray(globalThis[DISPATCH_FIELD])) {
globalThis[DISPATCH_FIELD] = globalThis[DISPATCH_FIELD].filter((i) => i !== dispatch);

globalThis[DISPATCH_FIELD].push(dispatch);
} else {
globalThis[DISPATCH_FIELD] = [dispatch];
}
}
};
1 change: 1 addition & 0 deletions packages/myreact-dom/src/shared/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from "./env";
export * from "./ref";
export * from "./dom";
export * from "./dev";
export * from "./tools";
export * from "./debug";
export * from "./render";
Expand Down
79 changes: 62 additions & 17 deletions packages/myreact-refresh/src/RefreshRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import type { forwardRef, memo, MixinMyReactClassComponent, MixinMyReactFunction
import type { ClientDomDispatch } from "@my-react/react-dom";
import type { CustomRenderDispatch, HMR, setRefreshHandler } from "@my-react/react-reconciler";

const HMR_FIELD = "__@my-react/hmr__";

const DISPATCH_FIELD = "__@my-react/dispatch__";

const RUNTIME_FIELD = "__@my-react/react-refresh__";

const DEV_TOOL_FIELD = "__@my-react/react-refresh-dev__";

type Family = {
current: MyReactComponentType;
};
Expand All @@ -19,8 +27,9 @@ type Signature = {
type MyReactComponentType = ReturnType<typeof forwardRef> | ReturnType<typeof memo> | MixinMyReactClassComponent | MixinMyReactFunctionComponent;

type HMRGlobal = {
["__@my-react/hmr__"]: HMR;
["__@my-react/react-refresh__"]: {
[HMR_FIELD]: HMR;
[DISPATCH_FIELD]: CustomRenderDispatch[];
[RUNTIME_FIELD]: {
register: typeof register;
setSignature: typeof setSignature;
getFamilyByID: typeof getFamilyByID;
Expand All @@ -30,9 +39,11 @@ type HMRGlobal = {
collectCustomHooksForSignature: typeof collectCustomHooksForSignature;
createSignatureFunctionForTransform: typeof createSignatureFunctionForTransform;
};
["__@my-react/react-refresh__id"]: typeof allFamiliesByID;
["__@my-react/react-refresh__updated"]: typeof updatedFamiliesByType;
["__@my-react/react-refresh__signature"]: typeof allSignaturesByType;
[DEV_TOOL_FIELD]: {
allFamiliesByID: typeof allFamiliesByID;
allSignaturesByType: typeof allSignaturesByType;
updatedFamiliesByType: typeof updatedFamiliesByType;
};
};

const typedSelf = globalThis as unknown as HMRGlobal;
Expand Down Expand Up @@ -251,7 +262,7 @@ export const createSignatureFunctionForTransform = () => {
export const performReactRefresh = () => {
if (!pendingUpdates.length) return;

if (typeof typedSelf?.["__@my-react/hmr__"]?.hmr !== "function") {
if (typeof typedSelf?.[HMR_FIELD]?.hmr !== "function") {
console.log(`[@my-react/react-refresh] try to refresh current App failed, current environment not have a valid HMR runtime`);
return;
}
Expand All @@ -268,7 +279,7 @@ export const performReactRefresh = () => {
const nextType = getRenderTypeFormType(_nextType);

if (prevType && nextType) {
const fibers = typedSelf["__@my-react/hmr__"]?.getCurrentFibersFromType?.(prevType);
const fibers = typedSelf[HMR_FIELD]?.getCurrentFibersFromType?.(prevType);

updatedFamiliesByType.set(prevType, family);

Expand All @@ -280,11 +291,11 @@ export const performReactRefresh = () => {
const forceReset = !canPreserveStateBetween(prevType, nextType);

fibers.forEach((f) => {
const container = typedSelf["__@my-react/hmr__"]?.getCurrentDispatchFromFiber?.(f);
const container = typedSelf[HMR_FIELD]?.getCurrentDispatchFromFiber?.(f);

const hasRootUpdate = containers.get(container) || f === container.rootFiber;

typedSelf?.["__@my-react/hmr__"]?.hmr?.(f, nextType, forceReset);
typedSelf?.[HMR_FIELD]?.hmr?.(f, nextType, forceReset);

containers.set(container, hasRootUpdate);
});
Expand Down Expand Up @@ -319,6 +330,7 @@ export const performReactRefresh = () => {
} else {
container.rootFiber._devUpdate?.(hasRootUpdate ? STATE_TYPE.__triggerSync__ : STATE_TYPE.__skippedSync__, updateDone);
}
setRefreshRuntimeFieldForDev(container);
});
} else {
console.log(`[@my-react/react-refresh] nothing need to update`);
Expand Down Expand Up @@ -369,15 +381,48 @@ export const isLikelyComponentType = (type: MyReactElementType) => {
}
};

const setRefreshRuntimeFieldForDev = (container: CustomRenderDispatch) => {
if (Object.prototype.hasOwnProperty.call(container, "_refreshRuntime")) {
return;
}
Object.defineProperty(container, "_refreshRuntime", {
value: {
register,
setSignature,
getFamilyByID,
getFamilyByType,
performReactRefresh,
isLikelyComponentType,
collectCustomHooksForSignature,
createSignatureFunctionForTransform,
},
});
Object.defineProperty(container, "_refreshRuntimeDev", {
value: {
allFamiliesByID,
allSignaturesByType,
updatedFamiliesByType,
},
});
};

const tryToRegister = () => {
if (__DEV__) {
try {
if (typeof typedSelf?.["__@my-react/hmr__"]?.setRefreshHandler !== "function") {
if (typeof typedSelf?.[HMR_FIELD]?.setRefreshHandler !== "function") {
console.error(`%c[@my-react/react-refresh] inject Dev refresh failed!`, "color: red; font-size: 14px;");
} else {
console.log(`%c[@my-react/react-refresh] Dev refresh have been enabled!`, "color: #38B2AC; font-size: 14px;");

typedSelf?.["__@my-react/hmr__"]?.setRefreshHandler?.(resolveFamily as Parameters<typeof setRefreshHandler>[0]);
typedSelf?.[HMR_FIELD]?.setRefreshHandler?.(resolveFamily as Parameters<typeof setRefreshHandler>[0]);
}
} catch {
void 0;
}

try {
if (Array.isArray(typedSelf?.[DISPATCH_FIELD])) {
typedSelf[DISPATCH_FIELD].forEach((dispatch) => setRefreshRuntimeFieldForDev(dispatch));
}
} catch {
void 0;
Expand All @@ -390,7 +435,7 @@ export const injectIntoGlobalHook = (globalThis: Window) => globalThis.addEventL
export const version = __VERSION__;

if (__DEV__) {
typedSelf["__@my-react/react-refresh__"] = {
typedSelf[RUNTIME_FIELD] = {
register,
setSignature,
getFamilyByID,
Expand All @@ -401,9 +446,9 @@ if (__DEV__) {
createSignatureFunctionForTransform,
};

typedSelf["__@my-react/react-refresh__id"] = allFamiliesByID;

typedSelf["__@my-react/react-refresh__updated"] = updatedFamiliesByType;

typedSelf["__@my-react/react-refresh__signature"] = allSignaturesByType;
typedSelf[DEV_TOOL_FIELD] = {
allFamiliesByID,
allSignaturesByType,
updatedFamiliesByType,
};
}
Loading

0 comments on commit d30c1c1

Please sign in to comment.