nervjs
Version:
A react-like framework based on virtual-dom
1,986 lines (1,801 loc) • 64.5 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.Nerv = global.Nerv || {})));
}(this, (function (exports) { 'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var Events = function () {
function Events(opts) {
classCallCheck(this, Events);
if (typeof opts !== 'undefined' && opts.callbacks) {
this.callbacks = opts.callbacks;
} else {
this.callbacks = {};
}
}
Events.prototype.on = function on(events, callback, context) {
var calls = void 0,
event = void 0,
node = void 0,
tail = void 0,
list = void 0;
if (!callback) {
return this;
}
events = events.split(Events.eventSplitter);
calls = this.callbacks;
while (event = events.shift()) {
list = calls[event];
node = list ? list.tail : {};
node.next = tail = {};
node.context = context;
node.callback = callback;
calls[event] = {
tail: tail,
next: list ? list.next : node
};
}
return this;
};
Events.prototype.off = function off(events, callback, context) {
var event = void 0,
calls = void 0,
node = void 0,
tail = void 0,
cb = void 0,
ctx = void 0;
if (!(calls = this.callbacks)) {
return this;
}
if (!(events || callback || context)) {
delete this.callbacks;
return this;
}
events = events ? events.split(Events.eventSplitter) : Object.keys(calls);
while (event = events.shift()) {
node = calls[event];
delete calls[event];
if (!node || !(callback || context)) {
continue;
}
tail = node.tail;
while ((node = node.next) !== tail) {
cb = node.callback;
ctx = node.context;
if (callback && cb !== callback || context && ctx !== context) {
this.on(event, cb, ctx);
}
}
}
return this;
};
Events.prototype.trigger = function trigger(events) {
var event = void 0,
node = void 0,
calls = void 0,
tail = void 0,
rest = void 0;
if (!(calls = this.callbacks)) {
return this;
}
events = events.split(Events.eventSplitter);
rest = [].slice.call(arguments, 1);
while (event = events.shift()) {
if (node = calls[event]) {
tail = node.tail;
while ((node = node.next) !== tail) {
node.callback.apply(node.context || this, rest);
}
}
}
return this;
};
return Events;
}();
Events.eventSplitter = /\s+/;
function type(arg) {
var class2type = {};
var toString = class2type.toString;
var types = 'Boolean Number String Function Array Date RegExp Object Error'.split(' ');
for (var i = 0; i < types.length; i++) {
var typeItem = types[i];
class2type['[object ' + typeItem + ']'] = typeItem.toLowerCase();
}
if (arg === null) {
return arg + '';
}
return (typeof arg === 'undefined' ? 'undefined' : _typeof(arg)) === 'object' || typeof arg === 'function' ? class2type[toString.call(arg)] || 'object' : typeof arg === 'undefined' ? 'undefined' : _typeof(arg);
}
function isBoolean(arg) {
return type(arg) === 'boolean';
}
function isNumber(arg) {
return type(arg) === 'number';
}
function isString(arg) {
return type(arg) === 'string';
}
function isFunction(arg) {
return type(arg) === 'function';
}
function isArray(arg) {
return type(arg) === 'array';
}
function isDate(arg) {
return type(arg) === 'date';
}
function isRegExp(arg) {
return type(arg) === 'regexp';
}
function isObject(arg) {
return type(arg) === 'object';
}
function isError(arg) {
return type(arg) === 'error';
}
function isNative(Ctor) {
return isFunction(Ctor) && /native code/.test(Ctor.toString());
}
function extend(source, from) {
if (!from) {
return source;
}
for (var key in from) {
if (from.hasOwnProperty(key)) {
source[key] = from[key];
}
}
return source;
}
function clone(obj) {
return extend({}, obj);
}
function getPrototype(obj) {
/* eslint-disable */
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(obj);
} else if (obj.__proto__) {
return obj.__proto__;
}
/* eslint-enable */
return obj.constructor.prototype;
}
function proxy(fn, context) {
return function () {
return fn.apply(context || this, arguments);
};
}
function isEmptyObject(obj) {
if (!obj) {
return true;
}
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
return false;
}
}
return true;
}
function debounce(func, wait, immediate) {
var timeout = void 0;
var args = void 0;
var context = void 0;
var timestamp = void 0;
var result = void 0;
var later = function later() {
var last = +new Date() - timestamp;
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
if (!timeout) {
context = null;
args = null;
}
}
}
};
return function debounced() {
context = this;
args = arguments;
timestamp = +new Date();
var callNow = immediate && !timeout;
if (!timeout) {
timeout = setTimeout(later, wait);
}
if (callNow) {
result = func.apply(context, args);
context = null;
args = null;
}
return result;
};
}
function throttle(fn, threshhold, scope) {
threshhold || (threshhold = 250);
var last = void 0,
deferTimer = void 0;
return function () {
var context = scope || this;
var now = +new Date();
var args = arguments;
if (last && now < last + threshhold) {
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
};
}
var index = Object.freeze({
type: type,
isBoolean: isBoolean,
isNumber: isNumber,
isString: isString,
isFunction: isFunction,
isArray: isArray,
isDate: isDate,
isRegExp: isRegExp,
isObject: isObject,
isError: isError,
isNative: isNative,
extend: extend,
clone: clone,
getPrototype: getPrototype,
proxy: proxy,
isEmptyObject: isEmptyObject,
debounce: debounce,
throttle: throttle
});
var callbacks = [];
var pending = false;
var runNextTick = void 0;
function nextHandler() {
pending = false;
var copies = callbacks.slice(0);
callbacks = [];
copies.forEach(function (task) {
return task();
});
}
function canUsePromise() {
return 'Promise' in window && isFunction(Promise) && isNative(Promise);
}
function canUseMutationObserver() {
return 'MutationObserver' in window && isFunction(MutationObserver) && (isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]');
}
function installPromise() {
var p = Promise.resolve();
var logErr = function logErr(err) {
return console.error(err);
};
runNextTick = function _runNextTick() {
p.then(nextHandler)['catch'](logErr);
};
}
function installMutationObserver() {
var observeNum = 1;
var textNode = document.createTextNode(observeNum);
var observer = new MutationObserver(nextHandler);
observer.observe(textNode, {
characterData: true
});
runNextTick = function _runNextTick() {
observeNum = (observeNum + 1) % 2;
textNode.data = observeNum;
};
}
function installSetTimeout() {
runNextTick = function _runNextTick() {
var timer = setTimeout;
timer(nextHandler, 0);
};
}
if (canUsePromise()) {
installPromise();
} else if (canUseMutationObserver()) {
installMutationObserver();
} else {
installSetTimeout();
}
function nextTick(cb, ctx) {
var _resolve = void 0;
callbacks.push(function () {
if (cb) {
try {
cb.call(ctx);
} catch (err) {
console.error(err);
}
} else if (_resolve) {
_resolve(ctx);
}
});
if (!pending) {
pending = true;
runNextTick();
}
if (!cb && canUsePromise()) {
return new Promise(function (resolve) {
_resolve = resolve;
});
}
}
var CurrentOwner = {
current: null
};
function isVNode(node) {
return node && node.type === 'VirtualNode';
}
function isVText(node) {
return node && node.type === 'VirtualText';
}
function isWidget(node) {
return node && node.type === 'Widget';
}
function isStateLess(node) {
return node && node.type === 'StateLess';
}
function isHook(arg) {
if (arg && typeof arg.hook === 'function' && !arg.hasOwnProperty('hook') || arg && typeof arg.unhook === 'function' && !arg.hasOwnProperty('unhook')) {
return true;
}
return false;
}
var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
var doc = document;
function createElement(vnode, isSvg) {
if (isWidget(vnode) || isStateLess(vnode)) {
return vnode.init();
}
if (isString(vnode) || isNumber(vnode)) {
return doc.createTextNode(vnode);
}
if (isVText(vnode)) {
return doc.createTextNode(vnode.text);
}
if (vnode === null || vnode === false) {
return doc.createComment('Empty dom node');
}
if (isVNode(vnode)) {
if (vnode.isSvg) {
isSvg = true;
} else if (vnode.tagName === 'svg') {
isSvg = true;
} else if (vnode.tagName === 'foreignObject') {
isSvg = false;
}
if (isSvg) {
vnode.namespace = SVG_NAMESPACE;
}
var domNode = vnode.namespace === null ? doc.createElement(vnode.tagName) : doc.createElementNS ? doc.createElementNS(vnode.namespace, vnode.tagName) : doc.createElement(vnode.tagName);
setProps(domNode, vnode.props, isSvg);
if (isSvg) {
vnode.isSvg = isSvg;
}
var children = vnode.children;
if (children.length) {
children.forEach(function (child) {
if (child !== undefined && child !== null && child !== false && domNode.appendChild) {
if (isWidget(child)) {
child.parentContext = vnode.parentContext || {};
}
var childNode = createElement(child, isSvg);
if (childNode) {
domNode.appendChild(childNode);
}
}
});
}
return domNode;
}
if (Array.isArray(vnode)) {
var _domNode = doc.createDocumentFragment();
vnode.forEach(function (child) {
if (child !== undefined && child !== null && child !== false && _domNode.appendChild) {
var childNode = createElement(child, isSvg);
if (childNode) {
_domNode.appendChild(childNode);
}
return _domNode.appendChild(childNode);
}
});
return _domNode;
}
return null;
}
function setProps(domNode, props, isSvg) {
for (var p in props) {
if (p === 'children') {
continue;
}
var propValue = props[p];
if (isHook(propValue)) {
if (propValue.hook) {
propValue.hook(domNode, p);
}
continue;
} else if (p === 'style') {
if (isString(propValue)) {
domNode.setAttribute(p, propValue);
} else if (isObject(propValue)) {
for (var s in propValue) {
var styleValue = propValue[s];
if (styleValue !== undefined) {
try {
domNode[p][s] = styleValue;
} catch (err) {}
}
}
}
continue;
} else if (isObject(propValue)) {
if (p in domNode) {
try {
domNode[p] = propValue;
} catch (err) {}
} else {
domNode.setAttribute(p, propValue);
}
continue;
} else if (p !== 'list' && p !== 'type' && !isSvg && p in domNode) {
try {
domNode[p] = propValue == null ? '' : propValue;
} catch (err) {}
if (propValue == null || propValue === false) {
domNode.removeAttribute(p);
}
continue;
} else {
if (propValue == null || propValue === false) {
domNode.removeAttribute(p);
} else {
if (!isFunction(propValue)) {
domNode.setAttribute(p, propValue);
}
}
}
}
}
var VText = function VText(text) {
classCallCheck(this, VText);
this.type = 'VirtualText';
this.text = text || '';
};
function createVText(text) {
return new VText(text);
}
var VPatch = function VPatch(type, vnode, patch) {
classCallCheck(this, VPatch);
this.type = type;
this.vnode = vnode;
this.patch = patch;
};
VPatch.NODE = 'NODE';
VPatch.VTEXT = 'VTEXT';
VPatch.VNODE = 'VNODE';
VPatch.WIDGET = 'WIDGET';
VPatch.STATELESS = 'STATELESS';
VPatch.PROPS = 'PROPS';
VPatch.ORDER = 'ORDER';
VPatch.INSERT = 'INSERT';
VPatch.REMOVE = 'REMOVE';
VPatch.prototype.type = 'VirtualPatch';
function diff(a, b) {
var patches = { old: a };
walk(a, b, patches, 0);
return patches;
}
function walk(a, b, patches, index) {
if (a === b) {
return;
}
var apply = patches[index];
var applyClear = false;
if (!b) {
if (!isWidget(a)) {
clearState(a, patches, index);
apply = patches[index];
}
apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, null));
} else if (isVText(b)) {
if (!isVText(a)) {
applyClear = true;
apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b));
} else if (a.text !== b.text) {
apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b));
}
} else if (isVNode(b)) {
if (!isVNode(a)) {
apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b));
applyClear = true;
} else if (a.tagName === b.tagName && a.key === b.key) {
var propsPatch = diffProps(a.props, b.props);
if (propsPatch) {
apply = appendPatch(apply, new VPatch(VPatch.PROPS, a, propsPatch));
}
apply = diffChildren(a, b, apply, patches, index);
} else {
apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b));
applyClear = true;
}
} else if (isWidget(b)) {
if (!isWidget(a)) {
applyClear = true;
}
apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b));
} else if (Array.isArray(b)) {
applyClear = true;
b.forEach(function (item) {
walk(null, item, patches, index);
index++;
});
} else if (isStateLess(b)) {
applyClear = true;
apply = appendPatch(apply, new VPatch(VPatch.STATELESS, a, b));
}
if (apply) {
patches[index] = apply;
}
if (applyClear) {
clearState(a, patches, index);
}
}
function diffProps(propsA, propsB) {
var diff = null;
for (var key in propsA) {
if (!propsB.hasOwnProperty(key)) {
diff = diff || {};
diff[key] = undefined;
}
var aValue = propsA[key];
var bValue = propsB[key];
if (aValue === bValue) {
continue;
} else if (isObject(aValue) && isObject(bValue)) {
if (getPrototype(aValue) !== getPrototype(bValue)) {
diff = diff || {};
diff[key] = bValue;
} else if (isHook(bValue)) {
diff = diff || {};
diff[key] = bValue;
} else {
var objDiff = diffProps(aValue, bValue);
if (objDiff) {
diff = diff || {};
diff[key] = objDiff;
}
}
} else {
diff = diff || {};
diff[key] = bValue;
}
}
for (var _key in propsB) {
if (!propsA.hasOwnProperty(_key)) {
diff = diff || {};
diff[_key] = propsB[_key];
}
}
return diff;
}
function diffChildren(a, b, apply, patches, index) {
var aChildren = a.children;
var diffSet = diffList(aChildren, b.children, 'key');
var bChildren = diffSet.list;
var len = Math.max(aChildren.length, bChildren.length);
for (var i = 0; i < len; i++) {
var leftNode = aChildren[i];
var rightNode = bChildren[i];
index += 1;
if (!leftNode) {
if (rightNode) {
apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode));
}
} else {
walk(leftNode, rightNode, patches, index);
}
if (isVNode(leftNode) && leftNode.count) {
index += leftNode.count;
}
}
if (diffSet.moves) {
apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, diffSet.moves));
}
return apply;
}
function diffList(oldList, newList, key) {
var newListKeyIndex = mapListKeyIndex(newList, key);
var newListkeyMap = newListKeyIndex.keyMap;
var newListFree = newListKeyIndex.free;
if (newListFree.length === newList.length) {
return {
list: newList,
moves: null
};
}
var oldListKeyIndex = mapListKeyIndex(oldList, key);
var oldListkeyMap = oldListKeyIndex.keyMap;
var oldListFree = oldListKeyIndex.free;
if (oldListFree.length === oldList.length) {
return {
list: newList,
moves: null
};
}
var listChange = [];
var freeIndex = 0;
var deletedItems = 0;
listChange = oldList.map(function (item) {
var itemKey = item[key];
if (itemKey) {
if (newListkeyMap.hasOwnProperty(itemKey)) {
return newList[newListkeyMap[itemKey]];
}
deletedItems++;
return null;
}
var itemIndex = newListFree[freeIndex++];
var freeItem = newList[itemIndex];
if (!freeItem) {
deletedItems++;
return null;
}
return freeItem;
});
var lastFreeIndex = freeIndex >= newListFree.length ? newList.length : newListFree[freeIndex];
newList.forEach(function (newItem, index) {
var itemKey = newItem[key];
if (itemKey) {
if (!oldListkeyMap.hasOwnProperty(itemKey)) {
listChange.push(newItem);
}
} else if (index >= lastFreeIndex) {
listChange.push(newItem);
}
});
var simulate = listChange.slice(0);
var simulateIndex = 0;
var removes = [];
var inserts = [];
var simulateItem = void 0;
for (var k = 0; k < newList.length;) {
simulateItem = simulate[simulateIndex];
while (simulateItem === null && simulate.length) {
removes.push(remove(simulate, simulateIndex, null));
simulateItem = simulate[simulateIndex];
}
var newItem = newList[k];
var newItemKey = newItem[key];
var simulateItemKey = simulateItem[key];
if (!simulateItem || simulateItemKey !== newItemKey) {
if (newItem[key]) {
if (simulateItem && simulateItemKey) {
if (newListkeyMap[simulateItemKey] !== k + 1) {
removes.push(remove(simulate, simulateIndex, simulateItemKey));
simulateItem = simulate[simulateIndex];
if (!simulateItem || simulateItemKey !== newItemKey) {
inserts.push({ key: newItemKey, to: k });
} else {
simulateIndex++;
}
} else {
inserts.push({ key: newItemKey, to: k });
}
} else {
inserts.push({ key: newItemKey, to: k });
}
k++;
} else if (simulateItem && simulateItemKey) {
removes.push(remove(simulate, simulateIndex, simulateItemKey));
}
} else {
simulateIndex++;
k++;
}
}
while (simulateIndex < simulate.length) {
simulateItem = simulate[simulateIndex];
removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key));
}
if (removes.length === deletedItems && !inserts.length) {
return {
list: listChange,
moves: null
};
}
return {
list: listChange,
moves: {
removes: removes,
inserts: inserts
}
};
}
function remove(arr, index, key) {
arr.splice(index, 1);
return {
from: index,
key: key
};
}
function clearState(vnode, patch, index) {
unhook(vnode, patch, index);
destroyWidgets(vnode, patch, index);
}
function unhook(vnode, patch, index) {
if (isVNode(vnode)) {
if (vnode.hooks) {
patch[index] = appendPatch(patch[index], new VPatch(VPatch.PROPS, vnode, undefinedKeys(vnode.hooks)));
}
if (vnode.descendantHooks) {
var children = vnode.children;
var len = children.length;
for (var i = 0; i < len; i++) {
var child = children[i];
index += 1;
unhook(child, patch, index);
if (isVNode(child) && child.count) {
index += child.count;
}
}
}
} else if (isStateLess(vnode)) {
index += 1;
unhook(vnode._renderd, patch, index);
}
}
function destroyWidgets(vnode, patch, index) {
if (isWidget(vnode)) {
if (isFunction(vnode.destroy)) {
patch[index] = appendPatch(patch[index], new VPatch(VPatch.REMOVE, vnode, null));
}
} else if (isVNode(vnode) && vnode.hasWidgets) {
vnode.children.forEach(function (child) {
index += 1;
destroyWidgets(child, patch, index);
if (isVNode(child) && child.count) {
index += child.count;
}
});
} else if (isStateLess(vnode)) {
index += 1;
destroyWidgets(vnode._renderd, patch, index);
}
}
function mapListKeyIndex(list, key) {
var keyMap = {};
var free = [];
list.forEach(function (item, i) {
if (item[key]) {
keyMap[item[key]] = i;
} else {
free.push(i);
}
});
return {
keyMap: keyMap,
free: free
};
}
function undefinedKeys(obj) {
var result = {};
for (var key in obj) {
result[key] = undefined;
}
return result;
}
function appendPatch(apply, patch) {
if (apply) {
if (Array.isArray(apply)) {
apply.push(patch);
} else {
apply = [apply, patch];
}
return apply;
}
return [patch];
}
/* eslint-disable */
if (!Object.is) {
Object.is = function (x, y) {
if (x === y) {
return x !== 0 || 1 / x === 1 / y;
}
return x !== x && y !== y;
};
}
/* eslint-enable */
function shallowEqual(obj1, obj2) {
if (obj1 === null || obj2 === null) {
return false;
}
if (Object.is(obj1, obj2)) {
return true;
}
var obj1Keys = obj1 ? Object.keys(obj1) : [];
var obj2Keys = obj2 ? Object.keys(obj2) : [];
if (obj1Keys.length !== obj2Keys.length) {
return false;
}
for (var i = 0; i < obj1Keys.length; i++) {
var obj1KeyItem = obj1Keys[i];
if (!obj2.hasOwnProperty(obj1KeyItem) || !Object.is(obj1[obj1KeyItem], obj2[obj1KeyItem])) {
return false;
}
}
return true;
}
function domIndex(rootNode, tree, patchIndices, nodes) {
if (!patchIndices || patchIndices.length === 0) {
return {};
}
patchIndices.sort(function (v1, v2) {
return v1 - v2;
});
return recurse(rootNode, tree, patchIndices, nodes, 0);
}
function recurse(rootNode, tree, patchIndices, nodes, index) {
nodes = nodes || {};
if (rootNode) {
if (indexInRange(patchIndices, index, index)) {
nodes[index] = rootNode;
}
var vChildren = tree.children;
if (vChildren) {
var childNodes = rootNode.childNodes;
vChildren.forEach(function (vChild, i) {
index++;
vChild = vChild || {};
var nextIndex = index + (vChild.count || 0);
if (indexInRange(patchIndices, index, nextIndex)) {
recurse(childNodes[i], vChild, patchIndices, nodes, index);
}
index = nextIndex;
});
}
}
return nodes;
}
function indexInRange(indices, left, right) {
if (indices.length === 0) {
return false;
}
var minIndex = 0;
var maxIndex = indices.length - 1;
var currentIndex = void 0;
var currentItem = void 0;
while (minIndex <= maxIndex) {
currentIndex = (maxIndex + minIndex) / 2 >> 0;
currentItem = indices[currentIndex];
if (minIndex === maxIndex) {
return currentItem >= left && currentItem <= right;
}
if (currentItem < left) {
minIndex = currentIndex + 1;
} else if (currentItem > right) {
maxIndex = currentIndex - 1;
} else {
return true;
}
}
return false;
}
function patch(rootNode, patches) {
var patchIndices = getPatchIndices(patches);
if (patchIndices.length === 0) {
return rootNode;
}
var oldTree = patches.old;
var nodes = domIndex(rootNode, oldTree, patchIndices);
patchIndices.forEach(function (index) {
rootNode = applyPatch(rootNode, nodes[index], patches[index]);
});
return rootNode;
}
function applyPatch(rootNode, domNode, patch) {
if (!domNode) {
return rootNode;
}
var newNode = void 0;
if (!Array.isArray(patch)) {
patch = [patch];
}
patch.forEach(function (patchItem) {
newNode = patchSingle(domNode, patchItem);
if (domNode === rootNode) {
rootNode = newNode;
}
});
return rootNode;
}
function patchSingle(domNode, vpatch) {
var type$$1 = vpatch.type;
var oldVNode = vpatch.vnode;
var patchObj = vpatch.patch;
switch (type$$1) {
case VPatch.VTEXT:
return patchVText(domNode, patchObj);
case VPatch.VNODE:
return patchVNode(domNode, patchObj);
case VPatch.INSERT:
return patchInsert(domNode, patchObj);
case VPatch.WIDGET:
return patchWidget(domNode, oldVNode, patchObj);
case VPatch.STATELESS:
return patchStateLess(domNode, oldVNode, patchObj);
case VPatch.PROPS:
return patchProps(domNode, patchObj, oldVNode.props, oldVNode.isSvg);
case VPatch.ORDER:
return patchOrder(domNode, patchObj);
case VPatch.REMOVE:
return patchRemove(domNode, oldVNode);
default:
return domNode;
}
}
function patchVText(domNode, patch) {
if (domNode === null) {
return createElement(patch);
}
if (domNode.nodeType === 3) {
if (domNode.textContent) {
domNode.textContent = patch.text;
} else {
domNode.nodeValue = patch.text;
}
return domNode;
}
var parentNode = domNode.parentNode;
var newNode = createElement(patch);
if (parentNode) {
parentNode.replaceChild(newNode, domNode);
}
return newNode;
}
function patchVNode(domNode, patch) {
if (domNode === null) {
return createElement(patch);
}
var parentNode = domNode.parentNode;
var newNode = createElement(patch);
if (parentNode && newNode !== domNode) {
parentNode.replaceChild(newNode, domNode);
}
return newNode;
}
function patchInsert(parentNode, vnode) {
var newNode = createElement(vnode);
if (parentNode && newNode) {
parentNode.appendChild(newNode);
}
return parentNode;
}
function patchWidget(domNode, vnode, patch) {
var isUpdate = isUpdateWidget(vnode, patch);
var newNode = void 0;
if (isUpdate) {
newNode = patch.update(vnode, domNode) || domNode;
} else {
newNode = createElement(patch);
}
var parentNode = domNode.parentNode;
if (parentNode && domNode !== newNode) {
parentNode.replaceChild(newNode, domNode);
}
if (!isUpdate && vnode) {
destroyWidget(domNode, vnode);
}
return newNode;
}
function patchStateLess(domNode, vnode, patch) {
var oldProps = vnode.props;
var newProps = patch.props;
if (shallowEqual(oldProps, newProps)) {
return domNode;
}
var newNode = createElement(patch);
var parentNode = domNode.parentNode;
if (parentNode && domNode !== newNode) {
parentNode.replaceChild(newNode, domNode);
}
return newNode;
}
function destroyWidget(domNode, widget) {
if (isFunction(widget.destroy) && isWidget(widget)) {
widget.destroy(domNode);
}
}
function patchProps(domNode, patch, previousProps, isSvg) {
for (var propName in patch) {
if (propName === 'children') {
continue;
}
var propValue = patch[propName];
var previousValue = previousProps[propName];
if (propValue == null || propValue === false) {
if (isHook(previousValue) && previousValue.unhook) {
previousValue.unhook(domNode, propName, propValue);
continue;
} else if (propName === 'style') {
if (isString(previousValue)) {
for (var styleName in previousValue) {
domNode.style[styleName] = '';
}
} else {
domNode.removeAttribute(propName);
}
continue;
} else if (propName in domNode) {
if (isString(previousValue)) {
domNode[propName] = '';
} else {
domNode[propName] = null;
}
domNode.removeAttribute(propName);
} else {
domNode.removeAttribute(propName);
}
} else {
if (isHook(propValue)) {
if (isHook(previousValue) && previousValue.unhook) {
previousValue.unhook(domNode, propName, propValue);
}
if (propValue && propValue.hook) {
propValue.hook(domNode, propName, previousValue);
}
continue;
} else if (propName === 'style') {
if (isString(propValue)) {
domNode.setAttribute(propName, propValue);
} else {
for (var _styleName in propValue) {
var styleValue = propValue[_styleName];
if (styleValue != null && styleValue !== false) {
try {
domNode[propName][_styleName] = styleValue;
} catch (err) {}
}
}
}
continue;
} else if (isObject(propValue)) {
if (previousValue && isObject(previousValue) && getPrototype(previousValue) !== getPrototype(propValue)) {
if (propName in domNode) {
try {
domNode[propName] = propValue;
} catch (err) {}
} else {
domNode.setAttribute(propName, propValue);
}
}
continue;
} else if (propName !== 'list' && propName !== 'type' && !isSvg && propName in domNode) {
try {
domNode[propName] = propValue;
} catch (err) {}
continue;
} else if (!isFunction(propValue)) {
domNode.setAttribute(propName, propValue);
}
}
}
return domNode;
}
function patchOrder(domNode, patch) {
var removes = patch.removes;
var inserts = patch.inserts;
var childNodes = domNode.childNodes;
var keyMap = {};
var node = void 0;
var remove = void 0;
var insert = void 0;
for (var i = 0; i < removes.length; i++) {
remove = removes[i];
node = childNodes[remove.from];
if (remove.key) {
keyMap[remove.key] = node;
}
domNode.removeChild(node);
}
var length = childNodes.length;
for (var j = 0; j < inserts.length; j++) {
insert = inserts[j];
node = keyMap[insert.key];
domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]);
}
return domNode;
}
function patchRemove(domNode, vnode) {
var parentNode = domNode.parentNode;
if (parentNode) {
parentNode.removeChild(domNode);
}
if (isWidget(vnode)) {
destroyWidget(domNode, vnode);
}
return null;
}
function isUpdateWidget(a, b) {
if (isWidget(a) && isWidget(b)) {
var keyA = a.props.key;
var keyB = b.props.key;
if ('name' in a && 'name' in b) {
return a.name === b.name && keyA === keyB;
}
return a.init === b.init && keyA === keyB;
}
return false;
}
function getPatchIndices(patches) {
var indices = [];
if (patches) {
for (var i in patches) {
if (i !== 'old' && patches.hasOwnProperty(i)) {
indices.push(Number(i));
}
}
}
return indices;
}
var RefHook = function () {
function RefHook(callback) {
classCallCheck(this, RefHook);
this.callback = callback;
}
RefHook.prototype.hook = function hook(node) {
this.callback(node);
};
RefHook.prototype.unhook = function unhook() {
this.callback(null);
};
return RefHook;
}();
var readyComponents = [];
function mountVNode(vnode, parentContext) {
if (isObject(vnode)) {
vnode.parentContext = parentContext;
}
return createElement(vnode);
}
function mountComponent(vnode) {
var parentContext = vnode.parentContext;
var componentPrototype = vnode.ComponentType.prototype;
if (componentPrototype && isFunction(componentPrototype.render)) {
vnode.component = new vnode.ComponentType(vnode.props, vnode.context);
}
var component = vnode.component;
component.context = vnode.context || parentContext;
if (isFunction(component.componentWillMount)) {
component.componentWillMount();
component.state = component.getState();
}
component._dirty = false;
var rendered = renderComponent(component);
component._rendered = rendered;
if (isFunction(component.componentDidMount)) {
readyComponents.push(component);
}
if (isFunction(vnode.props.ref)) {
readyComponents.push(function () {
return vnode.props.ref(component);
});
}
var dom = mountVNode(rendered, getChildContext(component, parentContext));
component.dom = dom;
component._disable = false;
return dom;
}
function mountStatelessComponent(vnode) {
var ref = vnode.props.ref;
delete vnode.props.ref;
vnode._renderd = vnode.tagName(vnode.props, vnode.parentContext);
var rendered = vnode._renderd;
if (isVNode(rendered) && isFunction(ref)) {
ref = new RefHook(ref);
rendered.props.ref = ref;
}
return mountVNode(rendered, vnode.parentContext);
}
function getChildContext(component, context) {
if (component.getChildContext) {
return extend(context, component.getChildContext());
}
return context;
}
function renderComponent(component) {
CurrentOwner.current = component;
var rendered = component.render();
if (isNumber(rendered) || isString(rendered)) {
rendered = createVText(rendered);
}
CurrentOwner.current = null;
return rendered;
}
function flushMount() {
if (!readyComponents.length) {
return;
}
var queue = readyComponents.slice(0);
readyComponents.length = 0;
queue.forEach(function (item) {
if (isFunction(item)) {
item();
} else if (item.componentDidMount) {
item.componentDidMount();
}
});
}
function reRenderComponent(prev, current) {
var component = current.component = prev.component;
var nextProps = current.props;
var nextContext = component.context;
component._disable = true;
if (isFunction(component.componentWillReceiveProps)) {
component.componentWillReceiveProps(nextProps, nextContext);
}
component._disable = false;
component.prevProps = component.props;
component.prevState = component.state;
component.prevContext = component.context;
component.props = nextProps;
component.context = nextContext;
if (isFunction(current.props.ref)) {
current.props.ref(component);
}
updateComponent(component);
return component.dom;
}
function updateComponent(component, isForce) {
var lastDom = component.dom;
var props = component.props;
var state = component.getState();
var context = component.context;
var prevProps = component.prevProps || props;
var prevContext = component.prevContext || context;
component.props = prevProps;
component.context = prevContext;
var skip = false;
if (!isForce && isFunction(component.shouldComponentUpdate) && component.shouldComponentUpdate(props, state, context) === false) {
skip = true;
} else if (isFunction(component.componentWillUpdate)) {
component.componentWillUpdate(props, state, context);
}
component.props = props;
component.state = state;
component.context = context;
component._dirty = false;
if (!skip) {
var lastRendered = component._rendered;
var rendered = renderComponent(component);
var childContext = getChildContext(component, context);
component._rendered = rendered;
component.dom = updateVNode(rendered, lastRendered, lastDom, childContext);
if (component.componentDidUpdate) {
component.componentDidUpdate(props, state, context);
}
}
component.prevProps = component.props;
component.prevState = component.state;
component.prevContext = component.context;
if (component._pendingCallbacks) {
while (component._pendingCallbacks.length) {
component._pendingCallbacks.pop().call(component);
}
}
flushMount();
}
function updateVNode(vnode, lastVNode, lastDom, childContext) {
if (isObject(vnode)) {
vnode.context = childContext;
}
var patches = diff(lastVNode, vnode);
var domNode = patch(lastDom, patches);
return domNode;
}
function unmountComponent(vnode) {
var component = vnode.component;
if (isFunction(component.componentWillUnmount)) {
component.componentWillUnmount();
}
var lastRendered = component._rendered;
updateVNode(null, lastRendered, component.dom, component.context);
component.dom = component._rendered = null;
if (isFunction(vnode.props.ref)) {
vnode.props.ref(null);
}
}
var items = [];
function enqueueRender(component) {
if (!component._dirty && (component._dirty = true) && items.push(component) === 1) {
nextTick(rerender);
}
}
function rerender() {
var p = void 0;
var list = items.concat();
items.length = 0;
while (p = list.pop()) {
if (p._dirty) {
updateComponent(p);
}
}
}
var Component = function (_Events) {
inherits(Component, _Events);
function Component(props, context) {
classCallCheck(this, Component);
var _this = possibleConstructorReturn(this, _Events.call(this));
if (!_this.state) {
_this.state = {};
}
_this.props = props || {};
_this.context = context || {};
_this._dirty = true;
_this._disable = true;
return _this;
}
Component.prototype.setState = function setState(state, callback) {
if (state) {
(this._pendingStates = this._pendingStates || []).push(state);
}
if (isFunction(callback)) {
(this._pendingCallbacks = this._pendingCallbacks || []).push(callback);
}
if (!this._disable) {
enqueueRender(this);
}
};
Component.prototype.getState = function getState() {
var _this2 = this;
var _pendingStates2 = this._pendingStates,
_pendingStates = _pendingStates2 === undefined ? [] : _pendingStates2,
state = this.state,
props = this.props;
if (!_pendingStates.length) {
return state;
}
var stateClone = clone(state);
var queue = _pendingStates.concat();
this._pendingStates.length = 0;
queue.forEach(function (nextState) {
if (isFunction(nextState)) {
nextState = nextState.call(_this2, state, props);
}
extend(stateClone, nextState);
});
return stateClone;
};
Component.prototype.forceUpdate = function forceUpdate(callback) {
if (isFunction(callback)) {
(this._pendingCallbacks = this._pendingCallbacks || []).push(callback);
}
updateComponent(this, true);
};
return Component;
}(Events);
var PureComponent = function (_Component) {
inherits(PureComponent, _Component);
function PureComponent() {
var _temp, _this, _ret;
classCallCheck(this, PureComponent);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = possibleConstructorReturn(this, _Component.call.apply(_Component, [this].concat(args))), _this), _this.isPureComponent = true, _temp), possibleConstructorReturn(_this, _ret);
}
PureComponent.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState) {
return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);
};
return PureComponent;
}(Component);
function isVChild(vnode) {
return isVNode(vnode) || isString(vnode) || isNumber(vnode);
}
function render(vnode, container, callback) {
if (!isVChild(vnode) && !isWidget(vnode) && !isStateLess(vnode)) {
return null;
}
if (!container || container.nodeType !== 1) {
throw new Error(container + ' should be a DOM Element');
}
var dom = mountVNode(vnode, {});
if (dom) {
container.appendChild(dom);
}
flushMount();
if (callback) {
callback();
}
return vnode.component || dom;
}
var VNode = function VNode(tagName, props, children, key, namespace, owner) {
classCallCheck(this, VNode);
this.type = 'VirtualNode';
this.tagName = tagName || 'DIV';
this.props = props || {};
this.children = children || [];
this.key = key || null;
this.namespace = isString(namespace) ? namespace : null;
this._owner = owner;
var count = this.children.length || 0;
var descendants = 0;
var hasWidgets = false;
var descendantHooks = false;
var hooks = void 0;
for (var propName in props) {
if (props.hasOwnProperty(propName)) {
var property = props[propName];
if (isHook(property) && property.unhook) {
if (!hooks) {
hooks = {};
}
hooks[propName] = property;
}
}
}
if (count) {
this.children.forEach(function (child) {
if (isVNode(child)) {
descendants += child.count || 0;
if (!hasWidgets && child.hasWidgets) {
hasWidgets = true;
}
if (!descendantHooks && (child.hooks || child.descendantHooks)) {
descendantHooks = true;
}
} else if (!hasWidgets && isWidget(child)) {
if (isFunction(child.destroy)) {
hasWidgets = true;
}
}
});
}
this.count = count + descendants;
this.hasWidgets = hasWidgets;
this.hooks = hooks;
this.descendantHooks = descendantHooks;
};
function h(tagName, props, children) {
var key = void 0;
var namespace = void 0;
var owner = void 0;
var childNodes = [];
if (!children && isChildren(props)) {
children = props;
props = {};
}
props = props || {};
if (props.hasOwnProperty('key') && props.key) {
key = props.key;
delete props.key;
}
if (props.hasOwnProperty('namespace') && props.namespace) {
namespace = props.namespace;
delete props.namespace;
}
if (props.hasOwnProperty('owner')) {
owner = props.owner;
delete props.owner;
}
if (props.hasOwnProperty('children') && props.children) {
if (!children || !children.length) {
children = props.children;
}
delete props.children;
}
if (children) {
addChildren(childNodes, children, tagName);
}
return new VNode(tagName, props, childNodes, key, namespace, owner);
}
function addChildren(childNodes, children, tagName) {
if (isString(children) || isNumber(children)) {
children = String(children);
childNodes.push(createVText(children));
} else if (isChild(children)) {
childNodes.push(children);
} else if (isArray(children)) {
children.forEach(function (child) {
return addChildren(childNodes, child, tagName);
});
}
}
function isChild(node) {
return isVNode(node) || isVText(node) || isWidget(node) || isStateLess(node);
}
function isChildren(x) {
return isString(x) || isArray(x) || isChild(x);
}
var NS = {
ev: 'http://www.w3.org/2001/xml-events',
xlink: 'http://www.w3.org/1999/xlink',
xml: 'http://www.w3.org/XML/1998/namespace'
};
var ATTRS = {
accentHeight: 'accent-height',
accumulate: 0,
additive: 0,
alignmentBaseline: 'alignment-baseline',
allowReorder: 'allowReorder',
alphabetic: 0,
amplitude: 0,
arabicForm: 'arabic-form',
ascent: 0,
attributeName: 'attributeName',
attributeType: 'attributeType',
autoReverse: 'autoReverse',
azimuth: 0,
baseFrequency: 'baseFrequency',
baseProfile: 'baseProfile',
baselineShift: 'baseline-shift',
bbox: 0,
begin: 0,
bias: 0,
by: 0,
calcMode: 'calcMode',
capHeight: 'cap-height',
clip: 0,
clipPath: 'clip-path',
clipRule: 'clip-rule',
clipPathUnits: 'clipPathUnits',
colorInterpolation: 'color-interpolation',
colorInterpolationFilters: 'color-interpolation-filters',
colorProfile: 'color-profile',
colorRendering: 'color-rendering',
contentScriptType: 'contentScriptType',
contentStyleType: 'contentStyleType',
cursor: 0,
cx: 0,
cy: 0,
d: 0,
decelerate: 0,
descent: 0,
diffuseConstant: 'diffuseConstant',
direction: 0,
display: 0,
divisor: 0,
dominantBaseline: 'dominant-baseline',
dur: 0,
dx: 0,
dy: 0,
edgeMode: 'edgeMode',
elevation: 0,
enableBackground: 'enable-background',
end: 0,
evEvent: 'ev:event',
exponent: 0,
externalResourcesRequired: 'externalResourcesRequired',
fill: 0,
fillOpacity: 'fill-opacity',
fillRule: 'fill-rule',
filter: 0,
filterRes: 'filterRes',
filterUnits: 'filterUnits',
floodColor: 'flood-color',
floodOpacity: 'flood-opacity',
focusable: 0,
fontFamily: 'font-family',
fontSize: 'font-size',
fontSizeAdjust: 'font-size-adjust',
fontStretch: 'font-stretch',
fontStyle: 'font-style',
fontVariant: 'font-variant',
fontWeight: 'font-weight',
format: 0,
from: 0,
fx: 0,
fy: 0,
g1: 0,
g2: 0,
glyphName: 'glyph-name',
glyphOrientationHorizontal: 'glyph-orientation-horizontal',
glyphOrientationVertical: 'glyph-orientation-vertical',
glyphRef: 'glyphRef',
gradientTransform: 'gradientTransform',
gradientUnits: 'gradientUnits',
hanging: 0,
horizAdvX: 'horiz-adv-x',
horizOriginX: 'horiz-origin-x',
ideographic: 0,
imageRendering: 'image-rendering',
'in': 0,
in2: 0,
intercept: 0,
k: 0,
k1: 0,
k2: 0,
k3: 0,
k4: 0,
kernelMatrix: 'kernelMatrix',
kernelUnitLength: 'kernelUnitLength',
kerning: 0,
keyPoints: 'keyPoints',
keySplines: 'keySplines',
keyTimes: 'keyTimes',
lengthAdjust: 'lengthAdjust',
letterSpacing: 'letter-spacing',
lightingColor: 'lighting-color',
limitingConeAngle: 'limitingConeAngle',
local: 0,
markerEnd: 'marker-end',
markerMid: 'marker-mid',
markerStart: 'marker-start',
markerHeight: 'markerHeight',
markerUnits: 'markerUnits',
markerWidth: 'markerWidth',
mask: 0,
maskContentUnits: 'maskContentUnits',
maskUnits: 'maskUnits',
mathematical: 0,
mode: 0,
numOctaves: 'numOctaves',
offset: 0,
opacity: 0,
operator: 0,
order: 0,
orient: 0,
orientation: 0,
origin: 0,
overflow: 0,
overlinePosition: 'overline-position',
overlineThickness: 'overline-thickness',
paintOrder: 'paint-order',
panose1: 'panose-1',
pathLength: 'pathLength',
patternContentUnits: 'patternContentUnits',
patternTransform: 'patternTransform',
patternUnits: 'patternUnits',
pointerEvents: 'pointer-events',
points: 0,
pointsAtX: 'pointsAtX',
pointsAtY: 'pointsAtY',
pointsAtZ: 'pointsAtZ',
preserveAlpha: 'preserveAlpha',
preserveAspectRatio: 'preserveAspectRatio',
primitiveUnits: 'primitiveUnits',
r: 0,
radius: 0,
refX: 'refX',
refY: 'refY',
renderingIntent: 'rendering-intent',
repeatCount: 'repeatCount',
repeatDur: 'repeatDur',
requiredExtensions: 'requiredExtensions',
requiredFeatures: 'requiredFeatures',
restart: 0,
result: 0,
rotate: 0,
rx: 0,
ry: 0,
scale: 0,
seed: 0,
shapeRendering: 'shape-rendering',
slope: 0,
spacing: 0,
specularConstant: 'specularConstant',
specularExponent: 'specularExponent',
speed: 0,
spreadMethod: 'spreadMethod',
startOffset: 'startOffset',
stdDeviation: 'stdDeviation',
stemh: 0,
stemv: 0,
stitchTiles: 'stitchTiles',
stopColor: 'stop-color',
stopOpacity: 'stop-opacity',
strikethroughPosition: 'strikethrough-position',
strikethroughThickness: 'strikethrough-thickness',
string: 0,
stroke: 0,
strokeDasharray: 'stroke-dasharray',
strokeDashoffset: 'stroke-dashoffset',
strokeLinecap: 'stroke-linecap',
strokeLinejoin: 'stroke-linejoin',
strokeMiterlimit: 'stroke-miterlimit',
strokeOpacity: 'stroke-opacity',
strokeWidth: 'stroke-width',
surfaceScale: 'surfaceScale',
systemLanguage: 'systemLanguage',
tableValues: 'tableValues',
targetX: 'targetX',
targetY: 'targetY',
textAnchor: 'text-anchor',
textDecoration: 'text-decoration',
textRendering: 'text-rendering',
textLength: 'textLength',
to: 0,
transform: 0,
u1: 0,
u2: 0,
underlinePosition: 'underline-position',
underlineThickness: 'underline-thickness',
unicode: 0,
unicodeBidi: 'unicode-bidi',
unicodeRange: 'unicode-range',
unitsPerEm: 'units-per-em',
vAlphabetic: 'v-alphabetic',
vHanging: 'v-hanging',
vIdeographic: 'v-ideographic',
vMathematical: 'v-mathematical',
values: 0,
vectorEffect: 'vector-effect',
version: 0,
vertAdvY: 'vert-adv-y',
vertOriginX: 'vert-origin-x',
vertOriginY: 'vert-origin-y',
viewBox: 'viewBox',
viewTarget: 'viewTarget',
visibility: 0,
widths: 0,
wordSpacing: 'word-spacing',
writingMode: 'writing-mode',
x: 0,
xHeight: 'x-height',
x1: 0,
x2: 0,
xChannelSelector: 'xChannelSelector',
xlinkActuate: 'xlink:actuate',
xlinkArcrole: 'xlink:arcrole',
xlinkHref: 'xlink:href',
xlinkRole: 'xlink:role',
xlinkShow: 'xlink:show',
xlinkTitle: 'xlink:title',
xlinkType: 'xlink:type',
xmlBase: 'xml:base',
xmlId: 'xml:id',
xmlns: 0,
xmlnsXlink: 'xmlns:xlink',
xmlLang: 'xml:lang',
xmlSpace: 'xml:space',
y: 0,
y1: 0,
y2: 0,
yChannelSelector: 'yChannelSelector',
z: 0,
zoomAndPan: 'zoomAndPan'
};
var SVGPropertyConfig = {
Properties: {},
DOMAttributeNamespaces: {
evEvent: NS.ev,
xlinkActuate: NS.xlink,
xlinkArcrole: NS.xlink,
xlinkHref: NS.xlink,
xlinkRole: NS.xlink,
xlinkShow: N