Skip to content

Commit

Permalink
refactor memo
Browse files Browse the repository at this point in the history
  • Loading branch information
yisar committed Nov 30, 2022
1 parent 6b4e63f commit 8fda775
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 70 deletions.
2 changes: 1 addition & 1 deletion demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/keys.tsx"></script>
<script type="module" src="/src/use-state.tsx"></script>
<script>
</script>
</body>
Expand Down
12 changes: 2 additions & 10 deletions demo/src/keys.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,8 @@ import {h, render, useState } from "../../src/index"
// }

function App() {
const [key, setKey] = useState([1,2,3])
return <div>
<button onClick={() => setKey([3,2,1])}>x</button>
<ul>
{key.map((i) => (
// <Li i={i} key={i} />
<li key={i} >{i}</li>
))}
</ul>
</div>
const [list, setList] = useState([1,2,3])
return <div>{list.map((d) => <span>{d}</span>)} <button onClick={() => setList(list.concat(4))}>+</button></div>
}

// function App() {
Expand Down
19 changes: 12 additions & 7 deletions demo/src/suspense.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render, lazy, Suspense } from '../../src/index'
import { render, lazy, Suspense, h } from '../../src/index'

const Lazy = lazy(() => {
return new Promise(resolve =>
Expand All @@ -12,12 +12,17 @@ const Lazy = lazy(() => {
)
})

function App() {
return <Suspense fallback={'loading'}>
<Lazy/>
<div>111</div>
<Lazy/>
</Suspense>
export function App() {
return (
<div>
<Suspense fallback={<div>loading...</div>}>
<Lazy />
<div>111</div>
<Lazy />
<div>111</div>
</Suspense>
</div>
)
}

render(<App />, document.getElementById('app'))
114 changes: 62 additions & 52 deletions src/reconcile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,51 +45,61 @@ export const update = (fiber?: IFiber) => {
}
}

const reconcile = (WIP?: IFiber): boolean => {
while (WIP && !shouldYield()) WIP = capture(WIP)
if (WIP) return reconcile.bind(null, WIP)
const reconcile = (wip?: IFiber): boolean => {
while (wip && !shouldYield()) wip = capture(wip)
if (wip) return reconcile.bind(null, wip)
if (finish) {
commit(finish)
finish = null
}
return null
}

const capture = (WIP: IFiber): IFiber | undefined => {
WIP.isComp = isFn(WIP.type)
if (WIP.isComp) {
if ((WIP.type as FC).memo && WIP.oldProps) {
let scu = (WIP.type as FC).shouldUpdate || shouldUpdate
if (!scu(WIP.props, WIP.oldProps) && (WIP.lane === LANE.UPDATE)) { // fast-fix
while (WIP) {
if (WIP.sibling)
return WIP.sibling
WIP = WIP.parent
}
}
const memo = (wip) => {
if ((wip.type as FC).memo && wip.oldProps) {
let scu = (wip.type as FC).shouldUpdate || shouldUpdate
if (!scu(wip.props, wip.oldProps)) { // fast-fix
return getSibling(wip)
}
updateHook(WIP)
}
return null
}

const capture = (wip: IFiber): IFiber | undefined => {
wip.isComp = isFn(wip.type)
if (wip.isComp) {
const memoFiber = memo(wip)
if (memoFiber) {
return memoFiber
}
updateHook(wip)
} else {
updateHost(WIP)
updateHost(wip)
}
if (WIP.child) return WIP.child
while (WIP) {
bubble(WIP)
if (!finish && WIP.lane & LANE.DIRTY) {
finish = WIP
WIP.lane &= ~LANE.DIRTY
if (wip.child) return wip.child
const sibling = getSibling(wip)
return sibling
}

const getSibling = (wip) =>{
while (wip) {
bubble(wip)
if (!finish && wip.lane & LANE.DIRTY) {
finish = wip
wip.lane &= ~LANE.DIRTY
return null
}
if (WIP.sibling) return WIP.sibling
WIP = WIP.parent
if (wip.sibling) return wip.sibling
wip = wip.parent
}
return null
}

const bubble = WIP => {
if (WIP.isComp) {
if (WIP.hooks) {
side(WIP.hooks.layout)
schedule(() => side(WIP.hooks.effect))
const bubble = wip => {
if (wip.isComp) {
if (wip.hooks) {
side(wip.hooks.layout)
schedule(() => side(wip.hooks.effect))
}
}
}
Expand All @@ -104,36 +114,36 @@ const shouldUpdate = (a, b) => {
for (let i in b) if (a[i] !== b[i]) return true
}

const updateHook = <P = Attributes>(WIP: IFiber): any => {
const updateHook = <P = Attributes>(wip: IFiber): any => {
resetCursor()
currentFiber = WIP
let children = (WIP.type as FC<P>)(WIP.props)
diffKids(WIP, simpleVnode(children))
currentFiber = wip
let children = (wip.type as FC<P>)(wip.props)
diffKids(wip, simpleVnode(children))
}

const updateHost = (WIP: IFiber): void => {
WIP.parentNode = (getParentNode(WIP) as any) || {}
if (!WIP.node) {
if (WIP.type === 'svg') WIP.lane |= LANE.SVG
WIP.node = createElement(WIP) as HTMLElementEx
const updateHost = (wip: IFiber): void => {
wip.parentNode = (getParentNode(wip) as any) || {}
if (!wip.node) {
if (wip.type === 'svg') wip.lane |= LANE.SVG
wip.node = createElement(wip) as HTMLElementEx
}
WIP.childNodes = Array.from(WIP.node.childNodes || [])
diffKids(WIP, WIP.props.children)
wip.childNodes = Array.from(wip.node.childNodes || [])
diffKids(wip, wip.props.children)
}

const simpleVnode = (type: any) =>
isStr(type) ? createText(type as string) : type

const getParentNode = (WIP: IFiber): HTMLElement | undefined => {
while ((WIP = WIP.parent)) {
if (!WIP.isComp) return WIP.node
const getParentNode = (wip: IFiber): HTMLElement | undefined => {
while ((wip = wip.parent)) {
if (!wip.isComp) return wip.node
}
}

const diffKids = (WIP: any, children: FreNode): void => {
let isMount = !WIP.kids,
aCh = WIP.kids || [],
bCh = (WIP.kids = arrayfy(children) as any),
const diffKids = (wip: any, children: FreNode): void => {
let isMount = !wip.kids,
aCh = wip.kids || [],
bCh = (wip.kids = arrayfy(children) as any),
aHead = 0,
bHead = 0,
aTail = aCh.length - 1,
Expand All @@ -154,7 +164,7 @@ const diffKids = (WIP: any, children: FreNode): void => {

for (let i = 0, aIndex = aHead, bIndex = bHead, mIndex; i < diff.length; i++) {
const op = diff[i]
const after = WIP.node?.childNodes[aIndex]
const after = wip.node?.childNodes[aIndex]
if (op === LANE.UPDATE) {
if (!same(aCh[aIndex], bCh[bIndex])) {
bCh[bIndex].lane = LANE.INSERT
Expand Down Expand Up @@ -201,14 +211,14 @@ const diffKids = (WIP: any, children: FreNode): void => {

for (let i = 0, prev = null, len = bCh.length; i < len; i++) {
const child = bCh[i]
if (WIP.lane & LANE.SVG) {
if (wip.lane & LANE.SVG) {
child.lane |= LANE.SVG
}
child.parent = WIP
child.parent = wip
if (i > 0) {
prev.sibling = child
} else {
WIP.child = child
wip.child = child
}
prev = child
}
Expand Down

0 comments on commit 8fda775

Please sign in to comment.