Untitled diff

Created Diff never expires
44 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
797 lines
45 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
798 lines
/** Virtual DOM Node */
/** Virtual DOM Node */
function VNode() {}
function VNode() {}


/** Global options
/** Global options
* @public
* @public
* @namespace options {Object}
* @namespace options {Object}
*/
*/
var options = {
var options = {


/** If `true`, `prop` changes trigger synchronous component updates.
/** If `true`, `prop` changes trigger synchronous component updates.
* @name syncComponentUpdates
* @name syncComponentUpdates
* @type Boolean
* @type Boolean
* @default true
* @default true
*/
*/
//syncComponentUpdates: true,
//syncComponentUpdates: true,


/** Processes all created VNodes.
/** Processes all created VNodes.
* @param {VNode} vnode A newly-created VNode to normalize/process
* @param {VNode} vnode A newly-created VNode to normalize/process
*/
*/
//vnode(vnode) { }
//vnode(vnode) { }


/** Hook invoked after a component is mounted. */
/** Hook invoked after a component is mounted. */
// afterMount(component) { }
// afterMount(component) { }


/** Hook invoked after the DOM is updated with a component's latest render. */
/** Hook invoked after the DOM is updated with a component's latest render. */
// afterUpdate(component) { }
// afterUpdate(component) { }


/** Hook invoked immediately before a component is unmounted. */
/** Hook invoked immediately before a component is unmounted. */
// beforeUnmount(component) { }
// beforeUnmount(component) { }
};
};


var stack = [];
var stack = [];


var EMPTY_CHILDREN = [];
var EMPTY_CHILDREN = [];


/** JSX/hyperscript reviver
/** JSX/hyperscript reviver
* Benchmarks: https://esbench.com/bench/57ee8f8e330ab09900a1a1a0
* Benchmarks: https://esbench.com/bench/57ee8f8e330ab09900a1a1a0
* @see http://jasonformat.com/wtf-is-jsx
* @see http://jasonformat.com/wtf-is-jsx
* @public
* @public
*/
*/
function h(nodeName, attributes) {
function h(nodeName, attributes) {
var children = EMPTY_CHILDREN,
var children = EMPTY_CHILDREN,
lastSimple = void 0,
lastSimple,
child = void 0,
child,
simple = void 0,
simple,
i = void 0;
i;
for (i = arguments.length; i-- > 2;) {
for (i = arguments.length; i-- > 2;) {
stack.push(arguments[i]);
stack.push(arguments[i]);
}
}
if (attributes && attributes.children != null) {
if (attributes && attributes.children != null) {
if (!stack.length) stack.push(attributes.children);
if (!stack.length) stack.push(attributes.children);
delete attributes.children;
delete attributes.children;
}
}
while (stack.length) {
while (stack.length) {
if ((child = stack.pop()) && child.pop !== undefined) {
if ((child = stack.pop()) && child.pop !== undefined) {
for (i = child.length; i--;) {
for (i = child.length; i--;) {
stack.push(child[i]);
stack.push(child[i]);
}
}
} else {
} else {
if (typeof child === 'boolean') child = null;
if (typeof child === 'boolean') child = null;


if (simple = typeof nodeName !== 'function') {
if (simple = typeof nodeName !== 'function') {
if (child == null) child = '';else if (typeof child === 'number') child = String(child);else if (typeof child !== 'string') simple = false;
if (child == null) child = '';else if (typeof child === 'number') child = String(child);else if (typeof child !== 'string') simple = false;
}
}


if (simple && lastSimple) {
if (simple && lastSimple) {
children[children.length - 1] += child;
children[children.length - 1] += child;
} else if (children === EMPTY_CHILDREN) {
} else if (children === EMPTY_CHILDREN) {
children = [child];
children = [child];
} else {
} else {
children.push(child);
children.push(child);
}
}


lastSimple = simple;
lastSimple = simple;
}
}
}
}


var p = new VNode();
var p = new VNode();
p.nodeName = nodeName;
p.nodeName = nodeName;
p.children = children;
p.children = children;
p.attributes = attributes == null ? undefined : attributes;
p.attributes = attributes == null ? undefined : attributes;
p.key = attributes == null ? undefined : attributes.key;
p.key = attributes == null ? undefined : attributes.key;


// if a "vnode hook" is defined, pass every created VNode to it
// if a "vnode hook" is defined, pass every created VNode to it
if (options.vnode !== undefined) options.vnode(p);
if (options.vnode !== undefined) options.vnode(p);


return p;
return p;
}
}


/** Copy own-properties from `props` onto `obj`.
/** Copy own-properties from `props` onto `obj`.
* @returns obj
* @returns obj
* @private
* @private
*/
*/
function extend(obj, props) {
function extend(obj, props) {
for (var i in props) {
for (var i in props) {
obj[i] = props[i];
obj[i] = props[i];
}return obj;
}return obj;
}
}


/** Call a function asynchronously, as soon as possible.
/** Call a function asynchronously, as soon as possible.
* @param {Function} callback
* @param {Function} callback
*/
*/
var defer = typeof Promise == 'function' ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout;
var defer = typeof Promise == 'function' ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout;


