diff options
Diffstat (limited to 'thirdparty/preact/src/vdom/diff.js')
-rw-r--r-- | thirdparty/preact/src/vdom/diff.js | 254 |
1 files changed, 0 insertions, 254 deletions
diff --git a/thirdparty/preact/src/vdom/diff.js b/thirdparty/preact/src/vdom/diff.js deleted file mode 100644 index 794a79aaa..000000000 --- a/thirdparty/preact/src/vdom/diff.js +++ /dev/null @@ -1,254 +0,0 @@ -import { ATTR_KEY } from '../constants'; -import { isString, isFunction } from '../util'; -import { isSameNodeType, isNamedNode } from './index'; -import { isFunctionalComponent, buildFunctionalComponent } from './functional-component'; -import { buildComponentFromVNode } from './component'; -import { setAccessor } from '../dom/index'; -import { createNode, collectNode } from '../dom/recycler'; -import { unmountComponent } from './component'; -import options from '../options'; - - -/** Diff recursion count, used to track the end of the diff cycle. */ -export const mounts = []; - -/** Diff recursion count, used to track the end of the diff cycle. */ -export let diffLevel = 0; - -let isSvgMode = false; - - -export function flushMounts() { - let c; - while ((c=mounts.pop())) { - if (options.afterMount) options.afterMount(c); - if (c.componentDidMount) c.componentDidMount(); - } -} - - -/** Apply differences in a given vnode (and it's deep children) to a real DOM Node. - * @param {Element} [dom=null] A DOM node to mutate into the shape of the `vnode` - * @param {VNode} vnode A VNode (with descendants forming a tree) representing the desired DOM structure - * @returns {Element} dom The created/mutated element - * @private - */ -export function diff(dom, vnode, context, mountAll, parent, componentRoot) { - if (!diffLevel++) isSvgMode = parent instanceof SVGElement; - let ret = idiff(dom, vnode, context, mountAll); - if (parent && ret.parentNode!==parent) parent.appendChild(ret); - if (!--diffLevel && !componentRoot) flushMounts(); - return ret; -} - - -function idiff(dom, vnode, context, mountAll) { - let originalAttributes = vnode && vnode.attributes; - - while (isFunctionalComponent(vnode)) { - vnode = buildFunctionalComponent(vnode, context); - } - - if (vnode==null) vnode = ''; - - if (isString(vnode)) { - if (dom) { - if (dom instanceof Text && dom.parentNode) { - if (dom.nodeValue!=vnode) { - dom.nodeValue = vnode; - } - return dom; - } - recollectNodeTree(dom); - } - return document.createTextNode(vnode); - } - - if (isFunction(vnode.nodeName)) { - return buildComponentFromVNode(dom, vnode, context, mountAll); - } - - let out = dom, - nodeName = vnode.nodeName, - prevSvgMode = isSvgMode, - vchildren = vnode.children; - - if (!isString(nodeName)) { - nodeName = String(nodeName); - } - - isSvgMode = nodeName==='svg' ? true : nodeName==='foreignObject' ? false : isSvgMode; - - if (!dom) { - out = createNode(nodeName, isSvgMode); - } - else if (!isNamedNode(dom, nodeName)) { - out = createNode(nodeName, isSvgMode); - // move children into the replacement node - while (dom.firstChild) out.appendChild(dom.firstChild); - // reclaim element nodes - recollectNodeTree(dom); - } - - // fast-path for elements containing a single TextNode: - if (vchildren && vchildren.length===1 && typeof vchildren[0]==='string' && out.childNodes.length===1 && out.firstChild instanceof Text) { - if (out.firstChild.nodeValue!=vchildren[0]) { - out.firstChild.nodeValue = vchildren[0]; - } - } - else if (vchildren && vchildren.length || out.firstChild) { - innerDiffNode(out, vchildren, context, mountAll); - } - - let props = out[ATTR_KEY]; - if (!props) { - out[ATTR_KEY] = props = {}; - for (let a=out.attributes, i=a.length; i--; ) props[a[i].name] = a[i].value; - } - - diffAttributes(out, vnode.attributes, props); - - if (originalAttributes && typeof originalAttributes.ref==='function') { - (props.ref = originalAttributes.ref)(out); - } - - isSvgMode = prevSvgMode; - - return out; -} - - -/** Apply child and attribute changes between a VNode and a DOM Node to the DOM. */ -function innerDiffNode(dom, vchildren, context, mountAll) { - let originalChildren = dom.childNodes, - children = [], - keyed = {}, - keyedLen = 0, - min = 0, - len = originalChildren.length, - childrenLen = 0, - vlen = vchildren && vchildren.length, - j, c, vchild, child; - - if (len) { - for (let i=0; i<len; i++) { - let child = originalChildren[i], - key = vlen ? ((c = child._component) ? c.__key : (c = child[ATTR_KEY]) ? c.key : null) : null; - if (key || key===0) { - keyedLen++; - keyed[key] = child; - } - else { - children[childrenLen++] = child; - } - } - } - - if (vlen) { - for (let i=0; i<vlen; i++) { - vchild = vchildren[i]; - child = null; - - // if (isFunctionalComponent(vchild)) { - // vchild = buildFunctionalComponent(vchild); - // } - - // attempt to find a node based on key matching - let key = vchild.key; - if (key!=null) { - if (keyedLen && key in keyed) { - child = keyed[key]; - keyed[key] = undefined; - keyedLen--; - } - } - // attempt to pluck a node of the same type from the existing children - else if (!child && min<childrenLen) { - for (j=min; j<childrenLen; j++) { - c = children[j]; - if (c && isSameNodeType(c, vchild)) { - child = c; - children[j] = undefined; - if (j===childrenLen-1) childrenLen--; - if (j===min) min++; - break; - } - } - if (!child && min<childrenLen && isFunction(vchild.nodeName) && mountAll) { - child = children[min]; - children[min++] = undefined; - } - } - - // morph the matched/found/created DOM child to match vchild (deep) - child = idiff(child, vchild, context, mountAll); - - if (child && child!==dom && child!==originalChildren[i]) { - dom.insertBefore(child, originalChildren[i] || null); - } - } - } - - - if (keyedLen) { - for (let i in keyed) if (keyed[i]) recollectNodeTree(keyed[i]); - } - - // remove orphaned children - if (min<childrenLen) { - removeOrphanedChildren(children); - } -} - - -/** Reclaim children that were unreferenced in the desired VTree */ -export function removeOrphanedChildren(children, unmountOnly) { - for (let i=children.length; i--; ) { - if (children[i]) { - recollectNodeTree(children[i], unmountOnly); - } - } -} - - -/** Reclaim an entire tree of nodes, starting at the root. */ -export function recollectNodeTree(node, unmountOnly) { - // @TODO: Need to make a call on whether Preact should remove nodes not created by itself. - // Currently it *does* remove them. Discussion: https://github.com/developit/preact/issues/39 - //if (!node[ATTR_KEY]) return; - - let component = node._component; - if (component) { - unmountComponent(component, !unmountOnly); - } - else { - if (node[ATTR_KEY] && node[ATTR_KEY].ref) node[ATTR_KEY].ref(null); - - if (!unmountOnly) { - collectNode(node); - } - - if (node.childNodes && node.childNodes.length) { - removeOrphanedChildren(node.childNodes, unmountOnly); - } - } -} - - -/** Apply differences in attributes from a VNode to the given DOM Node. */ -function diffAttributes(dom, attrs, old) { - for (let name in old) { - if (!(attrs && name in attrs) && old[name]!=null) { - setAccessor(dom, name, old[name], old[name] = undefined, isSvgMode); - } - } - - // new & updated - if (attrs) { - for (let name in attrs) { - if (name!=='children' && name!=='innerHTML' && (!(name in old) || attrs[name]!==(name==='value' || name==='checked' ? dom[name] : old[name]))) { - setAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode); - } - } - } -} |