quick_diff | function shouldSetAsProps(el, key, value) {
if (key === "form" && el.tagName === "INPUT") return false;
return key in el;
}
function createRenderer(options) {
const {
createElement,
insert,
setElementText,
patchProps,
createText,
setText
} = options;
function mountElement(vnode, container, anchor) {
const el = (vnode.el = createElement(vnode.type));
if (typeof vnode.children === "string") {
setElementText(el, vnode.children);
} else if (Array.isArray(vnode.children)) {
vnode.children.forEach((child) => {
patch(null, child, el);
});
}
if (vnode.props) {
for (const key in vnode.props) {
patchProps(el, key, null, vnode.props[key]);
}
}
insert(el, container, anchor);
}
function patchChildren(n1, n2, container) {
if (typeof n2.children === "string") {
if (Array.isArray(n1.children)) {
n1.children.forEach((c) => unmount(c));
}
setElementText(container, n2.children);
} else if (Array.isArray(n2.children)) {
patchKeyedChildren(n1, n2, container);
} else {
if (Array.isArray(n1.children)) {
n1.children.forEach((c) => unmount(c));
} else if (typeof n1.children === "string") {
setElementText(container, "");
}
}
}
function patchKeyedChildren(n1, n2, container) {
const oldChildren = n1.children;
const newChildren = n2.children;
let oldStartIdx = 0;
let oldEndIdx = oldChildren.length - 1;
let newStartIdx = 0;
let newEndIdx = newChildren.length - 1;
let oldStartVNode = oldChildren[oldStartIdx];
let oldEndVNode = oldChildren[oldEndIdx];
let newStartVNode = newChildren[newStartIdx];
let newEndVNode = newChildren[newEndIdx];
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (!oldStartVNode) {
oldStartVNode = oldChildren[++oldStartIdx];
} else if (!oldEndVNode) {
oldEndVNode = newChildren[--oldEndIdx];
} else if (oldStartVNode.key === newStartVNode.key) {
patch(oldStartVNode, newStartVNode, container);
oldStartVNode = oldChildren[++oldStartIdx];
newStartVNode = newChildren[++newStartIdx];
} else if (oldEndVNode.key === newEndVNode.key) {
patch(oldEndVNode, newEndVNode, container);
oldEndVNode = oldChildren[--oldEndIdx];
newEndVNode = newChildren[--newEndIdx];
} else if (oldStartVNode.key === newEndVNode.key) {
patch(oldStartVNode, newEndVNode, container);
insert(oldStartVNode.el, container, oldEndVNode.el.nextSibling);
oldStartVNode = oldChildren[++oldStartIdx];
newEndVNode = newChildren[--newEndIdx];
} else if (oldEndVNode.key === newStartVNode.key) {
patch(oldEndVNode, newStartVNode, container);
insert(oldEndVNode.el, container, oldStartVNode.el);
oldEndVNode = oldChildren[--oldEndIdx];
newStartVNode = newChildren[++newStartIdx];
} else {
const idxInOld = oldChildren.findIndex(
(node) => node.key === newStartVNode.key
);
if (idxInOld > 0) {
const vnodeToMove = oldChildren[idxInOld];
patch(vnodeToMove, newStartVNode, container);
insert(vnodeToMove.el, container, oldStartVNode.el);
oldChildren[idxInOld] = undefined;
} else {
patch(null, newStartVNode, container, oldStartVNode.el);
}
newStartVNode = newChildren[++newStartIdx];
}
}
if (oldEndIdx < oldStartIdx && newStartIdx <= newEndIdx) {
for (let i = newStartIdx; i <= newEndIdx; i++) {
patch(null, newChildren[i], container, oldStartVNode.el);
}
} else if (newEndIdx < newStartIdx && oldStartIdx <= oldEndIdx) {
for (let i = oldStartIdx; i <= oldEndIdx; i++) {
unmount(oldChildren[i]);
}
}
}
function patchElement(n1, n2) {
const el = (n2.el = n1.el);
const oldProps = n1.props;
const newProps = n2.props;
for (const key in newProps) {
if (newProps[key] !== oldProps[key]) {
patchProps(el, key, oldProps[key], newProps[key]);
}
}
for (const key in oldProps) {
if (!(key in newProps)) {
patchProps(el, key, oldProps[key], null);
}
}
patchChildren(n1, n2, el);
}
function unmount(vnode) {
if (vnode.type === Fragment) {
vnode.children.forEach((c) => unmount(c));
return;
}
const parent = vnode.el.parentNode;
if (parent) {
parent.removeChild(vnode.el);
}
}
function patch(n1, n2, container, anchor) {
if (n1 && n1.type !== n2.type) {
unmount(n1);
n1 = null;
}
const { type } = n2;
if (typeof type === "string") {
if (!n1) {
mountElement(n2, container, anchor);
} else {
patchElement(n1, n2);
}
} else if (type === Text) {
if (!n1) {
const el = (n2.el = createText(n2.children));
insert(el, container);
} else {
const el = (n2.el = n1.el);
if (n2.children !== n1.children) {
setText(el, n2.children);
}
}
} else if (type === Fragment) {
if (!n1) {
n2.children.forEach((c) => patch(null, c, container));
} else {
patchChildren(n1, n2, container);
}
}
}
function render(vnode, container) {
if (vnode) {
patch(container._vnode, vnode, container);
} else {
if (container._vnode) {
unmount(container._vnode);
}
}
container._vnode = vnode;
}
return {
render
};
}
const renderer = createRenderer({
createElement(tag) {
return document.createElement(tag);
},
setElementText(el, text) {
el.textContent = text;
},
insert(el, parent, anchor = null) {
parent.insertBefore(el, anchor);
},
createText(text) {
return document.createTextNode(text);
},
setText(el, text) {
el.nodeValue = text;
},
patchProps(el, key, prevValue, nextValue) {
if (/^on/.test(key)) {
const invokers = el._vei || (el._vei = {});
let invoker = invokers[key];
const name = key.slice(2).toLowerCase();
if (nextValue) {
if (!invoker) {
invoker = el._vei[key] = (e) => {
console.log(e.timeStamp);
console.log(invoker.attached);
if (e.timeStamp < invoker.attached) return;
if (Array.isArray(invoker.value)) {
invoker.value.forEach((fn) => fn(e));
} else {
invoker.value(e);
}
};
invoker.value = nextValue;
invoker.attached = performance.now();
el.addEventListener(name, invoker);
} else {
invoker.value = nextValue;
}
} else if (invoker) {
el.removeEventListener(name, invoker);
}
} else if (key === "class") {
el.className = nextValue || "";
} else if (shouldSetAsProps(el, key, nextValue)) {
const type = typeof el[key];
if (type === "boolean" && nextValue === "") {
el[key] = true;
} else {
el[key] = nextValue;
}
} else {
el.setAttribute(key, nextValue);
}
}
});
const Fragment = Symbol()
var VNode1 = {
type: "div",
children: []
};
var VNode2 = {
type: "div",
children: []
};
for (let i = 1; i <= 1000; i++) {
const childNode = {
type: "grid-item",
children: i.toString(),
key: i
};
VNode1.children.push(childNode);
}
renderer.render(VNode1, document.querySelector("#grid-container"));
function getSequence(arr) {
const p = arr.slice()
const result = [0]
let i, j, u, v, c
const len = arr.length
for (i = 0; i < len; i++) {
const arrI = arr[i]
if (arrI !== 0) {
j = result[result.length - 1]
if (arr[j] < arrI) {
p[i] = j
result.push(i)
continue
}
u = 0
v = result.length - 1
while (u < v) {
c = ((u + v) / 2) | 0
if (arr[result[c]] < arrI) {
u = c + 1
} else {
v = c
}
}
if (arrI < arr[result[u]]) {
if (u > 0) {
p[i] = result[u - 1]
}
result[u] = i
}
}
}
u = result.length
v = result[u - 1]
while (u-- > 0) {
result[u] = v
v = p[v]
}
return result
}
| ready |
double_diff | function shouldSetAsProps(el, key, value) {
if (key === "form" && el.tagName === "INPUT") return false;
return key in el;
}
function createRenderer(options) {
const {
createElement,
insert,
setElementText,
patchProps,
createText,
setText
} = options;
function mountElement(vnode, container, anchor) {
const el = (vnode.el = createElement(vnode.type));
if (typeof vnode.children === "string") {
setElementText(el, vnode.children);
} else if (Array.isArray(vnode.children)) {
vnode.children.forEach((child) => {
patch(null, child, el);
});
}
if (vnode.props) {
for (const key in vnode.props) {
patchProps(el, key, null, vnode.props[key]);
}
}
insert(el, container, anchor);
}
function patchChildren(n1, n2, container) {
if (typeof n2.children === "string") {
if (Array.isArray(n1.children)) {
n1.children.forEach((c) => unmount(c));
}
setElementText(container, n2.children);
} else if (Array.isArray(n2.children)) {
patchKeyedChildren(n1, n2, container);
} else {
if (Array.isArray(n1.children)) {
n1.children.forEach((c) => unmount(c));
} else if (typeof n1.children === "string") {
setElementText(container, "");
}
}
}
function patchKeyedChildren(n1, n2, container) {
const oldChildren = n1.children;
const newChildren = n2.children;
let oldStartIdx = 0;
let oldEndIdx = oldChildren.length - 1;
let newStartIdx = 0;
let newEndIdx = newChildren.length - 1;
let oldStartVNode = oldChildren[oldStartIdx];
let oldEndVNode = oldChildren[oldEndIdx];
let newStartVNode = newChildren[newStartIdx];
let newEndVNode = newChildren[newEndIdx];
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (!oldStartVNode) {
oldStartVNode = oldChildren[++oldStartIdx];
} else if (!oldEndVNode) {
oldEndVNode = newChildren[--oldEndIdx];
} else if (oldStartVNode.key === newStartVNode.key) {
patch(oldStartVNode, newStartVNode, container);
oldStartVNode = oldChildren[++oldStartIdx];
newStartVNode = newChildren[++newStartIdx];
} else if (oldEndVNode.key === newEndVNode.key) {
patch(oldEndVNode, newEndVNode, container);
oldEndVNode = oldChildren[--oldEndIdx];
newEndVNode = newChildren[--newEndIdx];
} else if (oldStartVNode.key === newEndVNode.key) {
patch(oldStartVNode, newEndVNode, container);
insert(oldStartVNode.el, container, oldEndVNode.el.nextSibling);
oldStartVNode = oldChildren[++oldStartIdx];
newEndVNode = newChildren[--newEndIdx];
} else if (oldEndVNode.key === newStartVNode.key) {
patch(oldEndVNode, newStartVNode, container);
insert(oldEndVNode.el, container, oldStartVNode.el);
oldEndVNode = oldChildren[--oldEndIdx];
newStartVNode = newChildren[++newStartIdx];
} else {
const idxInOld = oldChildren.findIndex(
(node) => node.key === newStartVNode.key
);
if (idxInOld > 0) {
const vnodeToMove = oldChildren[idxInOld];
patch(vnodeToMove, newStartVNode, container);
insert(vnodeToMove.el, container, oldStartVNode.el);
oldChildren[idxInOld] = undefined;
} else {
patch(null, newStartVNode, container, oldStartVNode.el);
}
newStartVNode = newChildren[++newStartIdx];
}
}
if (oldEndIdx < oldStartIdx && newStartIdx <= newEndIdx) {
for (let i = newStartIdx; i <= newEndIdx; i++) {
patch(null, newChildren[i], container, oldStartVNode.el);
}
} else if (newEndIdx < newStartIdx && oldStartIdx <= oldEndIdx) {
for (let i = oldStartIdx; i <= oldEndIdx; i++) {
unmount(oldChildren[i]);
}
}
}
function patchElement(n1, n2) {
const el = (n2.el = n1.el);
const oldProps = n1.props;
const newProps = n2.props;
for (const key in newProps) {
if (newProps[key] !== oldProps[key]) {
patchProps(el, key, oldProps[key], newProps[key]);
}
}
for (const key in oldProps) {
if (!(key in newProps)) {
patchProps(el, key, oldProps[key], null);
}
}
patchChildren(n1, n2, el);
}
function unmount(vnode) {
if (vnode.type === Fragment) {
vnode.children.forEach((c) => unmount(c));
return;
}
const parent = vnode.el.parentNode;
if (parent) {
parent.removeChild(vnode.el);
}
}
function patch(n1, n2, container, anchor) {
if (n1 && n1.type !== n2.type) {
unmount(n1);
n1 = null;
}
const { type } = n2;
if (typeof type === "string") {
if (!n1) {
mountElement(n2, container, anchor);
} else {
patchElement(n1, n2);
}
} else if (type === Text) {
if (!n1) {
const el = (n2.el = createText(n2.children));
insert(el, container);
} else {
const el = (n2.el = n1.el);
if (n2.children !== n1.children) {
setText(el, n2.children);
}
}
} else if (type === Fragment) {
if (!n1) {
n2.children.forEach((c) => patch(null, c, container));
} else {
patchChildren(n1, n2, container);
}
}
}
function render(vnode, container) {
if (vnode) {
patch(container._vnode, vnode, container);
} else {
if (container._vnode) {
unmount(container._vnode);
}
}
container._vnode = vnode;
}
return {
render
};
}
const renderer = createRenderer({
createElement(tag) {
return document.createElement(tag);
},
setElementText(el, text) {
el.textContent = text;
},
insert(el, parent, anchor = null) {
parent.insertBefore(el, anchor);
},
createText(text) {
return document.createTextNode(text);
},
setText(el, text) {
el.nodeValue = text;
},
patchProps(el, key, prevValue, nextValue) {
if (/^on/.test(key)) {
const invokers = el._vei || (el._vei = {});
let invoker = invokers[key];
const name = key.slice(2).toLowerCase();
if (nextValue) {
if (!invoker) {
invoker = el._vei[key] = (e) => {
console.log(e.timeStamp);
console.log(invoker.attached);
if (e.timeStamp < invoker.attached) return;
if (Array.isArray(invoker.value)) {
invoker.value.forEach((fn) => fn(e));
} else {
invoker.value(e);
}
};
invoker.value = nextValue;
invoker.attached = performance.now();
el.addEventListener(name, invoker);
} else {
invoker.value = nextValue;
}
} else if (invoker) {
el.removeEventListener(name, invoker);
}
} else if (key === "class") {
el.className = nextValue || "";
} else if (shouldSetAsProps(el, key, nextValue)) {
const type = typeof el[key];
if (type === "boolean" && nextValue === "") {
el[key] = true;
} else {
el[key] = nextValue;
}
} else {
el.setAttribute(key, nextValue);
}
}
});
const Fragment = Symbol()
var VNode1 = {
type: "div",
children: []
};
var VNode2 = {
type: "div",
children: []
};
for (let i = 1; i <= 1000; i++) {
const childNode = {
type: "grid-item",
children: i.toString(),
key: i
};
VNode1.children.push(childNode);
}
renderer.render(VNode1, document.querySelector("#grid-container"));
| ready |