function cloneElement(vnode, props) {
function cloneElement(vnode, props) {
return h(vnode.nodeName, extend(extend({}, vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children);
return h(vnode.nodeName, extend(extend({}, vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children);
}
}


// render modes

var NO_RENDER = 0;
var SYNC_RENDER = 1;
var FORCE_RENDER = 2;
var ASYNC_RENDER = 3;

var ATTR_KEY = '__preactattr_';

// DOM properties that should NOT have "px" added when numeric
// DOM properties that should NOT have "px" added when numeric
var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;
var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;


/** Managed queue of dirty components to be re-rendered */
/** Managed queue of dirty components to be re-rendered */


var items = [];
var items = [];


function enqueueRender(component) {
function enqueueRender(component) {
if (!component._dirty && (component._dirty = true) && items.push(component) == 1) {
if (!component._dirty && (component._dirty = true) && items.push(component) == 1) {
(options.debounceRendering || defer)(rerender);
(options.debounceRendering || defer)(rerender);
}
}
}
}


function rerender() {
function rerender() {
var p = void 0,
var p,
list = items;
list = items;
items = [];
items = [];
while (p = list.pop()) {
while (p = list.pop()) {
if (p._dirty) renderComponent(p);
if (p._dirty) renderComponent(p);
}
}
}
}


/** Check if two nodes are equivalent.
/** Check if two nodes are equivalent.
* @param {Element} node
* @param {Element} node
* @param {VNode} vnode
* @param {VNode} vnode
* @private
* @private
*/
*/
function isSameNodeType(node, vnode, hydrating) {
function isSameNodeType(node, vnode, hydrating) {
if (typeof vnode === 'string' || typeof vnode === 'number') {
if (typeof vnode === 'string' || typeof vnode === 'number') {
return node.splitText !== undefined;
return node.splitText !== undefined;
}
}
if (typeof vnode.nodeName === 'string') {
if (typeof vnode.nodeName === 'string') {
return !node._componentConstructor && isNamedNode(node, vnode.nodeName);
return !node._componentConstructor && isNamedNode(node, vnode.nodeName);
}
}
return hydrating || node._componentConstructor === vnode.nodeName;
return hydrating || node._componentConstructor === vnode.nodeName;
}
}


/** Check if an Element has a given normalized name.
/** Check if an Element has a given normalized name.
* @param {Element} node
* @param {Element} node
* @param {String} nodeName
* @param {String} nodeName
*/
*/
function isNamedNode(node, nodeName) {
function isNamedNode(node, nodeName) {
return node.normalizedNodeName === nodeName || node.nodeName.toLowerCase() === nodeName.toLowerCase();
return node.normalizedNodeName === nodeName || node.nodeName.toLowerCase() === nodeName.toLowerCase();
}
}


/**
/**
* Reconstruct Component-style `props` from a VNode.
* Reconstruct Component-style `props` from a VNode.
* Ensures default/fallback values from `defaultProps`:
* Ensures default/fallback values from `defaultProps`:
* Own-properties of `defaultProps` not present in `vnode.attributes` are added.
* Own-properties of `defaultProps` not present in `vnode.attributes` are added.
* @param {VNode} vnode
* @param {VNode} vnode
* @returns {Object} props
* @returns {Object} props
*/
*/
function getNodeProps(vnode) {
function getNodeProps(vnode) {
var props = extend({}, vnode.attributes);
var props = extend({}, vnode.attributes);
props.children = vnode.children;
props.children = vnode.children;


var defaultProps = vnode.nodeName.defaultProps;
var defaultProps = vnode.nodeName.defaultProps;
if (defaultProps !== undefined) {
if (defaultProps !== undefined) {
for (var i in defaultProps) {
for (var i in defaultProps) {
if (props[i] === undefined) {
if (props[i] === undefined) {
props[i] = defaultProps[i];
props[i] = defaultProps[i];
}
}
}
}
}
}


return props;
return props;
}
}


/** Create an element with the given nodeName.
/** Create an element with the given nodeName.
* @param {String} nodeName
* @param {String} nodeName
* @param {Boolean} [isSvg=false] If `true`, creates an element within the SVG namespace.
* @param {Boolean} [isSvg=false] If `true`, creates an element within the SVG namespace.
* @returns {Element} node
* @returns {Element} node
*/
*/
function createNode(nodeName, isSvg) {
function createNode(nodeName, isSvg) {
var node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName);
var node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName);
node.normalizedNodeName = nodeName;
node.normalizedNodeName = nodeName;
return node;
return node;
}
}


/** Remove a child node from its parent if attached.
/** Remove a child node from its parent if attached.
* @param {Element} node The node to remove
* @param {Element} node The node to remove
*/
*/
function removeNode(node) {
function removeNode(node) {
var parentNode = node.parentNode;
var parentNode = node.parentNode;
if (parentNode) parentNode.removeChild(node);
if (parentNode) parentNode.removeChild(node);
}
}


/** Set a named attribute on the given Node, with special behavior for some names and event handlers.
/** Set a named attribute on the given Node, with special behavior for some names and event handlers.
* If `value` is `null`, the attribute/handler will be removed.
* If `value` is `null`, the attribute/handler will be removed.
* @param {Element} node An element to mutate
* @param {Element} node An element to mutate
* @param {string} name The name/key to set, such as an event or attribute name
* @param {string} name The name/key to set, such as an event or attribute name
* @param {any} old The last value that was set for this name/node pair
* @param {any} old The last value that was set for this name/node pair
* @param {any} value An attribute value, such as a function to be used as an event handler
* @param {any} value An attribute value, such as a function to be used as an event handler
* @param {Boolean} isSvg Are we currently diffing inside an svg?
* @param {Boolean} isSvg Are we currently diffing inside an svg?
* @private
* @private
*/
*/
function setAccessor(node, name, old, value, isSvg) {
function setAccessor(node, name, old, value, isSvg) {
if (name === 'className') name = 'class';
if (name === 'className') name = 'class';


if (name === 'key') {
if (name === 'key') {
// ignore
// ignore
} else if (name === 'ref') {
} else if (name === 'ref') {
if (old) old(null);
if (old) old(null);
if (value) value(node);
if (value) value(node);
} else if (name === 'class' && !isSvg) {
} else if (name === 'class' && !isSvg) {
node.className = value || '';
node.className = value || '';
} else if (name === 'style') {
} else if (name === 'style') {
if (!value || typeof value === 'string' || typeof old === 'string') {
if (!value || typeof value === 'string' || typeof old === 'string') {
node.style.cssText = value || '';
node.style.cssText = value || '';
}
}
if (value && typeof value === 'object') {
if (value && typeof value === 'object') {
if (typeof old !== 'string') {
if (typeof old !== 'string') {
for (var i in old) {
for (var i in old) {
if (!(i in value)) node.style[i] = '';
if (!(i in value)) node.style[i] = '';
}
}
}
}
for (var _i in value) {
for (var _i in value) {
node.style[_i] = typeof value[_i] === 'number' && IS_NON_DIMENSIONAL.test(_i) === false ? value[_i] + 'px' : value[_i];
node.style[_i] = typeof value[_i] === 'number' && IS_NON_DIMENSIONAL.test(_i) === false ? value[_i] + 'px' : value[_i];
}
}
}
}
} else if (name === 'dangerouslySetInnerHTML') {
} else if (name === 'dangerouslySetInnerHTML') {
if (value) node.innerHTML = value.__html || '';
if (value) node.innerHTML = value.__html || '';
} else if (name[0] == 'o' && name[1] == 'n') {
} else if (name[0] == 'o' && name[1] == 'n') {
var useCapture = name !== (name = name.replace(/Capture$/, ''));
var useCapture = name !== (name = name.replace(/Capture$/, ''));
name = name.toLowerCase().substring(2);
name = name.toLowerCase().substring(2);
if (value) {
if (value) {
if (!old) node.addEventListener(name, eventProxy, useCapture);
if (!old) node.addEventListener(name, eventProxy, useCapture);
} else {
} else {
node.removeEventListener(name, eventProxy, useCapture);
node.removeEventListener(name, eventProxy, useCapture);
}
}
(node._listeners || (node._listeners = {}))[name] = value;
(node._listeners || (node._listeners = {}))[name] = value;
} else if (name !== 'list' && name !== 'type' && !isSvg && name in node) {
} else if (name !== 'list' && name !== 'type' && !isSvg && name in node) {
setProperty(node, name, value == null ? '' : value);
setProperty(node, name, value == null ? '' : value);
if (value == null || value === false) node.removeAttribute(name);
if (value == null || value === false) node.removeAttribute(name);
} else {
} else {
var ns = isSvg && name !== (name = name.replace(/^xlink\:?/, ''));
var ns = isSvg && name !== (name = name.replace(/^xlink\:?/, ''));
if (value == null || value === false) {
if (value == null || value === false) {
if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());else node.removeAttribute(name);
if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());else node.removeAttribute(name);
} else if (typeof value !== 'function') {
} else if (typeof value !== 'function') {
if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);else node.setAttribute(name, value);
if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);else node.setAttribute(name, value);
}
}
}
}
}
}


