diff options
Diffstat (limited to 'thirdparty/preact/src/vdom')
-rw-r--r-- | thirdparty/preact/src/vdom/component-recycler.js | 32 | ||||
-rw-r--r-- | thirdparty/preact/src/vdom/component.js | 281 | ||||
-rw-r--r-- | thirdparty/preact/src/vdom/diff.js | 254 | ||||
-rw-r--r-- | thirdparty/preact/src/vdom/functional-component.js | 25 | ||||
-rw-r--r-- | thirdparty/preact/src/vdom/index.js | 49 |
5 files changed, 0 insertions, 641 deletions
diff --git a/thirdparty/preact/src/vdom/component-recycler.js b/thirdparty/preact/src/vdom/component-recycler.js deleted file mode 100644 index a70f0ece0..000000000 --- a/thirdparty/preact/src/vdom/component-recycler.js +++ /dev/null @@ -1,32 +0,0 @@ -import { Component } from '../component'; - -/** Retains a pool of Components for re-use, keyed on component name. - * Note: since component names are not unique or even necessarily available, these are primarily a form of sharding. - * @private - */ -const components = {}; - - -export function collectComponent(component) { - let name = component.constructor.name, - list = components[name]; - if (list) list.push(component); - else components[name] = [component]; -} - - -export function createComponent(Ctor, props, context) { - let inst = new Ctor(props, context), - list = components[Ctor.name]; - Component.call(inst, props, context); - if (list) { - for (let i=list.length; i--; ) { - if (list[i].constructor===Ctor) { - inst.nextBase = list[i].nextBase; - list.splice(i, 1); - break; - } - } - } - return inst; -} diff --git a/thirdparty/preact/src/vdom/component.js b/thirdparty/preact/src/vdom/component.js deleted file mode 100644 index 64e7ff81f..000000000 --- a/thirdparty/preact/src/vdom/component.js +++ /dev/null @@ -1,281 +0,0 @@ -import { SYNC_RENDER, NO_RENDER, FORCE_RENDER, ASYNC_RENDER, ATTR_KEY } from '../constants'; -import options from '../options'; -import { isFunction, clone, extend } from '../util'; -import { enqueueRender } from '../render-queue'; -import { getNodeProps } from './index'; -import { diff, mounts, diffLevel, flushMounts, removeOrphanedChildren, recollectNodeTree } from './diff'; -import { isFunctionalComponent, buildFunctionalComponent } from './functional-component'; -import { createComponent, collectComponent } from './component-recycler'; -import { removeNode } from '../dom/index'; - - - -/** Set a component's `props` (generally derived from JSX attributes). - * @param {Object} props - * @param {Object} [opts] - * @param {boolean} [opts.renderSync=false] If `true` and {@link options.syncComponentUpdates} is `true`, triggers synchronous rendering. - * @param {boolean} [opts.render=true] If `false`, no render will be triggered. - */ -export function setComponentProps(component, props, opts, context, mountAll) { - if (component._disable) return; - component._disable = true; - - if ((component.__ref = props.ref)) delete props.ref; - if ((component.__key = props.key)) delete props.key; - - if (!component.base || mountAll) { - if (component.componentWillMount) component.componentWillMount(); - } - else if (component.componentWillReceiveProps) { - component.componentWillReceiveProps(props, context); - } - - if (context && context!==component.context) { - if (!component.prevContext) component.prevContext = component.context; - component.context = context; - } - - if (!component.prevProps) component.prevProps = component.props; - component.props = props; - - component._disable = false; - - if (opts!==NO_RENDER) { - if (opts===SYNC_RENDER || options.syncComponentUpdates!==false || !component.base) { - renderComponent(component, SYNC_RENDER, mountAll); - } - else { - enqueueRender(component); - } - } - - if (component.__ref) component.__ref(component); -} - - - -/** Render a Component, triggering necessary lifecycle events and taking High-Order Components into account. - * @param {Component} component - * @param {Object} [opts] - * @param {boolean} [opts.build=false] If `true`, component will build and store a DOM node if not already associated with one. - * @private - */ -export function renderComponent(component, opts, mountAll, isChild) { - if (component._disable) return; - - let skip, rendered, - props = component.props, - state = component.state, - context = component.context, - previousProps = component.prevProps || props, - previousState = component.prevState || state, - previousContext = component.prevContext || context, - isUpdate = component.base, - nextBase = component.nextBase, - initialBase = isUpdate || nextBase, - initialChildComponent = component._component, - inst, cbase; - - // if updating - if (isUpdate) { - component.props = previousProps; - component.state = previousState; - component.context = previousContext; - if (opts!==FORCE_RENDER - && component.shouldComponentUpdate - && component.shouldComponentUpdate(props, state, context) === false) { - skip = true; - } - else if (component.componentWillUpdate) { - component.componentWillUpdate(props, state, context); - } - component.props = props; - component.state = state; - component.context = context; - } - - component.prevProps = component.prevState = component.prevContext = component.nextBase = null; - component._dirty = false; - - if (!skip) { - if (component.render) rendered = component.render(props, state, context); - - // context to pass to the child, can be updated via (grand-)parent component - if (component.getChildContext) { - context = extend(clone(context), component.getChildContext()); - } - - while (isFunctionalComponent(rendered)) { - rendered = buildFunctionalComponent(rendered, context); - } - - let childComponent = rendered && rendered.nodeName, - toUnmount, base; - - if (isFunction(childComponent)) { - // set up high order component link - - - inst = initialChildComponent; - let childProps = getNodeProps(rendered); - - if (inst && inst.constructor===childComponent) { - setComponentProps(inst, childProps, SYNC_RENDER, context); - } - else { - toUnmount = inst; - - inst = createComponent(childComponent, childProps, context); - inst.nextBase = inst.nextBase || nextBase; - inst._parentComponent = component; - component._component = inst; - setComponentProps(inst, childProps, NO_RENDER, context); - renderComponent(inst, SYNC_RENDER, mountAll, true); - } - - base = inst.base; - } - else { - cbase = initialBase; - - // destroy high order component link - toUnmount = initialChildComponent; - if (toUnmount) { - cbase = component._component = null; - } - - if (initialBase || opts===SYNC_RENDER) { - if (cbase) cbase._component = null; - base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, true); - } - } - - if (initialBase && base!==initialBase && inst!==initialChildComponent) { - let baseParent = initialBase.parentNode; - if (baseParent && base!==baseParent) { - baseParent.replaceChild(base, initialBase); - - if (!toUnmount) { - initialBase._component = null; - recollectNodeTree(initialBase); - } - } - } - - if (toUnmount) { - unmountComponent(toUnmount, base!==initialBase); - } - - component.base = base; - if (base && !isChild) { - let componentRef = component, - t = component; - while ((t=t._parentComponent)) { - (componentRef = t).base = base; - } - base._component = componentRef; - base._componentConstructor = componentRef.constructor; - } - } - - if (!isUpdate || mountAll) { - mounts.unshift(component); - } - else if (!skip) { - if (component.componentDidUpdate) { - component.componentDidUpdate(previousProps, previousState, previousContext); - } - if (options.afterUpdate) options.afterUpdate(component); - } - - let cb = component._renderCallbacks, fn; - if (cb) while ( (fn = cb.pop()) ) fn.call(component); - - if (!diffLevel && !isChild) flushMounts(); -} - - - -/** Apply the Component referenced by a VNode to the DOM. - * @param {Element} dom The DOM node to mutate - * @param {VNode} vnode A Component-referencing VNode - * @returns {Element} dom The created/mutated element - * @private - */ -export function buildComponentFromVNode(dom, vnode, context, mountAll) { - let c = dom && dom._component, - oldDom = dom, - isDirectOwner = c && dom._componentConstructor===vnode.nodeName, - isOwner = isDirectOwner, - props = getNodeProps(vnode); - while (c && !isOwner && (c=c._parentComponent)) { - isOwner = c.constructor===vnode.nodeName; - } - - if (c && isOwner && (!mountAll || c._component)) { - setComponentProps(c, props, ASYNC_RENDER, context, mountAll); - dom = c.base; - } - else { - if (c && !isDirectOwner) { - unmountComponent(c, true); - dom = oldDom = null; - } - - c = createComponent(vnode.nodeName, props, context); - if (dom && !c.nextBase) { - c.nextBase = dom; - // passing dom/oldDom as nextBase will recycle it if unused, so bypass recycling on L241: - oldDom = null; - } - setComponentProps(c, props, SYNC_RENDER, context, mountAll); - dom = c.base; - - if (oldDom && dom!==oldDom) { - oldDom._component = null; - recollectNodeTree(oldDom); - } - } - - return dom; -} - - - -/** Remove a component from the DOM and recycle it. - * @param {Element} dom A DOM node from which to unmount the given Component - * @param {Component} component The Component instance to unmount - * @private - */ -export function unmountComponent(component, remove) { - if (options.beforeUnmount) options.beforeUnmount(component); - - // console.log(`${remove?'Removing':'Unmounting'} component: ${component.constructor.name}`); - let base = component.base; - - component._disable = true; - - if (component.componentWillUnmount) component.componentWillUnmount(); - - component.base = null; - - // recursively tear down & recollect high-order component children: - let inner = component._component; - if (inner) { - unmountComponent(inner, remove); - } - else if (base) { - if (base[ATTR_KEY] && base[ATTR_KEY].ref) base[ATTR_KEY].ref(null); - - component.nextBase = base; - - if (remove) { - removeNode(base); - collectComponent(component); - } - removeOrphanedChildren(base.childNodes, !remove); - } - - if (component.__ref) component.__ref(null); - if (component.componentDidUnmount) component.componentDidUnmount(); -} 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); - } - } - } -} diff --git a/thirdparty/preact/src/vdom/functional-component.js b/thirdparty/preact/src/vdom/functional-component.js deleted file mode 100644 index 04bc5a464..000000000 --- a/thirdparty/preact/src/vdom/functional-component.js +++ /dev/null @@ -1,25 +0,0 @@ -import { EMPTY } from '../constants'; -import { getNodeProps } from './index'; -import { isFunction } from '../util'; - - -/** Check if a VNode is a reference to a stateless functional component. - * A function component is represented as a VNode whose `nodeName` property is a reference to a function. - * If that function is not a Component (ie, has no `.render()` method on a prototype), it is considered a stateless functional component. - * @param {VNode} vnode A VNode - * @private - */ -export function isFunctionalComponent(vnode) { - let nodeName = vnode && vnode.nodeName; - return nodeName && isFunction(nodeName) && !(nodeName.prototype && nodeName.prototype.render); -} - - - -/** Construct a resultant VNode from a VNode referencing a stateless functional component. - * @param {VNode} vnode A VNode with a `nodeName` property that is a reference to a function. - * @private - */ -export function buildFunctionalComponent(vnode, context) { - return vnode.nodeName(getNodeProps(vnode), context || EMPTY); -} diff --git a/thirdparty/preact/src/vdom/index.js b/thirdparty/preact/src/vdom/index.js deleted file mode 100644 index f59fbae21..000000000 --- a/thirdparty/preact/src/vdom/index.js +++ /dev/null @@ -1,49 +0,0 @@ -import { clone, isString, isFunction, toLowerCase } from '../util'; -import { isFunctionalComponent } from './functional-component'; - - -/** Check if two nodes are equivalent. - * @param {Element} node - * @param {VNode} vnode - * @private - */ -export function isSameNodeType(node, vnode) { - if (isString(vnode)) { - return node instanceof Text; - } - if (isString(vnode.nodeName)) { - return isNamedNode(node, vnode.nodeName); - } - if (isFunction(vnode.nodeName)) { - return node._componentConstructor===vnode.nodeName || isFunctionalComponent(vnode); - } -} - - -export function isNamedNode(node, nodeName) { - return node.normalizedNodeName===nodeName || toLowerCase(node.nodeName)===toLowerCase(nodeName); -} - - -/** - * Reconstruct Component-style `props` from a VNode. - * Ensures default/fallback values from `defaultProps`: - * Own-properties of `defaultProps` not present in `vnode.attributes` are added. - * @param {VNode} vnode - * @returns {Object} props - */ -export function getNodeProps(vnode) { - let props = clone(vnode.attributes); - props.children = vnode.children; - - let defaultProps = vnode.nodeName.defaultProps; - if (defaultProps) { - for (let i in defaultProps) { - if (props[i]===undefined) { - props[i] = defaultProps[i]; - } - } - } - - return props; -} |