function diff(oldTree, newTree) {
const patches = {};
walk(oldTree, newTree, 0, patches);
return patches;
}
function walk(oldNode, newNode, index, patches) {
const currentPatches = [];
if (newNode === null) {
currentPatches.push({ type: 'REMOVE', index });
}
else if (typeof oldNode !== typeof newNode || oldNode.type !== newNode.type) {
currentPatches.push({ type: 'REPLACE', node: newNode });
}
else if (oldNode.type === newNode.type) {
currentPatches.push({ type: 'UPDATE', props: diffProps(oldNode.props, newNode.props) });
diffChildren(oldNode.children, newNode.children, patches);
}
if (currentPatches.length) {
patches[index] = currentPatches;
}
}
function diffProps(oldProps, newProps) {
const propsPatches = {};
for (const key in oldProps) {
if (oldProps[key] !== newProps[key]) {
propsPatches[key] = newProps[key];
}
}
for (const key in newProps) {
if (!oldProps.hasOwnProperty(key)) {
propsPatches[key] = newProps[key];
}
}
return propsPatches;
}
function diffChildren(oldChildren, newChildren, patches) {
}
const oldTree = {
type: 'div',
props: { className: 'container' },
children: [
{ type: 'h1', props: {}, children: ['Hello'] },
{ type: 'p', props: {}, children: ['World'] }
]
};
const newTree = {
type: 'div',
props: { className: 'container' },
children: [
{ type: 'h1', props: {}, children: ['Hello'] },
{ type: 'p', props: { style: 'color: red' }, children: ['World'] }
]
};
const patches = diff(oldTree, newTree);
console.log(patches);