/** Attempt to set a DOM property to the given value.
/** Attempt to set a DOM property to the given value.
* IE & FF throw for certain property-value combinations.
* IE & FF throw for certain property-value combinations.
*/
*/
function setProperty(node, name, value) {
function setProperty(node, name, value) {
try {
try {
node[name] = value;
node[name] = value;
} catch (e) {}
} catch (e) {}
}
}


/** Proxy an event to hooked event handlers
/** Proxy an event to hooked event handlers
* @private
* @private
*/
*/
function eventProxy(e) {
function eventProxy(e) {
return this._listeners[e.type](options.event && options.event(e) || e);
return this._listeners[e.type](options.event && options.event(e) || e);
}
}


/** Queue of components that have been mounted and are awaiting componentDidMount */
/** Queue of components that have been mounted and are awaiting componentDidMount */
var mounts = [];
var mounts = [];


/** Diff recursion count, used to track the end of the diff cycle. */
/** Diff recursion count, used to track the end of the diff cycle. */
var diffLevel = 0;
var diffLevel = 0;


/** Global flag indicating if the diff is currently within an SVG */
/** Global flag indicating if the diff is currently within an SVG */
var isSvgMode = false;
var isSvgMode = false;


/** Global flag indicating if the diff is performing hydration */
/** Global flag indicating if the diff is performing hydration */
var hydrating = false;
var hydrating = false;


/** Invoke queued componentDidMount lifecycle methods */
/** Invoke queued componentDidMount lifecycle methods */
function flushMounts() {
function flushMounts() {
var c = void 0;
var c;
while (c = mounts.pop()) {
while (c = mounts.pop()) {
if (options.afterMount) options.afterMount(c);
if (options.afterMount) options.afterMount(c);
if (c.componentDidMount) c.componentDidMount();
if (c.componentDidMount) c.componentDidMount();
}
}
}
}


