Compare commits
No commits in common. "e12618a688905b7ae9394fb80625aa6a2d414028" and "ac413285bffc88cebf0bd2d68fb19b754d00643d" have entirely different histories.
e12618a688
...
ac413285bf
|
|
@ -4,7 +4,6 @@ import {
|
||||||
EffectTag,
|
EffectTag,
|
||||||
isFunctionFiber,
|
isFunctionFiber,
|
||||||
isHostFiber,
|
isHostFiber,
|
||||||
StateHook,
|
|
||||||
type Child,
|
type Child,
|
||||||
type FiberNode,
|
type FiberNode,
|
||||||
type FunctionFiber,
|
type FunctionFiber,
|
||||||
|
|
@ -91,44 +90,16 @@ function createFiberFromElement(element: JSXElement): FiberNode {
|
||||||
effectTag: EffectTag.NoEffect,
|
effectTag: EffectTag.NoEffect,
|
||||||
alternate: null,
|
alternate: null,
|
||||||
nextEffect: null,
|
nextEffect: null,
|
||||||
actions: null,
|
|
||||||
pendingChildren: [],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function canBailout(fiber: FiberNode) {
|
|
||||||
const alternate = fiber.alternate;
|
|
||||||
if (!alternate) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (fiber.actions) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const propKeys = Object.keys(fiber.pendingProps);
|
|
||||||
const pendingPropKeys = Object.keys(alternate.pendingProps);
|
|
||||||
if (propKeys.length !== pendingPropKeys.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
propKeys.some(
|
|
||||||
(key) => fiber.pendingProps[key] !== alternate.pendingProps[key],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateFunctionComponent(fiber: FunctionFiber) {
|
function updateFunctionComponent(fiber: FunctionFiber) {
|
||||||
wipFiber = fiber;
|
wipFiber = fiber;
|
||||||
hookIndex = 0;
|
hookIndex = 0;
|
||||||
wipFiber.hooks = [];
|
wipFiber.hooks = [];
|
||||||
wipFiber.effectTag = EffectTag.NoEffect;
|
wipFiber.effectTag = EffectTag.NoEffect;
|
||||||
if (fiber.alternate && canBailout(fiber)) {
|
const children = [fiber.type(fiber.pendingProps)];
|
||||||
fiber.pendingChildren = fiber.alternate.pendingChildren;
|
reconcileChildren(fiber, children);
|
||||||
} else {
|
|
||||||
fiber.pendingChildren = [fiber.type(fiber.pendingProps)];
|
|
||||||
}
|
|
||||||
reconcileChildren(fiber, fiber.pendingChildren);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateHostComponent(fiber: HostFiber) {
|
function updateHostComponent(fiber: HostFiber) {
|
||||||
|
|
@ -157,26 +128,6 @@ function pushEffect(fiber: FiberNode) {
|
||||||
wipRoot.lastEffect = fiber;
|
wipRoot.lastEffect = fiber;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAlternate(oldFiber: FiberNode): FiberNode {
|
|
||||||
return {
|
|
||||||
$$typeof: FiberNodeSymbol,
|
|
||||||
type: oldFiber.type,
|
|
||||||
key: null,
|
|
||||||
child: null,
|
|
||||||
sibling: null,
|
|
||||||
parent: wipFiber,
|
|
||||||
index: 0,
|
|
||||||
dom: oldFiber.dom,
|
|
||||||
hooks: [],
|
|
||||||
pendingProps: oldFiber.pendingProps,
|
|
||||||
effectTag: EffectTag.Update,
|
|
||||||
alternate: oldFiber,
|
|
||||||
nextEffect: null,
|
|
||||||
actions: null,
|
|
||||||
pendingChildren: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function reconcileChildren(
|
function reconcileChildren(
|
||||||
wipFiber: FiberNode | RootFiber,
|
wipFiber: FiberNode | RootFiber,
|
||||||
children: Child[] = [],
|
children: Child[] = [],
|
||||||
|
|
@ -199,9 +150,21 @@ function reconcileChildren(
|
||||||
|
|
||||||
const isSameType = oldFiber && element && element.type === oldFiber.type;
|
const isSameType = oldFiber && element && element.type === oldFiber.type;
|
||||||
if (isSameType && oldFiber) {
|
if (isSameType && oldFiber) {
|
||||||
newFiber = createAlternate(oldFiber);
|
newFiber = {
|
||||||
newFiber.key = element.key ?? null;
|
$$typeof: FiberNodeSymbol,
|
||||||
newFiber.pendingProps = element.props;
|
type: oldFiber.type,
|
||||||
|
key: element.key ?? null,
|
||||||
|
child: null,
|
||||||
|
sibling: null,
|
||||||
|
parent: wipFiber,
|
||||||
|
index: 0,
|
||||||
|
dom: oldFiber.dom,
|
||||||
|
hooks: [],
|
||||||
|
pendingProps: element.props,
|
||||||
|
effectTag: EffectTag.Update,
|
||||||
|
alternate: oldFiber,
|
||||||
|
nextEffect: null,
|
||||||
|
};
|
||||||
pushEffect(newFiber);
|
pushEffect(newFiber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,8 +183,6 @@ function reconcileChildren(
|
||||||
effectTag: EffectTag.Placement,
|
effectTag: EffectTag.Placement,
|
||||||
alternate: null,
|
alternate: null,
|
||||||
nextEffect: null,
|
nextEffect: null,
|
||||||
actions: null,
|
|
||||||
pendingChildren: [],
|
|
||||||
};
|
};
|
||||||
pushEffect(newFiber);
|
pushEffect(newFiber);
|
||||||
}
|
}
|
||||||
|
|
@ -433,8 +394,6 @@ export function createRootFiber(root: HTMLElement): RootFiber {
|
||||||
isRoot: true,
|
isRoot: true,
|
||||||
firstEffect: null,
|
firstEffect: null,
|
||||||
lastEffect: null,
|
lastEffect: null,
|
||||||
actions: null,
|
|
||||||
pendingChildren: [],
|
|
||||||
};
|
};
|
||||||
const rootFiber: RootFiber = {
|
const rootFiber: RootFiber = {
|
||||||
$$typeof: FiberNodeSymbol,
|
$$typeof: FiberNodeSymbol,
|
||||||
|
|
@ -453,8 +412,6 @@ export function createRootFiber(root: HTMLElement): RootFiber {
|
||||||
isRoot: true,
|
isRoot: true,
|
||||||
firstEffect: null,
|
firstEffect: null,
|
||||||
lastEffect: null,
|
lastEffect: null,
|
||||||
actions: null,
|
|
||||||
pendingChildren: [],
|
|
||||||
};
|
};
|
||||||
alternate.alternate = rootFiber;
|
alternate.alternate = rootFiber;
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
|
|
@ -473,22 +430,9 @@ export function render(rootFiber: RootFiber, element: JSXElement) {
|
||||||
rootFiber.alternate!.pendingProps = {
|
rootFiber.alternate!.pendingProps = {
|
||||||
children: [element],
|
children: [element],
|
||||||
};
|
};
|
||||||
|
// const fiber = createFiberFromElement(element);
|
||||||
|
// fiber.parent = rootFiber;
|
||||||
|
// rootFiber.child = fiber;
|
||||||
|
// wipRoot.child = fiber;
|
||||||
unitOfWork = wipRoot;
|
unitOfWork = wipRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logFiber(label: string) {
|
|
||||||
console.log(label, unitOfWork);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useState<T>(initialValue: T) {
|
|
||||||
if (!unitOfWork)
|
|
||||||
throw new Error("useState can only be used inside of a component!");
|
|
||||||
const fiber = unitOfWork;
|
|
||||||
const alternate = fiber.alternate?.hooks[hookIndex];
|
|
||||||
if (alternate && alternate.type !== StateHook)
|
|
||||||
throw new Error("Hook order changed smth.");
|
|
||||||
const value: T = alternate ? alternate.value : initialValue;
|
|
||||||
const setValue = (newValue: T) => {
|
|
||||||
fiber.hooks[hookIndex];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,7 @@
|
||||||
import { createRootFiber, logFiber, render, scheduleRerender } from "./cr";
|
import { createRootFiber, render, scheduleRerender } from "./cr";
|
||||||
import { domFiber } from "./symbols";
|
import { domFiber } from "./symbols";
|
||||||
|
|
||||||
let renderCount = 0;
|
let renderCount = 0;
|
||||||
|
|
||||||
const Child = () => {
|
|
||||||
logFiber("Child");
|
|
||||||
return <div>Child</div>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
console.log("render");
|
console.log("render");
|
||||||
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
|
|
@ -21,7 +15,6 @@ const App = () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Hello world {String(++renderCount)}
|
Hello world {String(++renderCount)}
|
||||||
<Child />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -42,17 +42,11 @@ export const EffectHook = Symbol.for("cr.effect-hook");
|
||||||
type Hook =
|
type Hook =
|
||||||
| {
|
| {
|
||||||
type: typeof StateHook;
|
type: typeof StateHook;
|
||||||
value: any;
|
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: typeof EffectHook;
|
type: typeof EffectHook;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Action = {
|
|
||||||
execute: (fiber: FiberNode) => void;
|
|
||||||
nextAction: null | Action;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface FiberNode {
|
export interface FiberNode {
|
||||||
$$typeof: typeof FiberNodeSymbol;
|
$$typeof: typeof FiberNodeSymbol;
|
||||||
// Identity
|
// Identity
|
||||||
|
|
@ -69,14 +63,12 @@ export interface FiberNode {
|
||||||
dom: Node | null;
|
dom: Node | null;
|
||||||
hooks: Hook[];
|
hooks: Hook[];
|
||||||
pendingProps: any;
|
pendingProps: any;
|
||||||
pendingChildren: Child[];
|
|
||||||
|
|
||||||
effectTag: EffectTag;
|
effectTag: EffectTag;
|
||||||
|
|
||||||
// Used for double buffering
|
// Used for double buffering
|
||||||
alternate: FiberNode | null;
|
alternate: FiberNode | null;
|
||||||
nextEffect: FiberNode | null;
|
nextEffect: FiberNode | null;
|
||||||
actions: Action | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FunctionFiber = FiberNode & {
|
export type FunctionFiber = FiberNode & {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue