Skip to content

Commit

Permalink
fix retrigger update
Browse files Browse the repository at this point in the history
  • Loading branch information
MrWangJustToDo committed Nov 5, 2024
1 parent d45826e commit 8e4e551
Show file tree
Hide file tree
Showing 16 changed files with 211 additions and 233 deletions.
37 changes: 32 additions & 5 deletions __tests__/testLoop.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<div id="root"></div>

<script type="text/babel">
const { useState, useEffect } = React;
const { useState, useEffect, useLayoutEffect } = React;

const Bar = ({ set, s }) => {
return <div>Bar {s}
Expand All @@ -28,27 +28,54 @@

const App = () => {
const [s, setS] = useState(0);
const [b, setB] = useState(0)

if (s < 40 && s > 0) {
console.log('s', s);

console.log('b', b);

if (s < 5 && s > 0) {
setS(s + 1);
}

if (b < 9 && b > 0) {
setB(b + 1);
}

useLayoutEffect(() => {
console.log('useLayoutEffect', s);

return () => {
console.log('useLayoutEffect return', s);
}
}, [s, b])

useEffect(() => {
console.log('useEffect', s);

return () => {
console.log('useEffect return', s);
}
}, [s, b])

// useEffect(() => {
// setS((s) => s + 1)
// })

return <div>123 {s}
return <div>123 {s}, {b}
<br />
<Bar s={s} set={() => {
console.warn('setS', s)
console.warn('setB', b)
setS(s + 1)
setB(b + 1)
}} />
</div>
}

// ReactDOM.createRoot(document.getElementById('root')).render(<App />);
ReactDOM.createRoot(document.getElementById('root')).render(<App />);

ReactDOM.render(<App />, root);
// ReactDOM.render(<App />, root);
</script>
</body>

Expand Down
6 changes: 3 additions & 3 deletions packages/myreact-reconciler/src/processState/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ export const processState = (_params: UpdateQueue) => {

_params.isImmediate = !currentScopeFiber.current || !!currentRunningFiber.current;

_params.isRetrigger = !!currentComponentFiber.current;

const isImmediate = _params.isImmediate;

if (_params.type === UpdateQueueType.component) {
Expand Down Expand Up @@ -93,6 +95,7 @@ export const processState = (_params: UpdateQueue) => {
);
} else if (!isErrorBoundariesComponent(ownerFiber)) {
const triggeredElementName = getElementName(ownerFiber);

const currentElementName = getElementName(currentCFiber);

onceWarnWithKeyAndFiber(
Expand Down Expand Up @@ -120,7 +123,6 @@ export const processState = (_params: UpdateQueue) => {
ownerFiber.updateQueue.push(_params);

prepareUpdateOnFiber(ownerFiber, renderDispatch, isImmediate && renderDispatch?.isAppMounted);
// ownerFiber._prepare(isInitial && renderDispatch?.isAppMounted);
} else if (_params.type === UpdateQueueType.hook) {
const ownerFiber = getInstanceOwnerFiber(_params.trigger);

Expand Down Expand Up @@ -179,7 +181,6 @@ export const processState = (_params: UpdateQueue) => {
ownerFiber.updateQueue.push(_params);

prepareUpdateOnFiber(ownerFiber, renderDispatch, isImmediate && renderDispatch?.isAppMounted);
// ownerFiber._prepare(isInitial && renderDispatch?.isAppMounted);
} else {
const ownerFiber = _params.trigger as MyReactFiberNode;

Expand All @@ -192,6 +193,5 @@ export const processState = (_params: UpdateQueue) => {
ownerFiber.updateQueue.push(_params);

prepareUpdateOnFiber(ownerFiber, renderDispatch, isImmediate && renderDispatch?.isAppMounted);
// ownerFiber._prepare(isInitial && renderDispatch?.isAppMounted);
}
};
16 changes: 11 additions & 5 deletions packages/myreact-reconciler/src/renderNextWork/feature.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { __my_react_internal__ } from "@my-react/react";
import { STATE_TYPE, include } from "@my-react/react-shared";
import { STATE_TYPE, include, remove } from "@my-react/react-shared";

import { runtimeNextWork, runtimeNextWorkDev } from "../runtimeGenerate";
import { currentRenderDispatch, devErrorWithFiber } from "../share";
Expand All @@ -24,9 +24,12 @@ export const performToNextFiberFromRoot = (fiber: MyReactFiberNode, renderDispat
STATE_TYPE.__triggerSync__ |
STATE_TYPE.__triggerSyncForce__ |
STATE_TYPE.__triggerConcurrent__ |
STATE_TYPE.__triggerConcurrentForce__
STATE_TYPE.__triggerConcurrentForce__ |
STATE_TYPE.__retrigger__
)
) {
fiber.state = remove(fiber.state, STATE_TYPE.__retrigger__);

currentRenderDispatch.current = renderDispatch;

currentRunningFiber.current = fiber;
Expand All @@ -42,7 +45,7 @@ export const performToNextFiberFromRoot = (fiber: MyReactFiberNode, renderDispat
currentRenderDispatch.current = null;
}

fiber.state = STATE_TYPE.__stable__;
if (!include(fiber.state, STATE_TYPE.__retrigger__)) fiber.state = STATE_TYPE.__stable__;

if (fiber.child) return fiber.child;

Expand Down Expand Up @@ -76,9 +79,12 @@ export const performToNextFiberFromTrigger = (fiber: MyReactFiberNode, renderDis
STATE_TYPE.__triggerSync__ |
STATE_TYPE.__triggerSyncForce__ |
STATE_TYPE.__triggerConcurrent__ |
STATE_TYPE.__triggerConcurrentForce__
STATE_TYPE.__triggerConcurrentForce__ |
STATE_TYPE.__retrigger__
)
) {
fiber.state = remove(fiber.state, STATE_TYPE.__retrigger__);

currentRenderDispatch.current = renderDispatch;

currentRunningFiber.current = fiber;
Expand All @@ -93,7 +99,7 @@ export const performToNextFiberFromTrigger = (fiber: MyReactFiberNode, renderDis

currentRenderDispatch.current = null;

fiber.state = STATE_TYPE.__stable__;
if (!include(fiber.state, STATE_TYPE.__retrigger__)) fiber.state = STATE_TYPE.__stable__;

if (fiber.child) return fiber.child;
}
Expand Down
22 changes: 17 additions & 5 deletions packages/myreact-reconciler/src/runtimeFiber/instance.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { __my_react_internal__, __my_react_shared__ } from "@my-react/react";
import { PATCH_TYPE, STATE_TYPE, include } from "@my-react/react-shared";
import { PATCH_TYPE, STATE_TYPE, include, merge, remove } from "@my-react/react-shared";

import { processClassComponentUpdateQueue, processFunctionComponentUpdateQueue, processLazyComponentUpdate } from "../dispatchQueue";
import { listenerMap, type CustomRenderDispatch } from "../renderDispatch";
import { triggerRevert, triggerUpdate } from "../renderUpdate";
import { setImmediateNextFiber } from "../runtimeUpdate";
import { getFiberTreeWithFiber, getTypeFromElementNode, NODE_TYPE, safeCallWithCurrentFiber } from "../share";

import type { MyReactFiberNodeDev } from "./interface";
Expand All @@ -13,7 +14,7 @@ import type { ListTree } from "@my-react/react-shared";

type NativeNode = Record<string, any>;

const { currentRenderPlatform } = __my_react_internal__;
const { currentRenderPlatform, currentRunningFiber } = __my_react_internal__;

const { enableConcurrentMode } = __my_react_shared__;

Expand Down Expand Up @@ -101,7 +102,7 @@ const processUpdateOnFiber = (fiber: MyReactFiberNode, renderDispatch: CustomRen

const flag = enableConcurrentMode.current;

// const currentIsRunning = currentRunningFiber.current;
const currentRunning = currentRunningFiber.current;

let updateState: UpdateState | null = null;

Expand All @@ -123,12 +124,23 @@ const processUpdateOnFiber = (fiber: MyReactFiberNode, renderDispatch: CustomRen
},
});

// TODO get from updateState ?
if (currentRunning && currentRunning === fiber) {
fiber.state = remove(fiber.state, STATE_TYPE.__stable__);

fiber.state = merge(fiber.state, STATE_TYPE.__retrigger__);

setImmediateNextFiber(fiber);

return;
}

if (updateState.isSync) {
renderPlatform.microTask(function triggerSyncUpdateOnFiber() {
triggerUpdate(fiber, updateState.isForce ? STATE_TYPE.__triggerSyncForce__ : STATE_TYPE.__triggerSync__, updateState.callback);
});
} else {
renderPlatform.microTask(function processQueueAsync() {
renderPlatform.microTask(function triggerConcurrentUpdateOnFiber() {
triggerUpdate(fiber, updateState.isForce ? STATE_TYPE.__triggerConcurrentForce__ : STATE_TYPE.__triggerConcurrent__, updateState.callback);
});
}
Expand All @@ -143,7 +155,7 @@ export const prepareUpdateOnFiber = (fiber: MyReactFiberNode, renderDispatch: Cu
if (isImmediate) {
processUpdateOnFiber(fiber, renderDispatch);
} else {
renderPlatform.microTask(function processQueueAsync() {
renderPlatform.microTask(function asyncProcessUpdateOnFiber() {
processUpdateOnFiber(fiber, renderDispatch);
});
}
Expand Down
5 changes: 5 additions & 0 deletions packages/myreact-reconciler/src/runtimeGenerate/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,13 @@ export const transformChildrenFiber = (parentFiber: MyReactFiberNode, children:

const isHMR = include(parentFiber.state, STATE_TYPE.__hmr__);

const isRetrigger = include(parentFiber.state, STATE_TYPE.__retrigger__);

const renderDispatch = currentRenderDispatch.current;

// is current is retrigger update, skip update children
if (isRetrigger) return;

if (isUpdate || isHMR) {
const { existingChildrenMap, existingChildrenArray } = getExistingChildren(parentFiber);

Expand Down
25 changes: 21 additions & 4 deletions packages/myreact-reconciler/src/runtimeUpdate/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,56 @@ import { performToNextFiberFromRoot, performToNextFiberFromTrigger } from "../re
import { triggerFiberUpdateListener } from "../runtimeFiber";

import type { CustomRenderDispatch } from "../renderDispatch";
import type { MyReactFiberNode } from "../runtimeFiber";

let nextWorkFiber: MyReactFiberNode | null = null;

export const updateLoopSyncFromRoot = (renderDispatch: CustomRenderDispatch) => {
while (renderDispatch.runtimeFiber.nextWorkingFiber) {
nextWorkFiber = null;
const currentFiber = renderDispatch.runtimeFiber.nextWorkingFiber;
const nextFiber = performToNextFiberFromRoot(currentFiber, renderDispatch);
triggerFiberUpdateListener(renderDispatch, currentFiber);
renderDispatch.runtimeFiber.nextWorkingFiber = nextFiber;
renderDispatch.runtimeFiber.nextWorkingFiber = nextWorkFiber || nextFiber;
nextWorkFiber = null;
}
};

export const updateLoopSyncFromTrigger = (renderDispatch: CustomRenderDispatch) => {
while (renderDispatch.runtimeFiber.nextWorkingFiber) {
nextWorkFiber = null;
const currentFiber = renderDispatch.runtimeFiber.nextWorkingFiber;
const nextFiber = performToNextFiberFromTrigger(currentFiber, renderDispatch);
triggerFiberUpdateListener(renderDispatch, currentFiber);
renderDispatch.runtimeFiber.nextWorkingFiber = nextFiber;
renderDispatch.runtimeFiber.nextWorkingFiber = nextWorkFiber || nextFiber;
nextWorkFiber = null;
}
};

export const updateLoopConcurrentFromRoot = (renderDispatch: CustomRenderDispatch) => {
while (renderDispatch.runtimeFiber.nextWorkingFiber && !renderDispatch.shouldYield()) {
nextWorkFiber = null;
const currentFiber = renderDispatch.runtimeFiber.nextWorkingFiber;
const nextFiber = performToNextFiberFromRoot(currentFiber, renderDispatch);
triggerFiberUpdateListener(renderDispatch, currentFiber);
renderDispatch.runtimeFiber.nextWorkingFiber = nextFiber;
renderDispatch.runtimeFiber.nextWorkingFiber = nextWorkFiber || nextFiber;
nextWorkFiber = null;
}
};

export const updateLoopConcurrentFromTrigger = (renderDispatch: CustomRenderDispatch) => {
while (renderDispatch.runtimeFiber.nextWorkingFiber && !renderDispatch.shouldYield()) {
nextWorkFiber = null;
const currentFiber = renderDispatch.runtimeFiber.nextWorkingFiber;
const nextFiber = performToNextFiberFromTrigger(currentFiber, renderDispatch);
triggerFiberUpdateListener(renderDispatch, currentFiber);
renderDispatch.runtimeFiber.nextWorkingFiber = nextFiber;
renderDispatch.runtimeFiber.nextWorkingFiber = nextWorkFiber || nextFiber;
nextWorkFiber = null;
}
};

export const setImmediateNextFiber = (fiber: MyReactFiberNode) => {
if (!nextWorkFiber) {
nextWorkFiber = fiber;
}
};
1 change: 1 addition & 0 deletions packages/myreact-shared/src/symbol/fiberState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export enum STATE_TYPE {
__triggerSyncForce__ = 1 << 8,
__unmount__ = 1 << 9,
__hmr__ = 1 << 10,
__retrigger__ = 1 << 11,
}
4 changes: 4 additions & 0 deletions packages/myreact/src/renderQueue/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type ComponentUpdateQueue<State = Record<string, unknown>, Props = Record
trigger: MyReactComponent;
isForce?: boolean;
isSync?: boolean;
isRetrigger?: boolean;
isImmediate?: boolean;
payLoad?: Partial<State> | ((state: State, props: Props) => Partial<State>);
callback?: () => void;
Expand All @@ -25,6 +26,7 @@ export type HookUpdateQueue = {
trigger: RenderHook;
isForce?: boolean;
isSync?: boolean;
isRetrigger?: boolean;
isImmediate?: boolean;
payLoad?: Action;
callback?: () => void;
Expand All @@ -38,6 +40,7 @@ export type LazyUpdateQueue = {
trigger: RenderFiber;
isForce?: boolean;
isSync?: boolean;
isRetrigger?: boolean;
isImmediate?: boolean;
payLoad?: MixinMyReactFunctionComponent | MixinMyReactClassComponent;
callback?: () => void;
Expand All @@ -51,6 +54,7 @@ export type ContextUpdateQueue = {
trigger: RenderFiber;
isForce?: boolean;
isSync?: boolean;
isRetrigger?: boolean;
isImmediate?: boolean;
payLoad?: Record<string, unknown>;
callback?: () => void;
Expand Down
Loading

0 comments on commit 8e4e551

Please sign in to comment.