/** Apply differences in a given vnode (and it's deep children) to a real DOM Node.
/** 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 {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
* @param {VNode} vnode A VNode (with descendants forming a tree) representing the desired DOM structure
* @returns {Element} dom The created/mutated element
* @returns {Element} dom The created/mutated element
* @private
* @private
*/
*/
function diff(dom, vnode, context, mountAll, parent, componentRoot) {
function diff(dom, vnode, context, mountAll, parent, componentRoot) {
// diffLevel having been 0 here indicates initial entry into the diff (not a subdiff)
// diffLevel having been 0 here indicates initial entry into the diff (not a subdiff)
if (!diffLevel++) {
if (!diffLevel++) {
// when first starting the diff, check if we're diffing an SVG or within an SVG
// when first starting the diff, check if we're diffing an SVG or within an SVG
isSvgMode = parent != null && parent.ownerSVGElement !== undefined;
isSvgMode = parent != null && parent.ownerSVGElement !== undefined;


// hydration is indicated by the existing element to be diffed not having a prop cache
// hydration is indicated by the existing element to be diffed not having a prop cache
hydrating = dom != null && !(ATTR_KEY in dom);
hydrating = dom != null && !('__preactattr_' in dom);
}
}


var ret = idiff(dom, vnode, context, mountAll, componentRoot);
var ret = idiff(dom, vnode, context, mountAll, componentRoot);


// append the element if its a new parent
// append the element if its a new parent
if (parent && ret.parentNode !== parent) parent.appendChild(ret);
if (parent && ret.parentNode !== parent) parent.appendChild(ret);


// diffLevel being reduced to 0 means we're exiting the diff
// diffLevel being reduced to 0 means we're exiting the diff
if (! --diffLevel) {
if (! --diffLevel) {
hydrating = false;
hydrating = false;
// invoke queued componentDidMount lifecycle methods
// invoke queued componentDidMount lifecycle methods
if (!componentRoot) flushMounts();
if (!componentRoot) flushMounts();
}
}


return ret;
return ret;
}
}


/** Internals of `diff()`, separated to allow bypassing diffLevel / mount flushing. */
/** Internals of `diff()`, separated to allow bypassing diffLevel / mount flushing. */
function idiff(dom, vnode, context, mountAll, componentRoot) {
function idiff(dom, vnode, context, mountAll, componentRoot) {
var out = dom,
var out = dom,
prevSvgMode = isSvgMode;
prevSvgMode = isSvgMode;


// empty values (null, undefined, booleans) render as empty Text nodes
// empty values (null, undefined, booleans) render as empty Text nodes
if (vnode == null || typeof vnode === 'boolean') vnode = '';
if (vnode == null || typeof vnode === 'boolean') vnode = '';


// Fast case: Strings & Numbers create/update Text nodes.
// Fast case: Strings & Numbers create/update Text nodes.
if (typeof vnode === 'string' || typeof vnode === 'number') {
if (typeof vnode === 'string' || typeof vnode === 'number') {


// update if it's already a Text node:
// update if it's already a Text node:
if (dom && dom.splitText !== undefined && dom.parentNode && (!dom._component || componentRoot)) {
if (dom && dom.splitText !== undefined && dom.parentNode && (!dom._component || componentRoot)) {
/* istanbul ignore if */ /* Browser quirk that can't be covered: https://github.com/developit/preact/commit/fd4f21f5c45dfd75151bd27b4c217d8003aa5eb9 */
/* istanbul ignore if */ /* Browser quirk that can't be covered: https://github.com/developit/preact/commit/fd4f21f5c45dfd75151bd27b4c217d8003aa5eb9 */
if (dom.nodeValue != vnode) {
if (dom.nodeValue != vnode) {
dom.nodeValue = vnode;
dom.nodeValue = vnode;
}
}
} else {
} else {
// it wasn't a Text node: replace it with one and recycle the old Element
// it wasn't a Text node: replace it with one and recycle the old Element
out = document.createTextNode(vnode);
out = document.createTextNode(vnode);
if (dom) {
if (dom) {
if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
recollectNodeTree(dom, true);
recollectNodeTree(dom, true);
}
}
}
}


out[ATTR_KEY] = true;
out['__preactattr_'] = true;


return out;
return out;
}
}


// If the VNode represents a Component, perform a component diff:
// If the VNode represents a Component, perform a component diff:
var vnodeName = vnode.nodeName;
var vnodeName = vnode.nodeName;
if (typeof vnodeName === 'function') {
if (typeof vnodeName === 'function') {
return buildComponentFromVNode(dom, vnode, context, mountAll);
return buildComponentFromVNode(dom, vnode, context, mountAll);
}
}


// Tracks entering and exiting SVG namespace when descending through the tree.
// Tracks entering and exiting SVG namespace when descending through the tree.
isSvgMode = vnodeName === 'svg' ? true : vnodeName === 'foreignObject' ? false : isSvgMode;
isSvgMode = vnodeName === 'svg' ? true : vnodeName === 'foreignObject' ? false : isSvgMode;


// If there's no existing element or it's the wrong type, create a new one:
// If there's no existing element or it's the wrong type, create a new one:
vnodeName = String(vnodeName);
vnodeName = String(vnodeName);
if (!dom || !isNamedNode(dom, vnodeName)) {
if (!dom || !isNamedNode(dom, vnodeName)) {
out = createNode(vnodeName, isSvgMode);
out = createNode(vnodeName, isSvgMode);


if (dom) {
if (dom) {
// move children into the replacement node
// move children into the replacement node
while (dom.firstChild) {
while (dom.firstChild) {
out.appendChild(dom.firstChild);
out.appendChild(dom.firstChild);
} // if the previous Element was mounted into the DOM, replace it inline
} // if the previous Element was mounted into the DOM, replace it inline
if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
if (dom.parentNode) dom.parentNode.replaceChild(out, dom);


// recycle the old element (skips non-Element node types)
// recycle the old element (skips non-Element node types)
recollectNodeTree(dom, true);
recollectNodeTree(dom, true);
}
}
}
}


var fc = out.firstChild,
var fc = out.firstChild,
props = out[ATTR_KEY],
props = out['__preactattr_'],
vchildren = vnode.children;
vchildren = vnode.children;


if (props == null) {
if (props == null) {
props = out[ATTR_KEY] = {};
props = out['__preactattr_'] = {};
for (var a = out.attributes, i = a.length; i--;) {
for (var a = out.attributes, i = a.length; i--;) {
props[a[i].name] = a[i].value;
props[a[i].name] = a[i].value;
}
}
}
}


// Optimization: fast-path for elements containing a single TextNode:
// Optimization: fast-path for elements containing a single TextNode:
if (!hydrating && vchildren && vchildren.length === 1 && typeof vchildren[0] === 'string' && fc != null && fc.splitText !== undefined && fc.nextSibling == null) {
if (!hydrating && vchildren && vchildren.length === 1 && typeof vchildren[0] === 'string' && fc != null && fc.splitText !== undefined && fc.nextSibling == null) {
if (fc.nodeValue != vchildren[0]) {
if (fc.nodeValue != vchildren[0]) {
fc.nodeValue = vchildren[0];
fc.nodeValue = vchildren[0];
}
}
}
}
// otherwise, if there are existing or new children, diff them:
// otherwise, if there are existing or new children, diff them:
else if (vchildren && vchildren.length || fc != null) {
else if (vchildren && vchildren.length || fc != null) {
innerDiffNode(out, vchildren, context, mountAll, hydrating || props.dangerouslySetInnerHTML != null);
innerDiffNode(out, vchildren, context, mountAll, hydrating || props.dangerouslySetInnerHTML != null);
}
}


// Apply attributes/props from VNode to the DOM Element:
// Apply attributes/props from VNode to the DOM Element:
diffAttributes(out, vnode.attributes, props);
diffAttributes(out, vnode.attributes, props);


// restore previous SVG mode: (in case we're exiting an SVG namespace)
// restore previous SVG mode: (in case we're exiting an SVG namespace)
isSvgMode = prevSvgMode;
isSvgMode = prevSvgMode;


return out;
return out;
}
}


