a small incremental UI library for the web
javascript web ui
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Keyed reconciliation

garrison 8ef4c226 7318efa5

+92 -50
+84
js/fiber.ts
··· 1 + export function makeFiber() { 2 + return { 3 + type: null, 4 + props: null, 5 + 6 + index: null, 7 + key: null, 8 + 9 + dom: null, 10 + effect: null, 11 + 12 + parent: null, 13 + child: null, 14 + sibling: null, 15 + 16 + alternate: null, 17 + }; 18 + } 19 + 20 + export function reconcileChildren(parentFiber, childElementOrElements) { 21 + if (Array.isArray(childElementOrElements)) { 22 + return reconcileArray(parentFiber, childElementOrElements); 23 + } 24 + else { 25 + } 26 + } 27 + 28 + function reconcileArray(parentFiber, elements) { 29 + const oldFiberLookup = buildLookup(parentFiber.child); 30 + 31 + let firstNewChild = null; 32 + let prevChild; 33 + for (let i = 0; i < elements.length; i++) { 34 + const el = elements[i]; 35 + const key = el.key || i; 36 + const oldFiber = oldFiberLookup.get(key); 37 + const newFiber = update(oldFiberLookup, el, i); 38 + 39 + // TODO: placement 40 + newFiber.index = i; 41 + console.log(oldFiber, newFiber); 42 + 43 + if (prevChild) prevChild.sibling = newFiber; 44 + else firstNewChild = newFiber; 45 + prevChild = newFiber; 46 + } 47 + 48 + return firstNewChild; 49 + } 50 + 51 + function update(oldFiber, element, index) { 52 + if (typeof element == 'object') { 53 + return updateElement(oldFiber, element, index); 54 + } 55 + return null; 56 + } 57 + 58 + function updateElement(oldFiber, element, index) { 59 + if (oldFiber === null || oldFiber.type !== element.type) { 60 + const newFiber = makeFiber(); 61 + newFiber.type = element.type; 62 + newFiber.props = element.props; 63 + return newFiber; 64 + } 65 + else { 66 + const newFiber = oldFiber.alternate || makeFiber(); 67 + newFiber.props = element.props; 68 + return newFiber; 69 + } 70 + } 71 + 72 + function buildLookup(childFiber) { 73 + const lookup = new Map(); 74 + 75 + let fiber = childFiber; 76 + let i = 0; 77 + while (fiber) { 78 + key = fiber.key || i; 79 + lookup.set(key, fiber); 80 + fiber = fiber.sibling; 81 + } 82 + 83 + return lookup; 84 + }
+8 -50
js/noir.ts
··· 1 + import { makeFiber, reconcileChildren } from './fiber.ts'; 2 + 1 3 export function createElement(type, props, ...children) { 2 4 return { 3 5 type: type, ··· 11 13 let nextFiber; 12 14 13 15 export function render(element, container) { 14 - const rootFiber = { 15 - dom: container, 16 - props: { children: [element] }, 17 - }; 16 + const rootFiber = makeFiber(); 17 + rootFiber.type = 'root'; 18 + rootFiber.dom = container; 19 + rootFiber.props = { children: [element] }; 18 20 19 21 nextFiber = rootFiber; 20 22 performWork(); ··· 50 52 function renderHostFiber(fiber) { 51 53 if (!fiber.dom) { 52 54 } 53 - reconcileChildren(fiber, fiber.props.children); 54 - } 55 - 56 - function reconcileChildren(fiber, elements) { 57 - const oldChildren = gatherOldChildren(fiber); 58 - let prevSibling; 59 - 60 - for (let i = 0; i < Math.max(oldChildren.length, elements.length); i++) { 61 - const oldChild = oldChildren[i]; 62 - const element = elements[i]; 63 - 64 - const sameType = oldChild && element && oldChild.type == element.type; 65 - let newChild; 66 - 67 - if (sameType) { 68 - } 69 - 70 - if (!sameType && element) { 71 - newChild = { 72 - type: element.type, 73 - props: element.props, 74 - dom: null, 75 - 76 - parent: fiber, 77 - effect: 'placement', 78 - }; 79 - } 80 - 81 - if (!sameType && oldChild) { 82 - } 83 - 84 - if (prevSibling) prevSibling.sibling = newChild; 85 - else fiber.child = newChild; 86 - 87 - prevSibling = newChild; 88 - } 89 - } 90 - 91 - function gatherOldChildren(fiber) { 92 - const acc = []; 93 - let oldChild = fiber.alternate && fiber.alternate.child; 94 - while (oldChild != null) { 95 - acc.push(oldChild); 96 - oldChild = oldChild.sibling; 97 - } 98 - return acc; 55 + const firstNewChild = reconcileChildren(fiber, fiber.props.children); 56 + fiber.child = firstNewChild; 99 57 }