/** Apply child and attribute changes between a VNode and a DOM Node to the DOM.
/** Apply child and attribute changes between a VNode and a DOM Node to the DOM.
* @param {Element} dom Element whose children should be compared & mutated
* @param {Element} dom Element whose children should be compared & mutated
* @param {Array} vchildren Array of VNodes to compare to `dom.childNodes`
* @param {Array} vchildren Array of VNodes to compare to `dom.childNodes`
* @param {Object} context Implicitly descendant context object (from most recent `getChildContext()`)
* @param {Object} context Implicitly descendant context object (from most recent `getChildContext()`)
* @param {Boolean} mountAll
* @param {Boolean} mountAll
* @param {Boolean} isHydrating If `true`, consumes externally created elements similar to hydration
* @param {Boolean} isHydrating If `true`, consumes externally created elements similar to hydration
*/
*/
function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {
function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {
var originalChildren = dom.childNodes,
var originalChildren = dom.childNodes,
children = [],
children = [],
keyed = {},
keyed = {},
keyedLen = 0,
keyedLen = 0,
min = 0,
min = 0,
len = originalChildren.length,
len = originalChildren.length,
childrenLen = 0,
childrenLen = 0,
vlen = vchildren ? vchildren.length : 0,
vlen = vchildren ? vchildren.length : 0,
j = void 0,
j,
c = void 0,
c,
f = void 0,
f,
vchild = void 0,
vchild,
child = void 0;
child;


// Build up a map of keyed children and an Array of unkeyed children:
// Build up a map of keyed children and an Array of unkeyed children:
if (len !== 0) {
if (len !== 0) {
for (var i = 0; i < len; i++) {
for (var i = 0; i < len; i++) {
var _child = originalChildren[i],
var _child = originalChildren[i],
props = _child[ATTR_KEY],
props = _child['__preactattr_'],
key = vlen && props ? _child._component ? _child._component.__key : props.key : null;
key = vlen && props ? _child._component ? _child._component.__key : props.key : null;
if (key != null) {
if (key != null) {
keyedLen++;
keyedLen++;
keyed[key] = _child;
keyed[key] = _child;
} else if (props || (_child.splitText !== undefined ? isHydrating ? _child.nodeValue.trim() : true : isHydrating)) {
} else if (props || (_child.splitText !== undefined ? isHydrating ? _child.nodeValue.trim() : true : isHydrating)) {
children[childrenLen++] = _child;
children[childrenLen++] = _child;
}
}
}
}
}
}


if (vlen !== 0) {
if (vlen !== 0) {
for (var _i = 0; _i < vlen; _i++) {
for (var _i = 0; _i < vlen; _i++) {
vchild = vchildren[_i];
vchild = vchildren[_i];
child = null;
child = null;


// attempt to find a node based on key matching
// attempt to find a node based on key matching
var _key = vchild.key;
var _key = vchild.key;
if (_key != null) {
if (_key != null) {
if (keyedLen && keyed[_key] !== undefined) {
if (keyedLen && keyed[_key] !== undefined) {
child = keyed[_key];
child = keyed[_key];
keyed[_key] = undefined;
keyed[_key] = undefined;
keyedLen--;
keyedLen--;
}
}
}
}
// attempt to pluck a node of the same type from the existing children
// attempt to pluck a node of the same type from the existing children
else if (!child && min < childrenLen) {
else if (!child && min < childrenLen) {
for (j = min; j < childrenLen; j++) {
for (j = min; j < childrenLen; j++) {
if (children[j] !== undefined && isSameNodeType(c = children[j], vchild, isHydrating)) {
if (children[j] !== undefined && isSameNodeType(c = children[j], vchild, isHydrating)) {
child = c;
child = c;
children[j] = undefined;
children[j] = undefined;
if (j === childrenLen - 1) childrenLen--;
if (j === childrenLen - 1) childrenLen--;
if (j === min) min++;
if (j === min) min++;
break;
break;
}
}
}
}
}
}


// morph the matched/found/created DOM child to match vchild (deep)
// morph the matched/found/created DOM child to match vchild (deep)
child = idiff(child, vchild, context, mountAll);
child = idiff(child, vchild, context, mountAll);


f = originalChildren[_i];
f = originalChildren[_i];
if (child && child !== dom && child !== f) {
if (child && child !== dom && child !== f) {
if (f == null) {
if (f == null) {
dom.appendChild(child);
dom.appendChild(child);
} else if (child === f.nextSibling) {
} else if (child === f.nextSibling) {
removeNode(f);
removeNode(f);
} else {
} else {
dom.insertBefore(child, f);
dom.insertBefore(child, f);
}
}
}
}
}
}
}
}


// remove unused keyed children:
// remove unused keyed children:
if (keyedLen) {
if (keyedLen) {
for (var _i2 in keyed) {
for (var _i2 in keyed) {
if (keyed[_i2] !== undefined) recollectNodeTree(keyed[_i2], false);
if (keyed[_i2] !== undefined) recollectNodeTree(keyed[_i2], false);
}
}
}
}


// remove orphaned unkeyed children:
// remove orphaned unkeyed children:
while (min <= childrenLen) {
while (min <= childrenLen) {
if ((child = children[childrenLen--]) !== undefined) recollectNodeTree(child, false);
if ((child = children[childrenLen--]) !== undefined) recollectNodeTree(child, false);
}
}
}
}


/** Recursively recycle (or just unmount) a node an its descendants.
/** Recursively recycle (or just unmount) a node an its descendants.
* @param {Node} node DOM node to start unmount/removal from
* @param {Node} node DOM node to start unmount/removal from
* @param {Boolean} [unmountOnly=false] If `true`, only triggers unmount lifecycle, skips removal
* @param {Boolean} [unmountOnly=false] If `true`, only triggers unmount lifecycle, skips removal
*/
*/
function recollectNodeTree(node, unmountOnly) {
function recollectNodeTree(node, unmountOnly) {
var component = node._component;
var component = node._component;
if (component) {
if (component) {
// if node is owned by a Component, unmount that component (ends up recursing back here)
// if node is owned by a Component, unmount that component (ends up recursing back here)
unmountComponent(component);
unmountComponent(component);
} else {
} else {
// If the node's VNode had a ref function, invoke it with null here.
// If the node's VNode had a ref function, invoke it with null here.
// (this is part of the React spec, and smart for unsetting references)
// (this is part of the React spec, and smart for unsetting references)
if (node[ATTR_KEY] != null && node[ATTR_KEY].ref) node[ATTR_KEY].ref(null);
if (node['__preactattr_'] != null && node['__preactattr_'].ref) node['__preactattr_'].ref(null);


if (unmountOnly === false || node[ATTR_KEY] == null) {
if (unmountOnly === false || node['__preactattr_'] == null) {
removeNode(node);
removeNode(node);
}
}


removeChildren(node);
removeChildren(node);
}
}
}
}


/** Recollect/unmount all children.
/** Recollect/unmount all children.
* - we use .lastChild here because it causes less reflow than .firstChild
* - we use .lastChild here because it causes less reflow than .firstChild
* - it's also cheaper than accessing the .childNodes Live NodeList
* - it's also cheaper than accessing the .childNodes Live NodeList
*/
*/
function removeChildren(node) {
function removeChildren(node) {
node = node.lastChild;
node = node.lastChild;
while (node) {
while (node) {
var next = node.previousSibling;
var next = node.previousSibling;
recollectNodeTree(node, true);
recollectNodeTree(node, true);
node = next;
node = next;
}
}
}
}


/** Apply differences in attributes from a VNode to the given DOM Element.
/** Apply differences in attributes from a VNode to the given DOM Element.
* @param {Element} dom Element with attributes to diff `attrs` against
* @param {Element} dom Element with attributes to diff `attrs` against
* @param {Object} attrs The desired end-state key-value attribute pairs
* @param {Object} attrs The desired end-state key-value attribute pairs
* @param {Object} old Current/previous attributes (from previous VNode or element's prop cache)
* @param {Object} old Current/previous attributes (from previous VNode or element's prop cache)
*/
*/
function diffAttributes(dom, attrs, old) {
function diffAttributes(dom, attrs, old) {
var name = void 0;
var name;


// remove attributes no longer present on the vnode by setting them to undefined
// remove attributes no longer present on the vnode by setting them to undefined
for (name in old) {
for (name in old) {
if (!(attrs && attrs[name] != null) && old[name] != null) {
if (!(attrs && attrs[name] != null) && old[name] != null) {
setAccessor(dom, name, old[name], old[name] = undefined, isSvgMode);
setAccessor(dom, name, old[name], old[name] = undefined, isSvgMode);
}
}
}
}


// add new & update changed attributes
// add new & update changed attributes
for (name in attrs) {
for (name in attrs) {
if (name !== 'children' && name !== 'innerHTML' && (!(name in old) || attrs[name] !== (name === 'value' || name === 'checked' ? dom[name] : old[name]))) {
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);
setAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode);
}
}
}
}
}
}


/** Retains a pool of Components for re-use, keyed on component name.
/** 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.
* Note: since component names are not unique or even necessarily available, these are primarily a form of sharding.
* @private
* @private
*/
*/
var components = {};
var components = {};


/** Reclaim a component for later re-use by the recycler. */
/** Reclaim a component for later re-use by the recycler. */
function collectComponent(component) {
function collectComponent(component) {
var name = component.constructor.name;
var name = component.constructor.name;
(components[name] || (components[name] = [])).push(component);
(components[name] || (components[name] = [])).push(component);
}
}


/** Create a component. Normalizes differences between PFC's and classful Components. */
/** Create a component. Normalizes differences between PFC's and classful Components. */
function createComponent(Ctor, props, context) {
function createComponent(Ctor, props, context) {
var list = components[Ctor.name],
var list = components[Ctor.name],
inst = void 0;
inst;


if (Ctor.prototype && Ctor.prototype.render) {
if (Ctor.prototype && Ctor.prototype.render) {
inst = new Ctor(props, context);
inst = new Ctor(props, context);
Component.call(inst, props, context);
Component.call(inst, props, context);
} else {
} else {
inst = new Component(props, context);
inst = new Component(props, context);
inst.constructor = Ctor;
inst.constructor = Ctor;
inst.render = doRender;
inst.render = doRender;
}
}


if (list) {
if (list) {
for (var i = list.length; i--;) {
for (var i = list.length; i--;) {
if (list[i].constructor === Ctor) {
if (list[i].constructor === Ctor) {
inst.nextBase = list[i].nextBase;
inst.nextBase = list[i].nextBase;
list.splice(i, 1);
list.splice(i, 1);
break;
break;
}
}
}
}
}
}
return inst;
return inst;
}
}


/** The `.render()` method for a PFC backing instance. */
/** The `.render()` method for a PFC backing instance. */
function doRender(props, state, context) {
function doRender(props, state, context) {
return this.constructor(props, context);
return this.constructor(props, context);
}
}


/** Set a component's `props` (generally derived from JSX attributes).
/** Set a component's `props` (generally derived from JSX attributes).
* @param {Object} props
* @param {Object} props
* @param {Object} [opts]
* @param {Object} [opts]
* @param {boolean} [opts.renderSync=false] If `true` and {@link options.syncComponentUpdates} is `true`, triggers synchronous rendering.
* @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.
* @param {boolean} [opts.render=true] If `false`, no render will be triggered.
*/
*/
function setComponentProps(component, props, opts, context, mountAll) {
function setComponentProps(component, props, opts, context, mountAll) {
if (component._disable) return;
if (component._disable) return;
component._disable = true;
component._disable = true;


if (component.__ref = props.ref) delete props.ref;
if (component.__ref = props.ref) delete props.ref;
if (component.__key = props.key) delete props.key;
if (component.__key = props.key) delete props.key;


if (!component.base || mountAll) {
if (!component.base || mountAll) {
if (component.componentWillMount) component.componentWillMount();
if (component.componentWillMount) component.componentWillMount();
} else if (component.componentWillReceiveProps) {
} else if (component.componentWillReceiveProps) {
component.componentWillReceiveProps(props, context);
component.componentWillReceiveProps(props, context);
}
}


if (context && context !== component.context) {
if (context && context !== component.context) {
if (!component.prevContext) component.prevContext = component.context;
if (!component.prevContext) component.prevContext = component.context;
component.context = context;
component.context = context;
}
}


if (!component.prevProps) component.prevProps = component.props;
if (!component.prevProps) component.prevProps = component.props;
component.props = props;
component.props = props;


component._disable = false;
component._disable = false;


if (opts !== NO_RENDER) {
if (opts !== 0) {
if (opts === SYNC_RENDER || options.syncComponentUpdates !== false || !component.base) {
if (opts === 1 || options.syncComponentUpdates !== false || !component.base) {
renderComponent(component, SYNC_RENDER, mountAll);
renderComponent(component, 1, mountAll);
} else {
} else {
enqueueRender(component);
enqueueRender(component);
}
}
}
}


if (component.__ref) component.__ref(component);
if (component.__ref) component.__ref(component);
}
}


/** Render a Component, triggering necessary lifecycle events and taking High-Order Components into account.
/** Render a Component, triggering necessary lifecycle events and taking High-Order Components into account.
* @param {Component} component
* @param {Component} component
* @param {Object} [opts]
* @param {Object} [opts]
* @param {boolean} [opts.build=false] If `true`, component will build and store a DOM node if not already associated with one.
* @param {boolean} [opts.build=false] If `true`, component will build and store a DOM node if not already associated with one.
* @private
* @private
*/
*/
function renderComponent(component, opts, mountAll, isChild) {
function renderComponent(component, opts, mountAll, isChild) {
if (component._disable) return;
if (component._disable) return;


var props = component.props,
var props = component.props,
state = component.state,
state = component.state,
context = component.context,
context = component.context,
previousProps = component.prevProps || props,
previousProps = component.prevProps || props,
previousState = component.prevState || state,
previousState = component.prevState || state,
previousContext = component.prevContext || context,
previousContext = component.prevContext || context,
isUpdate = component.base,
isUpdate = component.base,
nextBase = component.nextBase,
nextBase = component.nextBase,
initialBase = isUpdate || nextBase,
initialBase = isUpdate || nextBase,
initialChildComponent = component._component,
initialChildComponent = component._component,
skip = false,
skip = false,
rendered = void 0,
rendered,
inst = void 0,
inst,
cbase = void 0;
cbase;


// if updating
// if updating
if (isUpdate) {
if (isUpdate) {
component.props = previousProps;
component.props = previousProps;
component.state = previousState;
component.state = previousState;
component.context = previousContext;
component.context = previousContext;
if (opts !== FORCE_RENDER && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === false) {
if (opts !== 2 && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === false) {
skip = true;
skip = true;
} else if (component.componentWillUpdate) {
} else if (component.componentWillUpdate) {
component.componentWillUpdate(props, state, context);
component.componentWillUpdate(props, state, context);
}
}
component.props = props;
component.props = props;
component.state = state;
component.state = state;
component.context = context;
component.context = context;
}
}


component.prevProps = component.prevState = component.prevContext = component.nextBase = null;
component.prevProps = component.prevState = component.prevContext = component.nextBase = null;
component._dirty = false;
component._dirty = false;


if (!skip) {
if (!skip) {
rendered = component.render(props, state, context);
rendered = component.render(props, state, context);


// context to pass to the child, can be updated via (grand-)parent component
// context to pass to the child, can be updated via (grand-)parent component
if (component.getChildContext) {
if (component.getChildContext) {
context = extend(extend({}, context), component.getChildContext());
context = extend(extend({}, context), component.getChildContext());
}
}


var childComponent = rendered && rendered.nodeName,
var childComponent = rendered && rendered.nodeName,
toUnmount = void 0,
toUnmount,
base = void 0;
base;


if (typeof childComponent === 'function') {
if (typeof childComponent === 'function') {
// set up high order component link
// set up high order component link


var childProps = getNodeProps(rendered);
var childProps = getNodeProps(rendered);
inst = initialChildComponent;
inst = initialChildComponent;


if (inst && inst.constructor === childComponent && childProps.key == inst.__key) {
if (inst && inst.constructor === childComponent && childProps.key == inst.__key) {
setComponentProps(inst, childProps, SYNC_RENDER, context, false);
setComponentProps(inst, childProps, 1, context, false);
} else {
} else {
toUnmount = inst;
toUnmount = inst;


component._component = inst = createComponent(childComponent, childProps, context);
component._component = inst = createComponent(childComponent, childProps, context);
inst.nextBase = inst.nextBase || nextBase;
inst.nextBase = inst.nextBase || nextBase;
inst._parentComponent = component;
inst._parentComponent = component;
setComponentProps(inst, childProps, NO_RENDER, context, false);
setComponentProps(inst, childProps, 0, context, false);
renderComponent(inst, SYNC_RENDER, mountAll, true);
renderComponent(inst, 1, mountAll, true);
}
}


base = inst.base;
base = inst.base;
} else {
} else {
cbase = initialBase;
cbase = initialBase;


// destroy high order component link
// destroy high order component link
toUnmount = initialChildComponent;
toUnmount = initialChildComponent;
if (toUnmount) {
if (toUnmount) {
cbase = component._component = null;
cbase = component._component = null;
}
}


if (initialBase || opts === SYNC_RENDER) {
if (initialBase || opts === 1) {
if (cbase) cbase._component = null;
if (cbase) cbase._component = null;
base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, true);
base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, true);
}
}
}
}


if (initialBase && base !== initialBase && inst !== initialChildComponent) {
if (initialBase && base !== initialBase && inst !== initialChildComponent) {
var baseParent = initialBase.parentNode;
var baseParent = initialBase.parentNode;
if (baseParent && base !== baseParent) {
if (baseParent && base !== baseParent) {
baseParent.replaceChild(base, initialBase);
baseParent.replaceChild(base, initialBase);


if (!toUnmount) {
if (!toUnmount) {
initialBase._component = null;
initialBase._component = null;
recollectNodeTree(initialBase, false);
recollectNodeTree(initialBase, false);
}
}
}
}
}
}


if (toUnmount) {
if (toUnmount) {
unmountComponent(toUnmount);
unmountComponent(toUnmount);
}
}


component.base = base;
component.base = base;
if (base && !isChild) {
if (base && !isChild) {
var componentRef = component,
var componentRef = component,
t = component;
t = component;
while (t = t._parentComponent) {
while (t = t._parentComponent) {
(componentRef = t).base = base;
(componentRef = t).base = base;
}
}
base._component = componentRef;
base._component = componentRef;
base._componentConstructor = componentRef.constructor;
base._componentConstructor = componentRef.constructor;
}
}
}
}


if (!isUpdate || mountAll) {
if (!isUpdate || mountAll) {
mounts.unshift(component);
mounts.unshift(component);
} else if (!skip) {
} else if (!skip) {
// Ensure that pending componentDidMount() hooks of child components
// Ensure that pending componentDidMount() hooks of child components
// are called before the componentDidUpdate() hook in the parent.
// are called before the componentDidUpdate() hook in the parent.
flushMounts();
flushMounts();


if (component.componentDidUpdate) {
if (component.componentDidUpdate) {
component.componentDidUpdate(previousProps, previousState, previousContext);
component.componentDidUpdate(previousProps, previousState, previousContext);
}
}
if (options.afterUpdate) options.afterUpdate(component);
if (options.afterUpdate) options.afterUpdate(component);
}
}


if (component._renderCallbacks != null) {
if (component._renderCallbacks != null) {
while (component._renderCallbacks.length) {
while (component._renderCallbacks.length) {
component._renderCallbacks.pop().call(component);
component._renderCallbacks.pop().call(component);
}
}
}
}


if (!diffLevel && !isChild) flushMounts();
if (!diffLevel && !isChild) flushMounts();
}
}


/** Apply the Component referenced by a VNode to the DOM.
/** Apply the Component referenced by a VNode to the DOM.
* @param {Element} dom The DOM node to mutate
* @param {Element} dom The DOM node to mutate
* @param {VNode} vnode A Component-referencing VNode
* @param {VNode} vnode A Component-referencing VNode
* @returns {Element} dom The created/mutated element
* @returns {Element} dom The created/mutated element
* @private
* @private
*/
*/
function buildComponentFromVNode(dom, vnode, context, mountAll) {
function buildComponentFromVNode(dom, vnode, context, mountAll) {
var c = dom && dom._comp
var c = dom && dom._component,
originalComponent = c,
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