From c6d6afbdfaf7b569c13e8cbd59b94ce0a941f6b7 Mon Sep 17 00:00:00 2001 From: Gandalf-the-Bot Date: Tue, 4 Dec 2018 17:22:15 +0000 Subject: [PATCH] Bundled output for commit bcc6003bf3fff0613090d49215c6d0520f82c802 [skip ci] --- README.md | 2 +- mithril.js | 61 ++--- mithril.min.js | 2 +- mithril.min.mjs | 49 +--- mithril.mjs | 555 ++++++++++++++++++++++++---------------------- stream/stream.mjs | 247 ++++++++++----------- 6 files changed, 446 insertions(+), 470 deletions(-) diff --git a/README.md b/README.md index 9dd9239c..681158a9 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ mithril.js [![NPM Version](https://img.shields.io/npm/v/mithril.svg)](https://ww ## What is Mithril? -A modern client-side Javascript framework for building Single Page Applications. It's small (8.83 KB gzipped), fast and provides routing and XHR utilities out of the box. +A modern client-side Javascript framework for building Single Page Applications. It's small (8.86 KB gzipped), fast and provides routing and XHR utilities out of the box. Mithril is used by companies like Vimeo and Nike, and open source platforms like Lichess 👍. diff --git a/mithril.js b/mithril.js index 7ebaab0a..2df3ed82 100644 --- a/mithril.js +++ b/mithril.js @@ -1155,36 +1155,45 @@ var coreRenderer = function($window) { // Defer the property check until *after* we check everything. ) && key in vnode.dom } - var matchUpperCase = /[A-Z]/g - function prependDashAndLowerCase(string){ - return "-" + string.toLowerCase() - } - function normalizeProp(prop) { - return "-" && prop[1] === "-" - ? prop - : prop.replace(matchUpperCase, prependDashAndLowerCase) - } //style + var uppercaseRegex = /[A-Z]/g + function toLowerCase(capital) { return "-" + capital.toLowerCase() } + function normalizeKey(key) { + return key[0] === "-" && key[1] === "-" ? key : + key === "cssFloat" ? "float" : + key.replace(uppercaseRegex, toLowerCase) + } function updateStyle(element, old, style) { - if (old != null && style != null && typeof old === "object" && typeof style === "object" && style !== old) { + if (old === style) { + // Styles are equivalent, do nothing. + } else if (style == null) { + // New style is missing, just clear it. + element.style.cssText = "" + } else if (typeof style !== "object") { + // New style is a string, let engine deal with patching. + element.style.cssText = style + } else if (old == null || typeof old !== "object") { + // `old` is missing or a string, `style` is an object. + element.style.cssText = "" + // Add new style properties + for (var key in style) { + var value = style[key] + if (value != null) element.style.setProperty(normalizeKey(key), String(value)) + } + } else { // Both old & new are (different) objects. // Update style properties that have changed for (var key in style) { - if (style[key] !== old[key]) element.style.setProperty(normalizeProp(key), style[key]) + var value = style[key] + if (value != null && (value = String(value)) !== String(old[key])) { + element.style.setProperty(normalizeKey(key), value) + } } // Remove style properties that no longer exist for (var key in old) { - if (!(key in style)) element.style.removeProperty(normalizeProp(key)) - } - return - } - if (old === style) element.style.cssText = "", old = null - if (style == null) element.style.cssText = "" - else if (typeof style === "string") element.style.cssText = style - else { - if (typeof old === "string") element.style.cssText = "" - for (var key in style) { - element.style.setProperty(normalizeProp(key), style[key]) + if (old[key] != null && style[key] == null) { + element.style.removeProperty(normalizeKey(key)) + } } } } @@ -1333,9 +1342,9 @@ var parseQueryString = function(string) { for (var i = 0; i < entries.length; i++) { var entry = entries[i].split("=") var key2 = decodeURIComponent(entry[0]) - var value = entry.length === 2 ? decodeURIComponent(entry[1]) : "" - if (value === "true") value = true - else if (value === "false") value = false + var value0 = entry.length === 2 ? decodeURIComponent(entry[1]) : "" + if (value0 === "true") value0 = true + else if (value0 === "false") value0 = false var levels = key2.split(/\]\[?|\[/) var cursor = data2 if (key2.indexOf("[") > -1) levels.pop() @@ -1349,7 +1358,7 @@ var parseQueryString = function(string) { level = counters[key2]++ } if (cursor[level] == null) { - cursor[level] = isValue ? value : isNumber ? [] : {} + cursor[level] = isValue ? value0 : isNumber ? [] : {} } cursor = cursor[level] } diff --git a/mithril.min.js b/mithril.min.js index f44eaed6..56071ddd 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1 +1 @@ -!function(){"use strict";function e(e,t,n,r,o,i){return{tag:e,key:t,attrs:n,children:r,text:o,dom:i,domSize:void 0,state:void 0,events:void 0,instance:void 0}}e.normalize=function(t){return Array.isArray(t)?e("[",void 0,void 0,e.normalizeChildren(t),void 0,void 0):null!=t&&"object"!=typeof t?e("#",void 0,void 0,!1===t?"":t,void 0,void 0):t},e.normalizeChildren=function(t){for(var n=[],r=0;r0&&(l.className=i.join(" ")),n[e]={tag:o,attrs:l}}(i),a,e.normalizeChildren(l)):e(i,a.key,a,l)}i.trust=function(t){return null==t&&(t=""),e("<",void 0,void 0,t,void 0,void 0)},i.fragment=function(t,n){return e("[",t.key,t,e.normalizeChildren(n),void 0,void 0)};var l=function(){return i.apply(this,arguments)};if(l.m=i,l.trust=i.trust,l.fragment=i.fragment,(a=function(e){if(!(this instanceof a))throw new Error("Promise must be called with `new`");if("function"!=typeof e)throw new TypeError("executor must be a function");var t=this,n=[],r=[],o=f(n,!0),i=f(r,!1),l=t._instance={resolvers:n,rejectors:r},u="function"==typeof setImmediate?setImmediate:setTimeout;function f(e,o){return function a(f){var c;try{if(!o||null==f||"object"!=typeof f&&"function"!=typeof f||"function"!=typeof(c=f.then))u(function(){o||0!==e.length||console.error("Possible unhandled promise rejection:",f);for(var t=0;t0||e(n)}}var r=n(i);try{e(n(o),r)}catch(e){r(e)}}s(e)}).prototype.then=function(e,t){var n,r,o=this._instance;function i(e,t,i,l){t.push(function(t){if("function"!=typeof e)i(t);else try{n(e(t))}catch(e){r&&r(e)}}),"function"==typeof o.retry&&l===o.state&&o.retry()}var l=new a(function(e,t){n=e,r=t});return i(e,o.resolvers,n,!0),i(t,o.rejectors,r,!1),l},a.prototype.catch=function(e){return this.then(null,e)},a.prototype.finally=function(e){return this.then(function(t){return a.resolve(e()).then(function(){return t})},function(t){return a.resolve(e()).then(function(){return a.reject(t)})})},a.resolve=function(e){return e instanceof a?e:new a(function(t){t(e)})},a.reject=function(e){return new a(function(t,n){n(e)})},a.all=function(e){return new a(function(t,n){var r=e.length,o=0,i=[];if(0===e.length)t([]);else for(var l=0;l=200&&c.status<300||304===c.status||/^file:\/\//i.test(t),i=c.responseText;if("function"==typeof n.extract)i=n.extract(c,n),e=!0;else if("function"==typeof n.deserialize)i=n.deserialize(i);else try{i=i?JSON.parse(i):null}catch(e){throw new Error("Invalid JSON: "+i)}if(e)r(i);else{var l=new Error(c.responseText);l.code=c.status,l.response=i,o(l)}}catch(e){o(e)}},u&&null!=f?c.send(f):c.send()}),jsonp:o(function(t,n,o,i){var a=n.callbackName||"_mithril_"+Math.round(1e16*Math.random())+"_"+r++,u=e.document.createElement("script");e[a]=function(t){u.parentNode.removeChild(u),o(t),delete e[a]},u.onerror=function(){u.parentNode.removeChild(u),i(new Error("JSONP request failed")),delete e[a]},t=l(t,n.data,!0),u.src=t+(t.indexOf("?")<0?"?":"&")+encodeURIComponent(n.callbackKey||"callback")+"="+encodeURIComponent(a),e.document.documentElement.appendChild(u)}),setCompletionCallback:function(e){n=e}}}(window,a),s=function(t){var n,r=t.document,o={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"};function i(e){return e.attrs&&e.attrs.xmlns||o[e.tag]}function l(e,t){if(e.state!==t)throw new Error("`vnode.state` must not be modified")}function a(e){var t=e.state;try{return this.apply(t,arguments)}finally{l(e,t)}}function u(){try{return r.activeElement}catch(e){return null}}function f(e,t,n,r,o,i,l){for(var a=n;a'+t.children+"",l=l.firstChild):l.innerHTML=t.children,t.dom=l.firstChild,t.domSize=l.childNodes.length;for(var a,u=r.createDocumentFragment();a=l.firstChild;)u.appendChild(a);g(e,u,o)}function v(e,t,n,r,o,i){if(t!==n&&(null!=t||null!=n))if(null==t||0===t.length)f(e,n,0,n.length,r,o,i);else if(null==n||0===n.length)b(t,0,t.length);else{for(var l=0,a=0,u=null,c=null;a=a&&E>=l;)if(w=t[S],k=n[E],null==w)S--;else if(null==k)E--;else{if(w.key!==k.key)break;w!==k&&p(e,w,k,r,o,i),null!=k.dom&&(o=k.dom),S--,E--}for(;S>=a&&E>=l;)if(d=t[a],v=n[l],null==d)a++;else if(null==v)l++;else{if(d.key!==v.key)break;a++,l++,d!==v&&p(e,d,v,r,y(t,a,o),i)}for(;S>=a&&E>=l;){if(null==d)a++;else if(null==v)l++;else if(null==w)S--;else if(null==k)E--;else{if(l===E)break;if(d.key!==k.key||w.key!==v.key)break;C=y(t,a,o),g(e,m(w),C),w!==v&&p(e,w,v,r,C,i),++l<=--E&&g(e,m(d),o),d!==k&&p(e,d,k,r,o,i),null!=k.dom&&(o=k.dom),a++,S--}w=t[S],k=n[E],d=t[a],v=n[l]}for(;S>=a&&E>=l;){if(null==w)S--;else if(null==k)E--;else{if(w.key!==k.key)break;w!==k&&p(e,w,k,r,o,i),null!=k.dom&&(o=k.dom),S--,E--}w=t[S],k=n[E]}if(l>E)b(t,a,S+1);else if(a>S)f(e,n,l,E+1,r,o,i);else{var z,A,j=o,N=E-l+1,P=new Array(N),O=0,T=0,$=2147483647,I=0;for(T=0;T=l;T--)if(null==z&&(z=h(t,a,S+1)),null!=(k=n[T])){var R=z[k.key];null!=R&&($=R<$?R:-1,P[T-l]=R,w=t[R],t[R]=null,w!==k&&p(e,w,k,r,o,i),null!=k.dom&&(o=k.dom),I++)}if(o=j,I!==S-a+1&&b(t,a,S+1),0===I)f(e,n,l,E+1,r,o,i);else if(-1===$)for(O=(A=function(e){var t,n,r=e.slice(),o=[];o.push(0);for(var i=0,l=e.length;i0&&(r[i]=o[t-1]),o[t]=i)}}t=o.length,n=o[t-1];for(;t-- >0;)o[t]=n,n=r[n];return o}(P)).length-1,T=E;T>=l;T--)v=n[T],-1===P[T-l]?s(e,v,r,i,o):A[O]===T-l?O--:g(e,m(v),o),null!=v.dom&&(o=n[T].dom);else for(T=E;T>=l;T--)v=n[T],-1===P[T-l]&&s(e,v,r,i,o),null!=v.dom&&(o=n[T].dom)}}else{var L=t.lengthL&&b(t,l,t.length),n.length>L&&f(e,n,l,n.length,r,o,i)}}}function p(t,n,r,o,l,u){var f=n.tag;if(f===r.tag){if(r.state=n.state,r.events=n.events,function(e,t){do{if(null!=e.attrs&&"function"==typeof e.attrs.onbeforeupdate){var n=a.call(e.attrs.onbeforeupdate,e,t);if(void 0!==n&&!n)break}if("string"!=typeof e.tag&&"function"==typeof e.state.onbeforeupdate){var n=a.call(e.state.onbeforeupdate,e,t);if(void 0!==n&&!n)break}return!1}while(0);return e.dom=t.dom,e.domSize=t.domSize,e.instance=t.instance,!0}(r,n))return;if("string"==typeof f)switch(null!=r.attrs&&$(r.attrs,r,o),f){case"#":!function(e,t){e.children.toString()!==t.children.toString()&&(e.dom.nodeValue=t.children);t.dom=e.dom}(n,r);break;case"<":!function(e,t,n,r,o){t.children!==n.children?(m(t),d(e,n,r,o)):(n.dom=t.dom,n.domSize=t.domSize)}(t,n,r,u,l);break;case"[":!function(e,t,n,r,o,i){v(e,t.children,n.children,r,o,i);var l=0,a=n.children;if(n.dom=null,null!=a){for(var u=0;u0){for(var o=e.dom;--t;)n.appendChild(o.nextSibling);n.insertBefore(o,n.firstChild)}return n}return e.dom}function y(e,t,n){for(;t-1||null!=e.attrs&&e.attrs.is||"href"!==t&&"list"!==t&&"form"!==t&&"width"!==t&&"height"!==t)&&t in e.dom}var z=/[A-Z]/g;function A(e){return"-"+e.toLowerCase()}function j(e){return"-"===e[1]?e:e.replace(z,A)}function N(e,t,n){if(null==t||null==n||"object"!=typeof t||"object"!=typeof n||n===t)if(t===n&&(e.style.cssText="",t=null),null==n)e.style.cssText="";else if("string"==typeof n)e.style.cssText=n;else for(var r in"string"==typeof t&&(e.style.cssText=""),n)e.style.setProperty(j(r),n[r]);else{for(var r in n)n[r]!==t[r]&&e.style.setProperty(j(r),n[r]);for(var r in t)r in n||e.style.removeProperty(j(r))}}function P(){}function O(e,t,n){if(null!=e.events){if(e.events[t]===n)return;null==n||"function"!=typeof n&&"object"!=typeof n?(null!=e.events[t]&&e.dom.removeEventListener(t.slice(2),e.events,!1),e.events[t]=void 0):(null==e.events[t]&&e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=n)}else null==n||"function"!=typeof n&&"object"!=typeof n||(e.events=new P,e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=n)}function T(e,t,n){"function"==typeof e.oninit&&a.call(e.oninit,t),"function"==typeof e.oncreate&&n.push(a.bind(e.oncreate,t))}function $(e,t,n){"function"==typeof e.onupdate&&n.push(a.bind(e.onupdate,t))}return P.prototype=Object.create(null),P.prototype.handleEvent=function(e){var t,r=this["on"+e.type];"function"==typeof r?t=r.call(e.currentTarget,e):"function"==typeof r.handleEvent&&r.handleEvent(e),!1===e.redraw?e.redraw=void 0:"function"==typeof n&&n(),!1===t&&(e.preventDefault(),e.stopPropagation())},{render:function(t,n){if(!t)throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.");var r=[],o=u(),i=t.namespaceURI;null==t.vnodes&&(t.textContent=""),n=e.normalizeChildren(Array.isArray(n)?n:[n]),v(t,t.vnodes,n,r,null,"http://www.w3.org/1999/xhtml"===i?void 0:i),t.vnodes=n,null!=o&&u()!==o&&"function"==typeof o.focus&&o.focus();for(var l=0;l-1&&r.splice(t,2)}function l(){if(o)throw new Error("Nested m.redraw.sync() call");o=!0;for(var e=1;e-1&&u.pop();for(var s=0;s-1?r:o>-1?o:e.length;if(r>-1){var l=o>-1?o:e.length,a=p(e.slice(r+1,l));for(var u in a)t[u]=a[u]}if(o>-1){var f=p(e.slice(o+1));for(var u in f)n[u]=f[u]}return e.slice(0,i)}var l={prefix:"#!",getPath:function(){switch(l.prefix.charAt(0)){case"#":return o("hash").slice(l.prefix.length);case"?":return o("search").slice(l.prefix.length)+o("hash");default:return o("pathname").slice(l.prefix.length)+o("search")+o("hash")}},setPath:function(t,r,o){var a={},f={};if(t=i(t,a,f),null!=r){for(var s in r)a[s]=r[s];t=t.replace(/:([^\/]+)/g,function(e,t){return delete a[t],r[t]})}var c=u(a);c&&(t+="?"+c);var d=u(f);if(d&&(t+="#"+d),n){var v=o?o.state:null,p=o?o.title:null;e.onpopstate(),o&&o.replace?e.history.replaceState(v,p,l.prefix+t):e.history.pushState(v,p,l.prefix+t)}else e.location.href=l.prefix+t}};return l.defineRoutes=function(o,a,u){function f(){var t=l.getPath(),n={},r=i(t,n,n),f=e.history.state;if(null!=f)for(var s in f)n[s]=f[s];for(var c in o){var d=new RegExp("^"+c.replace(/:[^\/]+?\.{3}/g,"(.*?)").replace(/:[^\/]+/g,"([^\\/]+)")+"/?$");if(d.test(r))return void r.replace(d,function(){for(var e=c.match(/:[^\/]+/g)||[],r=[].slice.call(arguments,1,-2),i=0;i0&&(l.className=i.join(" ")),n[e]={tag:o,attrs:l}}(i),a,e.normalizeChildren(l)):e(i,a.key,a,l)}i.trust=function(t){return null==t&&(t=""),e("<",void 0,void 0,t,void 0,void 0)},i.fragment=function(t,n){return e("[",t.key,t,e.normalizeChildren(n),void 0,void 0)};var l=function(){return i.apply(this,arguments)};if(l.m=i,l.trust=i.trust,l.fragment=i.fragment,(a=function(e){if(!(this instanceof a))throw new Error("Promise must be called with `new`");if("function"!=typeof e)throw new TypeError("executor must be a function");var t=this,n=[],r=[],o=f(n,!0),i=f(r,!1),l=t._instance={resolvers:n,rejectors:r},u="function"==typeof setImmediate?setImmediate:setTimeout;function f(e,o){return function a(f){var c;try{if(!o||null==f||"object"!=typeof f&&"function"!=typeof f||"function"!=typeof(c=f.then))u(function(){o||0!==e.length||console.error("Possible unhandled promise rejection:",f);for(var t=0;t0||e(n)}}var r=n(i);try{e(n(o),r)}catch(e){r(e)}}s(e)}).prototype.then=function(e,t){var n,r,o=this._instance;function i(e,t,i,l){t.push(function(t){if("function"!=typeof e)i(t);else try{n(e(t))}catch(e){r&&r(e)}}),"function"==typeof o.retry&&l===o.state&&o.retry()}var l=new a(function(e,t){n=e,r=t});return i(e,o.resolvers,n,!0),i(t,o.rejectors,r,!1),l},a.prototype.catch=function(e){return this.then(null,e)},a.prototype.finally=function(e){return this.then(function(t){return a.resolve(e()).then(function(){return t})},function(t){return a.resolve(e()).then(function(){return a.reject(t)})})},a.resolve=function(e){return e instanceof a?e:new a(function(t){t(e)})},a.reject=function(e){return new a(function(t,n){n(e)})},a.all=function(e){return new a(function(t,n){var r=e.length,o=0,i=[];if(0===e.length)t([]);else for(var l=0;l=200&&c.status<300||304===c.status||/^file:\/\//i.test(t),i=c.responseText;if("function"==typeof n.extract)i=n.extract(c,n),e=!0;else if("function"==typeof n.deserialize)i=n.deserialize(i);else try{i=i?JSON.parse(i):null}catch(e){throw new Error("Invalid JSON: "+i)}if(e)r(i);else{var l=new Error(c.responseText);l.code=c.status,l.response=i,o(l)}}catch(e){o(e)}},u&&null!=f?c.send(f):c.send()}),jsonp:o(function(t,n,o,i){var a=n.callbackName||"_mithril_"+Math.round(1e16*Math.random())+"_"+r++,u=e.document.createElement("script");e[a]=function(t){u.parentNode.removeChild(u),o(t),delete e[a]},u.onerror=function(){u.parentNode.removeChild(u),i(new Error("JSONP request failed")),delete e[a]},t=l(t,n.data,!0),u.src=t+(t.indexOf("?")<0?"?":"&")+encodeURIComponent(n.callbackKey||"callback")+"="+encodeURIComponent(a),e.document.documentElement.appendChild(u)}),setCompletionCallback:function(e){n=e}}}(window,a),s=function(t){var n,r=t.document,o={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"};function i(e){return e.attrs&&e.attrs.xmlns||o[e.tag]}function l(e,t){if(e.state!==t)throw new Error("`vnode.state` must not be modified")}function a(e){var t=e.state;try{return this.apply(t,arguments)}finally{l(e,t)}}function u(){try{return r.activeElement}catch(e){return null}}function f(e,t,n,r,o,i,l){for(var a=n;a'+t.children+"",l=l.firstChild):l.innerHTML=t.children,t.dom=l.firstChild,t.domSize=l.childNodes.length;for(var a,u=r.createDocumentFragment();a=l.firstChild;)u.appendChild(a);g(e,u,o)}function v(e,t,n,r,o,i){if(t!==n&&(null!=t||null!=n))if(null==t||0===t.length)f(e,n,0,n.length,r,o,i);else if(null==n||0===n.length)b(t,0,t.length);else{for(var l=0,a=0,u=null,c=null;a=a&&E>=l;)if(w=t[C],k=n[E],null==w)C--;else if(null==k)E--;else{if(w.key!==k.key)break;w!==k&&p(e,w,k,r,o,i),null!=k.dom&&(o=k.dom),C--,E--}for(;C>=a&&E>=l;)if(d=t[a],v=n[l],null==d)a++;else if(null==v)l++;else{if(d.key!==v.key)break;a++,l++,d!==v&&p(e,d,v,r,y(t,a,o),i)}for(;C>=a&&E>=l;){if(null==d)a++;else if(null==v)l++;else if(null==w)C--;else if(null==k)E--;else{if(l===E)break;if(d.key!==k.key||w.key!==v.key)break;S=y(t,a,o),g(e,m(w),S),w!==v&&p(e,w,v,r,S,i),++l<=--E&&g(e,m(d),o),d!==k&&p(e,d,k,r,o,i),null!=k.dom&&(o=k.dom),a++,C--}w=t[C],k=n[E],d=t[a],v=n[l]}for(;C>=a&&E>=l;){if(null==w)C--;else if(null==k)E--;else{if(w.key!==k.key)break;w!==k&&p(e,w,k,r,o,i),null!=k.dom&&(o=k.dom),C--,E--}w=t[C],k=n[E]}if(l>E)b(t,a,C+1);else if(a>C)f(e,n,l,E+1,r,o,i);else{var z,A,j=o,N=E-l+1,P=new Array(N),O=0,$=0,T=2147483647,I=0;for($=0;$=l;$--)if(null==z&&(z=h(t,a,C+1)),null!=(k=n[$])){var R=z[k.key];null!=R&&(T=R0&&(r[i]=o[t-1]),o[t]=i)}}t=o.length,n=o[t-1];for(;t-- >0;)o[t]=n,n=r[n];return o}(P)).length-1,$=E;$>=l;$--)v=n[$],-1===P[$-l]?s(e,v,r,i,o):A[O]===$-l?O--:g(e,m(v),o),null!=v.dom&&(o=n[$].dom);else for($=E;$>=l;$--)v=n[$],-1===P[$-l]&&s(e,v,r,i,o),null!=v.dom&&(o=n[$].dom)}}else{var L=t.lengthL&&b(t,l,t.length),n.length>L&&f(e,n,l,n.length,r,o,i)}}}function p(t,n,r,o,l,u){var f=n.tag;if(f===r.tag){if(r.state=n.state,r.events=n.events,function(e,t){do{if(null!=e.attrs&&"function"==typeof e.attrs.onbeforeupdate){var n=a.call(e.attrs.onbeforeupdate,e,t);if(void 0!==n&&!n)break}if("string"!=typeof e.tag&&"function"==typeof e.state.onbeforeupdate){var n=a.call(e.state.onbeforeupdate,e,t);if(void 0!==n&&!n)break}return!1}while(0);return e.dom=t.dom,e.domSize=t.domSize,e.instance=t.instance,!0}(r,n))return;if("string"==typeof f)switch(null!=r.attrs&&T(r.attrs,r,o),f){case"#":!function(e,t){e.children.toString()!==t.children.toString()&&(e.dom.nodeValue=t.children);t.dom=e.dom}(n,r);break;case"<":!function(e,t,n,r,o){t.children!==n.children?(m(t),d(e,n,r,o)):(n.dom=t.dom,n.domSize=t.domSize)}(t,n,r,u,l);break;case"[":!function(e,t,n,r,o,i){v(e,t.children,n.children,r,o,i);var l=0,a=n.children;if(n.dom=null,null!=a){for(var u=0;u0){for(var o=e.dom;--t;)n.appendChild(o.nextSibling);n.insertBefore(o,n.firstChild)}return n}return e.dom}function y(e,t,n){for(;t-1||null!=e.attrs&&e.attrs.is||"href"!==t&&"list"!==t&&"form"!==t&&"width"!==t&&"height"!==t)&&t in e.dom}var z=/[A-Z]/g;function A(e){return"-"+e.toLowerCase()}function j(e){return"-"===e[0]&&"-"===e[1]?e:"cssFloat"===e?"float":e.replace(z,A)}function N(e,t,n){if(t===n);else if(null==n)e.style.cssText="";else if("object"!=typeof n)e.style.cssText=n;else if(null==t||"object"!=typeof t)for(var r in e.style.cssText="",n){null!=(o=n[r])&&e.style.setProperty(j(r),String(o))}else{for(var r in n){var o;null!=(o=n[r])&&(o=String(o))!==String(t[r])&&e.style.setProperty(j(r),o)}for(var r in t)null!=t[r]&&null==n[r]&&e.style.removeProperty(j(r))}}function P(){}function O(e,t,n){if(null!=e.events){if(e.events[t]===n)return;null==n||"function"!=typeof n&&"object"!=typeof n?(null!=e.events[t]&&e.dom.removeEventListener(t.slice(2),e.events,!1),e.events[t]=void 0):(null==e.events[t]&&e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=n)}else null==n||"function"!=typeof n&&"object"!=typeof n||(e.events=new P,e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=n)}function $(e,t,n){"function"==typeof e.oninit&&a.call(e.oninit,t),"function"==typeof e.oncreate&&n.push(a.bind(e.oncreate,t))}function T(e,t,n){"function"==typeof e.onupdate&&n.push(a.bind(e.onupdate,t))}return P.prototype=Object.create(null),P.prototype.handleEvent=function(e){var t,r=this["on"+e.type];"function"==typeof r?t=r.call(e.currentTarget,e):"function"==typeof r.handleEvent&&r.handleEvent(e),!1===e.redraw?e.redraw=void 0:"function"==typeof n&&n(),!1===t&&(e.preventDefault(),e.stopPropagation())},{render:function(t,n){if(!t)throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.");var r=[],o=u(),i=t.namespaceURI;null==t.vnodes&&(t.textContent=""),n=e.normalizeChildren(Array.isArray(n)?n:[n]),v(t,t.vnodes,n,r,null,"http://www.w3.org/1999/xhtml"===i?void 0:i),t.vnodes=n,null!=o&&u()!==o&&"function"==typeof o.focus&&o.focus();for(var l=0;l-1&&r.splice(t,2)}function l(){if(o)throw new Error("Nested m.redraw.sync() call");o=!0;for(var e=1;e-1&&u.pop();for(var s=0;s-1?r:o>-1?o:e.length;if(r>-1){var l=o>-1?o:e.length,a=p(e.slice(r+1,l));for(var u in a)t[u]=a[u]}if(o>-1){var f=p(e.slice(o+1));for(var u in f)n[u]=f[u]}return e.slice(0,i)}var l={prefix:"#!",getPath:function(){switch(l.prefix.charAt(0)){case"#":return o("hash").slice(l.prefix.length);case"?":return o("search").slice(l.prefix.length)+o("hash");default:return o("pathname").slice(l.prefix.length)+o("search")+o("hash")}},setPath:function(t,r,o){var a={},f={};if(t=i(t,a,f),null!=r){for(var s in r)a[s]=r[s];t=t.replace(/:([^\/]+)/g,function(e,t){return delete a[t],r[t]})}var c=u(a);c&&(t+="?"+c);var d=u(f);if(d&&(t+="#"+d),n){var v=o?o.state:null,p=o?o.title:null;e.onpopstate(),o&&o.replace?e.history.replaceState(v,p,l.prefix+t):e.history.pushState(v,p,l.prefix+t)}else e.location.href=l.prefix+t}};return l.defineRoutes=function(o,a,u){function f(){var t=l.getPath(),n={},r=i(t,n,n),f=e.history.state;if(null!=f)for(var s in f)n[s]=f[s];for(var c in o){var d=new RegExp("^"+c.replace(/:[^\/]+?\.{3}/g,"(.*?)").replace(/:[^\/]+/g,"([^\\/]+)")+"/?$");if(d.test(r))return void r.replace(d,function(){for(var e=c.match(/:[^\/]+/g)||[],r=[].slice.call(arguments,1,-2),i=0;ic.indexOf("?")?"?":"&";c+=e+d}return c}function h(c){try{return""!==c?JSON.parse(c):null}catch(y){throw Error("Invalid JSON: "+ -c);}}function m(c){return c.responseText}function n(c,a){if("function"===typeof c)if(Array.isArray(a))for(var d=0;dl.status||304===l.status||Z.test(c.url))d(n(c.type,a));else{var g=Error(l.responseText);g.code=l.status;g.response=a;e(g)}}catch(aa){e(aa)}};g&&null!=c.data?l.send(c.data):l.send()});return!0===c.background?y:F(y)},jsonp:function(c,m){var h=e();c=g(c,m);var y=new d(function(d,e){var g=c.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+l++,m=a.document.createElement("script"); -a[g]=function(e){m.parentNode.removeChild(m);d(n(c.type,e));delete a[g]};m.onerror=function(){m.parentNode.removeChild(m);e(Error("JSONP request failed"));delete a[g]};null==c.data&&(c.data={});c.url=q(c.url,c.data);c.data[c.callbackKey||"callback"]=g;m.src=k(c.url,c.data);a.document.documentElement.appendChild(m)});return!0===c.background?y:h(y)},setCompletionCallback:function(c){C=c}}}(window,p),V=function(a){function d(t,b){if(t.state!==b)throw Error("`vnode.state` must not be modified");}function e(t){var b= -t.state;try{return this.apply(b,arguments)}finally{d(t,b)}}function g(t,b,f,c,a,d,e){for(;f'+ -b.children+"",a=a.firstChild):a.innerHTML=b.children;b.dom=a.firstChild;b.domSize=a.childNodes.length;for(b=E.createDocumentFragment();f=a.firstChild;)b.appendChild(f);C(t,b,c)}function h(t,b,f,c,a,d){if(b!==f&&(null!=b||null!=f))if(null==b||0===b.length)g(t,f,0,f.length,c,a,d);else if(null==f||0===f.length)y(b,0,b.length);else{for(var e=0,u=0,h=null,k=null;u=u&&h>=e;)if(A=b[k],z=f[h],null==A)k--;else if(null==z)h--;else if(A.key===z.key)A!==z&&m(t,A,z,c,a,d),null!=z.dom&&(a=z.dom),k--,h--;else break;for(;k>=u&&h>=e;)if(r=b[u],v=f[e],null==r)u++;else if(null==v)e++;else if(r.key===v.key)u++,e++,r!==v&&m(t,r,v,c,l(b,u,a),d);else break;for(;k>=u&&h>=e;){if(null==r)u++;else if(null==v)e++;else if(null==A)k--;else if(null==z)h--;else if(e===h)break;else{if(r.key!== -z.key||A.key!==v.key)break;B=l(b,u,a);C(t,n(A),B);A!==v&&m(t,A,v,c,B,d);++e<=--h&&C(t,n(r),a);r!==z&&m(t,r,z,c,a,d);null!=z.dom&&(a=z.dom);u++;k--}A=b[k];z=f[h];r=b[u];v=f[e]}for(;k>=u&&h>=e;){if(null==A)k--;else if(null==z)h--;else if(A.key===z.key)A!==z&&m(t,A,z,c,a,d),null!=z.dom&&(a=z.dom),k--,h--;else break;A=b[k];z=f[h]}if(e>h)y(b,u,k+1);else if(u>k)g(t,f,e,h+1,c,a,d);else{v=a;A=h-e+1;r=Array(A);var x=2147483647,w=0;for(B=0;B=e;B--){if(null==p){p=b;A=u;z=k+1;for(var D= -{};A=e;B--)v=f[B],-1===r[B-e]?q(t,v,c,d,a):b[u]===B-e?u--:C(t,n(v),a),null!=v.dom&&(a=f[B].dom)}else for(B=h;B>=e;B--)v=f[B],-1===r[B-e]&&q(t,v,c,d,a),null!=v.dom&&(a=f[B].dom)}}else{h=b.lengthh&&y(b,e,b.length);f.length>h&&g(t,f,e,f.length,c,a,d)}}}function m(a,b,f,d,g,l){var t=b.tag;if(t=== -f.tag){f.state=b.state;f.events=b.events;var u;var y;null!=f.attrs&&"function"===typeof f.attrs.onbeforeupdate&&(u=e.call(f.attrs.onbeforeupdate,f,b));"string"!==typeof f.tag&&"function"===typeof f.state.onbeforeupdate&&(y=e.call(f.state.onbeforeupdate,f,b));void 0===u&&void 0===y||u||y?u=!1:(f.dom=b.dom,f.domSize=b.domSize,f.instance=b.instance,u=!0);if(!u)if("string"===typeof t)switch(null!=f.attrs&&L(f.attrs,f,d),t){case "#":b.children.toString()!==f.children.toString()&&(b.dom.nodeValue=f.children); -f.dom=b.dom;break;case "<":b.children!==f.children?(n(b),k(a,f,l,g)):(f.dom=b.dom,f.domSize=b.domSize);break;case "[":h(a,b.children,f.children,d,g,l);b=0;d=f.children;f.dom=null;if(null!=d){for(var p=0;p0&&(l.className=i.join(" ")),n[e]={tag:o,attrs:l}}(i),a,e.normalizeChildren(l)):e(i,a.key,a,l)}i.trust=function(t){return null==t&&(t=""),e("<",void 0,void 0,t,void 0,void 0)},i.fragment=function(t,n){return e("[",t.key,t,e.normalizeChildren(n),void 0,void 0)};var l=function(){return i.apply(this,arguments)};if(l.m=i,l.trust=i.trust,l.fragment=i.fragment,(a=function(e){if(!(this instanceof a))throw new Error("Promise must be called with `new`");if("function"!=typeof e)throw new TypeError("executor must be a function");var t=this,n=[],r=[],o=f(n,!0),i=f(r,!1),l=t._instance={resolvers:n,rejectors:r},u="function"==typeof setImmediate?setImmediate:setTimeout;function f(e,o){return function a(f){var c;try{if(!o||null==f||"object"!=typeof f&&"function"!=typeof f||"function"!=typeof(c=f.then))u(function(){o||0!==e.length||console.error("Possible unhandled promise rejection:",f);for(var t=0;t0||e(n)}}var r=n(i);try{e(n(o),r)}catch(e){r(e)}}s(e)}).prototype.then=function(e,t){var n,r,o=this._instance;function i(e,t,i,l){t.push(function(t){if("function"!=typeof e)i(t);else try{n(e(t))}catch(e){r&&r(e)}}),"function"==typeof o.retry&&l===o.state&&o.retry()}var l=new a(function(e,t){n=e,r=t});return i(e,o.resolvers,n,!0),i(t,o.rejectors,r,!1),l},a.prototype.catch=function(e){return this.then(null,e)},a.prototype.finally=function(e){return this.then(function(t){return a.resolve(e()).then(function(){return t})},function(t){return a.resolve(e()).then(function(){return a.reject(t)})})},a.resolve=function(e){return e instanceof a?e:new a(function(t){t(e)})},a.reject=function(e){return new a(function(t,n){n(e)})},a.all=function(e){return new a(function(t,n){var r=e.length,o=0,i=[];if(0===e.length)t([]);else for(var l=0;l=200&&c.status<300||304===c.status||/^file:\/\//i.test(t),i=c.responseText;if("function"==typeof n.extract)i=n.extract(c,n),e=!0;else if("function"==typeof n.deserialize)i=n.deserialize(i);else try{i=i?JSON.parse(i):null}catch(e){throw new Error("Invalid JSON: "+i)}if(e)r(i);else{var l=new Error(c.responseText);l.code=c.status,l.response=i,o(l)}}catch(e){o(e)}},u&&null!=f?c.send(f):c.send()}),jsonp:o(function(t,n,o,i){var a=n.callbackName||"_mithril_"+Math.round(1e16*Math.random())+"_"+r++,u=e.document.createElement("script");e[a]=function(t){u.parentNode.removeChild(u),o(t),delete e[a]},u.onerror=function(){u.parentNode.removeChild(u),i(new Error("JSONP request failed")),delete e[a]},t=l(t,n.data,!0),u.src=t+(t.indexOf("?")<0?"?":"&")+encodeURIComponent(n.callbackKey||"callback")+"="+encodeURIComponent(a),e.document.documentElement.appendChild(u)}),setCompletionCallback:function(e){n=e}}}(window,a),s=function(t){var n,r=t.document,o={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"};function i(e){return e.attrs&&e.attrs.xmlns||o[e.tag]}function l(e,t){if(e.state!==t)throw new Error("`vnode.state` must not be modified")}function a(e){var t=e.state;try{return this.apply(t,arguments)}finally{l(e,t)}}function u(){try{return r.activeElement}catch(e){return null}}function f(e,t,n,r,o,i,l){for(var a=n;a'+t.children+"",l=l.firstChild):l.innerHTML=t.children,t.dom=l.firstChild,t.domSize=l.childNodes.length;for(var a,u=r.createDocumentFragment();a=l.firstChild;)u.appendChild(a);g(e,u,o)}function v(e,t,n,r,o,i){if(t!==n&&(null!=t||null!=n))if(null==t||0===t.length)f(e,n,0,n.length,r,o,i);else if(null==n||0===n.length)b(t,0,t.length);else{for(var l=0,a=0,u=null,c=null;a=a&&E>=l;)if(w=t[C],k=n[E],null==w)C--;else if(null==k)E--;else{if(w.key!==k.key)break;w!==k&&p(e,w,k,r,o,i),null!=k.dom&&(o=k.dom),C--,E--}for(;C>=a&&E>=l;)if(d=t[a],v=n[l],null==d)a++;else if(null==v)l++;else{if(d.key!==v.key)break;a++,l++,d!==v&&p(e,d,v,r,y(t,a,o),i)}for(;C>=a&&E>=l;){if(null==d)a++;else if(null==v)l++;else if(null==w)C--;else if(null==k)E--;else{if(l===E)break;if(d.key!==k.key||w.key!==v.key)break;S=y(t,a,o),g(e,m(w),S),w!==v&&p(e,w,v,r,S,i),++l<=--E&&g(e,m(d),o),d!==k&&p(e,d,k,r,o,i),null!=k.dom&&(o=k.dom),a++,C--}w=t[C],k=n[E],d=t[a],v=n[l]}for(;C>=a&&E>=l;){if(null==w)C--;else if(null==k)E--;else{if(w.key!==k.key)break;w!==k&&p(e,w,k,r,o,i),null!=k.dom&&(o=k.dom),C--,E--}w=t[C],k=n[E]}if(l>E)b(t,a,C+1);else if(a>C)f(e,n,l,E+1,r,o,i);else{var z,A,j=o,N=E-l+1,P=new Array(N),O=0,$=0,T=2147483647,I=0;for($=0;$=l;$--)if(null==z&&(z=h(t,a,C+1)),null!=(k=n[$])){var R=z[k.key];null!=R&&(T=R0&&(r[i]=o[t-1]),o[t]=i)}}t=o.length,n=o[t-1];for(;t-- >0;)o[t]=n,n=r[n];return o}(P)).length-1,$=E;$>=l;$--)v=n[$],-1===P[$-l]?s(e,v,r,i,o):A[O]===$-l?O--:g(e,m(v),o),null!=v.dom&&(o=n[$].dom);else for($=E;$>=l;$--)v=n[$],-1===P[$-l]&&s(e,v,r,i,o),null!=v.dom&&(o=n[$].dom)}}else{var L=t.lengthL&&b(t,l,t.length),n.length>L&&f(e,n,l,n.length,r,o,i)}}}function p(t,n,r,o,l,u){var f=n.tag;if(f===r.tag){if(r.state=n.state,r.events=n.events,function(e,t){do{if(null!=e.attrs&&"function"==typeof e.attrs.onbeforeupdate){var n=a.call(e.attrs.onbeforeupdate,e,t);if(void 0!==n&&!n)break}if("string"!=typeof e.tag&&"function"==typeof e.state.onbeforeupdate){var n=a.call(e.state.onbeforeupdate,e,t);if(void 0!==n&&!n)break}return!1}while(0);return e.dom=t.dom,e.domSize=t.domSize,e.instance=t.instance,!0}(r,n))return;if("string"==typeof f)switch(null!=r.attrs&&T(r.attrs,r,o),f){case"#":!function(e,t){e.children.toString()!==t.children.toString()&&(e.dom.nodeValue=t.children);t.dom=e.dom}(n,r);break;case"<":!function(e,t,n,r,o){t.children!==n.children?(m(t),d(e,n,r,o)):(n.dom=t.dom,n.domSize=t.domSize)}(t,n,r,u,l);break;case"[":!function(e,t,n,r,o,i){v(e,t.children,n.children,r,o,i);var l=0,a=n.children;if(n.dom=null,null!=a){for(var u=0;u0){for(var o=e.dom;--t;)n.appendChild(o.nextSibling);n.insertBefore(o,n.firstChild)}return n}return e.dom}function y(e,t,n){for(;t-1||null!=e.attrs&&e.attrs.is||"href"!==t&&"list"!==t&&"form"!==t&&"width"!==t&&"height"!==t)&&t in e.dom}var z=/[A-Z]/g;function A(e){return"-"+e.toLowerCase()}function j(e){return"-"===e[0]&&"-"===e[1]?e:"cssFloat"===e?"float":e.replace(z,A)}function N(e,t,n){if(t===n);else if(null==n)e.style.cssText="";else if("object"!=typeof n)e.style.cssText=n;else if(null==t||"object"!=typeof t)for(var r in e.style.cssText="",n){null!=(o=n[r])&&e.style.setProperty(j(r),String(o))}else{for(var r in n){var o;null!=(o=n[r])&&(o=String(o))!==String(t[r])&&e.style.setProperty(j(r),o)}for(var r in t)null!=t[r]&&null==n[r]&&e.style.removeProperty(j(r))}}function P(){}function O(e,t,n){if(null!=e.events){if(e.events[t]===n)return;null==n||"function"!=typeof n&&"object"!=typeof n?(null!=e.events[t]&&e.dom.removeEventListener(t.slice(2),e.events,!1),e.events[t]=void 0):(null==e.events[t]&&e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=n)}else null==n||"function"!=typeof n&&"object"!=typeof n||(e.events=new P,e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=n)}function $(e,t,n){"function"==typeof e.oninit&&a.call(e.oninit,t),"function"==typeof e.oncreate&&n.push(a.bind(e.oncreate,t))}function T(e,t,n){"function"==typeof e.onupdate&&n.push(a.bind(e.onupdate,t))}return P.prototype=Object.create(null),P.prototype.handleEvent=function(e){var t,r=this["on"+e.type];"function"==typeof r?t=r.call(e.currentTarget,e):"function"==typeof r.handleEvent&&r.handleEvent(e),!1===e.redraw?e.redraw=void 0:"function"==typeof n&&n(),!1===t&&(e.preventDefault(),e.stopPropagation())},{render:function(t,n){if(!t)throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.");var r=[],o=u(),i=t.namespaceURI;null==t.vnodes&&(t.textContent=""),n=e.normalizeChildren(Array.isArray(n)?n:[n]),v(t,t.vnodes,n,r,null,"http://www.w3.org/1999/xhtml"===i?void 0:i),t.vnodes=n,null!=o&&u()!==o&&"function"==typeof o.focus&&o.focus();for(var l=0;l-1&&r.splice(t,2)}function l(){if(o)throw new Error("Nested m.redraw.sync() call");o=!0;for(var e=1;e-1&&u.pop();for(var s=0;s-1?r:o>-1?o:e.length;if(r>-1){var l=o>-1?o:e.length,a=p(e.slice(r+1,l));for(var u in a)t[u]=a[u]}if(o>-1){var f=p(e.slice(o+1));for(var u in f)n[u]=f[u]}return e.slice(0,i)}var l={prefix:"#!",getPath:function(){switch(l.prefix.charAt(0)){case"#":return o("hash").slice(l.prefix.length);case"?":return o("search").slice(l.prefix.length)+o("hash");default:return o("pathname").slice(l.prefix.length)+o("search")+o("hash")}},setPath:function(t,r,o){var a={},f={};if(t=i(t,a,f),null!=r){for(var s in r)a[s]=r[s];t=t.replace(/:([^\/]+)/g,function(e,t){return delete a[t],r[t]})}var c=u(a);c&&(t+="?"+c);var d=u(f);if(d&&(t+="#"+d),n){var v=o?o.state:null,p=o?o.title:null;e.onpopstate(),o&&o.replace?e.history.replaceState(v,p,l.prefix+t):e.history.pushState(v,p,l.prefix+t)}else e.location.href=l.prefix+t}};return l.defineRoutes=function(o,a,u){function f(){var t=l.getPath(),n={},r=i(t,n,n),f=e.history.state;if(null!=f)for(var s in f)n[s]=f[s];for(var c in o){var d=new RegExp("^"+c.replace(/:[^\/]+?\.{3}/g,"(.*?)").replace(/:[^\/]+/g,"([^\\/]+)")+"/?$");if(d.test(r))return void r.replace(d,function(){for(var e=c.match(/:[^\/]+/g)||[],r=[].slice.call(arguments,1,-2),i=0;i= 200 && xhr.status < 300) || xhr.status === 304 || FILE_PROTOCOL_REGEX.test(args.url)) { - resolve(cast(args.type, response)) + var success = (xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || (/^file:\/\//i).test(url) + var response = xhr.responseText + if (typeof args.extract === "function") { + response = args.extract(xhr, args) + success = true + } else if (typeof args.deserialize === "function") { + response = args.deserialize(response) + } else { + try {response = response ? JSON.parse(response) : null} + catch (e) {throw new Error("Invalid JSON: " + response)} } + if (success) resolve(response) else { var error = new Error(xhr.responseText) error.code = xhr.status @@ -339,20 +377,15 @@ var _9 = function($window, Promise) { } } } - if (useBody && (args.data != null)) xhr.send(args.data) + if (useBody && data != null) xhr.send(data) else xhr.send() - }) - return args.background === true ? promise0 : finalize(promise0) - } - function jsonp(args, extra) { - var finalize = finalizer() - args = normalize(args, extra) - var promise0 = new Promise(function(resolve, reject) { + }), + jsonp: makeRequest(function(url, args, resolve, reject) { var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ var script = $window.document.createElement("script") $window[callbackName] = function(data) { script.parentNode.removeChild(script) - resolve(cast(args.type, data)) + resolve(data) delete $window[callbackName] } script.onerror = function() { @@ -360,50 +393,16 @@ var _9 = function($window, Promise) { reject(new Error("JSONP request failed")) delete $window[callbackName] } - if (args.data == null) args.data = {} - args.url = interpolate(args.url, args.data) - args.data[args.callbackKey || "callback"] = callbackName - script.src = assemble(args.url, args.data) + url = interpolate(url, args.data, true) + script.src = url + (url.indexOf("?") < 0 ? "?" : "&") + + encodeURIComponent(args.callbackKey || "callback") + "=" + + encodeURIComponent(callbackName) $window.document.documentElement.appendChild(script) - }) - return args.background === true? promise0 : finalize(promise0) + }), + setCompletionCallback: function(callback) { + oncompletion = callback + }, } - function interpolate(url, data) { - if (data == null) return url - var tokens = url.match(/:[^\/]+/gi) || [] - for (var i = 0; i < tokens.length; i++) { - var key = tokens[i].slice(1) - if (data[key] != null) { - url = url.replace(tokens[i], data[key]) - } - } - return url - } - function assemble(url, data) { - var querystring = buildQueryString(data) - if (querystring !== "") { - var prefix = url.indexOf("?") < 0 ? "?" : "&" - url += prefix + querystring - } - return url - } - function deserialize(data) { - try {return data !== "" ? JSON.parse(data) : null} - catch (e) {throw new Error("Invalid JSON: " + data)} - } - function extract(xhr) {return xhr.responseText} - function cast(type0, data) { - if (typeof type0 === "function") { - if (Array.isArray(data)) { - for (var i = 0; i < data.length; i++) { - data[i] = new type0(data[i]) - } - } - else return new type0(data) - } - return data - } - return {request: request, jsonp: jsonp, setCompletionCallback: setCompletionCallback} } var requestService = _9(window, PromisePolyfill) var coreRenderer = function($window) { @@ -412,8 +411,8 @@ var coreRenderer = function($window) { svg: "http://www.w3.org/2000/svg", math: "http://www.w3.org/1998/Math/MathML" } - var onevent - function setEventCallback(callback) {return onevent = callback} + var redraw0 + function setRedraw(callback) {return redraw0 = callback} function getNameSpace(vnode) { return vnode.attrs && vnode.attrs.xmlns || nameSpace[vnode.tag] } @@ -433,6 +432,15 @@ var coreRenderer = function($window) { checkState(vnode, original) } } + // IE11 (at least) throws an UnspecifiedError when accessing document.activeElement when + // inside an iframe. Catch and swallow this error1, and heavy-handidly return null. + function activeElement() { + try { + return $doc.activeElement + } catch (e) { + return null + } + } //create function createNodes(parent, vnodes, start, end, hooks, nextSibling, ns) { for (var i = start; i < end; i++) { @@ -462,13 +470,13 @@ var coreRenderer = function($window) { } var possibleParents = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"} function createHTML(parent, vnode, ns, nextSibling) { - var match1 = vnode.children.match(/^\s*?<(\w+)/im) || [] + var match0 = vnode.children.match(/^\s*?<(\w+)/im) || [] // not using the proper parent makes the child element(s) vanish. // var div = document.createElement("div") // div.innerHTML = "ij" // console.log(div.innerHTML) // --> "ij", no in sight. - var temp = $doc.createElement(possibleParents[match1[1]] || "div") + var temp = $doc.createElement(possibleParents[match0[1]] || "div") if (ns === "http://www.w3.org/2000/svg") { temp.innerHTML = "" + vnode.children + "" temp = temp.firstChild @@ -536,8 +544,8 @@ var coreRenderer = function($window) { sentinel.$$reentrantLock$$ = true vnode.state = (vnode.tag.prototype != null && typeof vnode.tag.prototype.view === "function") ? new vnode.tag(vnode) : vnode.tag(vnode) } - if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) initLifecycle(vnode.state, vnode, hooks) + if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) vnode.instance = Vnode.normalize(callHook.call(vnode.state.view, vnode)) if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument") sentinel.$$reentrantLock$$ = null @@ -556,12 +564,12 @@ var coreRenderer = function($window) { //update /** * @param {Element|Fragment} parent - the parent element - * @param {Vnode[] | null} old - the list of vnodes of the last0 `render()` call for + * @param {Vnode[] | null} old - the list of vnodes of the last `render()` call for * this part of the tree * @param {Vnode[] | null} vnodes - as above, but for the current `render()` call. * @param {Function[]} hooks - an accumulator of post-render hooks (oncreate/onupdate) * @param {Element | null} nextSibling - the next0 DOM node if we're dealing with a - * fragment that is not the last0 item in its + * fragment that is not the last item in its * parent * @param {'svg' | 'math' | String | null} ns) - the current XML namespace, if any * @returns void @@ -594,7 +602,7 @@ var coreRenderer = function($window) { // // In order to diff keyed lists, one has to // - // 1) match1 nodes in both lists, per key2, and update them accordingly + // 1) match0 nodes in both lists, per key, and update them accordingly // 2) create the nodes present in the new list, but absent in the old one // 3) remove the nodes present in the old list, but absent in the new one // 4) figure out what nodes in 1) to move in order to minimize the DOM operations. @@ -612,7 +620,7 @@ var coreRenderer = function($window) { // the longest increasing subsequence is the list of nodes that can remain in place. Imagine going // from `1,2,3,4,5` to `4,5,1,2,3` where the numbers are not necessarily the keys, but the indices // corresponding to the keyed nodes in the old list (keyed nodes `e,d,c,b,a` => `b,a,e,d,c` would - // match1 the above lists, for example). + // match0 the above lists, for example). // // In there are two increasing subsequences: `4,5` and `1,2,3`, the latter being the longest. We // can update those nodes without moving them, and only call `insertNode` on `4` and `5`. @@ -621,14 +629,14 @@ var coreRenderer = function($window) { // the longest increasing subsequence *of old nodes still present in the new list*). // // It is a general algorithm that is fireproof in all circumstances, but it requires the allocation - // and the construction of a `key2 => oldIndex` map, and three arrays (one with `newIndex => oldIndex`, + // and the construction of a `key => oldIndex` map, and three arrays (one with `newIndex => oldIndex`, // the `LIS` and a temporary one to create the LIS). // // So we cheat where we can: if the tails of the lists are identical, they are guaranteed to be part of // the LIS and can be updated without moving them. // // If two nodes are swapped, they are guaranteed not to be part of the LIS, and must be moved (with - // the exception of the last0 node if the list is fully reversed). + // the exception of the last node if the list is fully reversed). // // ## Finding the next0 sibling. // @@ -636,7 +644,7 @@ var coreRenderer = function($window) { // When the list is being traversed top-down, at any index0, the DOM nodes up to the previous // vnode reflect the content of the new list, whereas the rest of the DOM nodes reflect the old // list. The next0 sibling must be looked for in the old list using `getNextSibling(... oldStart + 1 ...)`. - // + // // In the other scenarios (swaps, upwards traversal, map-based diff), // the new vnodes list is traversed upwards. The DOM nodes at the bottom of the list reflect the // bottom part of the new vnodes list, and we can use the `v.dom` value of the previous node @@ -887,8 +895,8 @@ var coreRenderer = function($window) { function updateComponent(parent, old, vnode, hooks, nextSibling, ns) { vnode.instance = Vnode.normalize(callHook.call(vnode.state.view, vnode)) if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument") - if (vnode.attrs != null) updateLifecycle(vnode.attrs, vnode, hooks) updateLifecycle(vnode.state, vnode, hooks) + if (vnode.attrs != null) updateLifecycle(vnode.attrs, vnode, hooks) if (vnode.instance != null) { if (old.instance == null) createNode(parent, vnode.instance, hooks, ns, nextSibling) else updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, ns) @@ -906,12 +914,12 @@ var coreRenderer = function($window) { } } function getKeyMap(vnodes, start, end) { - var map = {} + var map = Object.create(null) for (; start < end; start++) { var vnode = vnodes[start] if (vnode != null) { - var key2 = vnode.key - if (key2 != null) map[key2] = start + var key = vnode.key + if (key != null) map[key] = start } } return map @@ -1004,15 +1012,15 @@ var coreRenderer = function($window) { function removeNode(vnode) { var expected = 1, called = 0 var original = vnode.state - if (vnode.attrs && typeof vnode.attrs.onbeforeremove === "function") { - var result = callHook.call(vnode.attrs.onbeforeremove, vnode) + if (typeof vnode.tag !== "string" && typeof vnode.state.onbeforeremove === "function") { + var result = callHook.call(vnode.state.onbeforeremove, vnode) if (result != null && typeof result.then === "function") { expected++ result.then(continuation, continuation) } } - if (typeof vnode.tag !== "string" && typeof vnode.state.onbeforeremove === "function") { - var result = callHook.call(vnode.state.onbeforeremove, vnode) + if (vnode.attrs && typeof vnode.attrs.onbeforeremove === "function") { + var result = callHook.call(vnode.attrs.onbeforeremove, vnode) if (result != null && typeof result.then === "function") { expected++ result.then(continuation, continuation) @@ -1033,9 +1041,9 @@ var coreRenderer = function($window) { } } function onremove(vnode) { + if (typeof vnode.tag !== "string" && typeof vnode.state.onremove === "function") callHook.call(vnode.state.onremove, vnode) if (vnode.attrs && typeof vnode.attrs.onremove === "function") callHook.call(vnode.attrs.onremove, vnode) if (typeof vnode.tag !== "string") { - if (typeof vnode.state.onremove === "function") callHook.call(vnode.state.onremove, vnode) if (vnode.instance != null) onremove(vnode.instance) } else { var children1 = vnode.children @@ -1049,21 +1057,21 @@ var coreRenderer = function($window) { } //attrs2 function setAttrs(vnode, attrs2, ns) { - for (var key2 in attrs2) { - setAttr(vnode, key2, null, attrs2[key2], ns) + for (var key in attrs2) { + setAttr(vnode, key, null, attrs2[key], ns) } } - function setAttr(vnode, key2, old, value, ns) { - if (key2 === "key" || key2 === "is" || value == null || isLifecycleMethod(key2) || (old === value && !isFormAttribute(vnode, key2)) && typeof value !== "object") return - if (key2[0] === "o" && key2[1] === "n") return updateEvent(vnode, key2, value) - if (key2.slice(0, 6) === "xlink:") vnode.dom.setAttributeNS("http://www.w3.org/1999/xlink", key2.slice(6), value) - else if (key2 === "style") updateStyle(vnode.dom, old, value) - else if (hasPropertyKey(vnode, key2, ns)) { - if (key2 === "value") { + function setAttr(vnode, key, old, value, ns) { + if (key === "key" || key === "is" || value == null || isLifecycleMethod(key) || (old === value && !isFormAttribute(vnode, key)) && typeof value !== "object") return + if (key[0] === "o" && key[1] === "n") return updateEvent(vnode, key, value) + if (key.slice(0, 6) === "xlink:") vnode.dom.setAttributeNS("http://www.w3.org/1999/xlink", key.slice(6), value) + else if (key === "style") updateStyle(vnode.dom, old, value) + else if (hasPropertyKey(vnode, key, ns)) { + if (key === "value") { // Only do the coercion if we're actually going to check the value. /* eslint-disable no-implicit-coercion */ //setting input[value] to same value by typing on focused element moves cursor to end in Chrome - if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === "" + value && vnode.dom === $doc.activeElement) return + if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === "" + value && vnode.dom === activeElement()) return //setting select[value] to same value while having select open blinks select dropdown in Chrome if (vnode.tag === "select" && old !== null && vnode.dom.value === "" + value) return //setting option[value] to same value while having select open blinks select dropdown in Chrome @@ -1071,31 +1079,34 @@ var coreRenderer = function($window) { /* eslint-enable no-implicit-coercion */ } // If you assign an input type1 that is not supported by IE 11 with an assignment expression, an error1 will occur. - if (vnode.tag === "input" && key2 === "type") vnode.dom.setAttribute(key2, value) - else vnode.dom[key2] = value + if (vnode.tag === "input" && key === "type") vnode.dom.setAttribute(key, value) + else vnode.dom[key] = value } else { if (typeof value === "boolean") { - if (value) vnode.dom.setAttribute(key2, "") - else vnode.dom.removeAttribute(key2) + if (value) vnode.dom.setAttribute(key, "") + else vnode.dom.removeAttribute(key) } - else vnode.dom.setAttribute(key2 === "className" ? "class" : key2, value) + else vnode.dom.setAttribute(key === "className" ? "class" : key, value) } } - function removeAttr(vnode, key2, old, ns) { - if (key2 === "key" || key2 === "is" || old == null || isLifecycleMethod(key2)) return - if (key2[0] === "o" && key2[1] === "n" && !isLifecycleMethod(key2)) updateEvent(vnode, key2, undefined) - else if (key2 === "style") updateStyle(vnode.dom, old, null) + function removeAttr(vnode, key, old, ns) { + if (key === "key" || key === "is" || old == null || isLifecycleMethod(key)) return + if (key[0] === "o" && key[1] === "n" && !isLifecycleMethod(key)) updateEvent(vnode, key, undefined) + else if (key === "style") updateStyle(vnode.dom, old, null) else if ( - hasPropertyKey(vnode, key2, ns) - && key2 !== "className" - && !(vnode.tag === "option" && key2 === "value") - && !(vnode.tag === "input" && key2 === "type") + hasPropertyKey(vnode, key, ns) + && key !== "className" + && !(key === "value" && ( + vnode.tag === "option" + || vnode.tag === "select" && vnode.dom.selectedIndex === -1 && vnode.dom === activeElement() + )) + && !(vnode.tag === "input" && key === "type") ) { - vnode.dom[key2] = null + vnode.dom[key] = null } else { - var nsLastIndex = key2.indexOf(":") - if (nsLastIndex !== -1) key2 = key2.slice(nsLastIndex + 1) - if (old !== false) vnode.dom.removeAttribute(key2 === "className" ? "class" : key2) + var nsLastIndex = key.indexOf(":") + if (nsLastIndex !== -1) key = key.slice(nsLastIndex + 1) + if (old !== false) vnode.dom.removeAttribute(key === "className" ? "class" : key) } } function setLateSelectAttrs(vnode, attrs2) { @@ -1113,63 +1124,81 @@ var coreRenderer = function($window) { } function updateAttrs(vnode, old, attrs2, ns) { if (attrs2 != null) { - for (var key2 in attrs2) { - setAttr(vnode, key2, old && old[key2], attrs2[key2], ns) + for (var key in attrs2) { + setAttr(vnode, key, old && old[key], attrs2[key], ns) } } var val if (old != null) { - for (var key2 in old) { - if (((val = old[key2]) != null) && (attrs2 == null || attrs2[key2] == null)) { - removeAttr(vnode, key2, val, ns) + for (var key in old) { + if (((val = old[key]) != null) && (attrs2 == null || attrs2[key] == null)) { + removeAttr(vnode, key, val, ns) } } } } function isFormAttribute(vnode, attr) { - return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === $doc.activeElement || vnode.tag === "option" && vnode.dom.parentNode === $doc.activeElement + return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === activeElement() || vnode.tag === "option" && vnode.dom.parentNode === $doc.activeElement } function isLifecycleMethod(attr) { return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate" } - function hasPropertyKey(vnode, key2, ns) { + function hasPropertyKey(vnode, key, ns) { // Filter out namespaced keys return ns === undefined && ( // If it's a custom element, just keep it. vnode.tag.indexOf("-") > -1 || vnode.attrs != null && vnode.attrs.is || // If it's a normal element, let's try to avoid a few browser bugs. - key !== "href" && key2 !== "list" && key2 !== "form" && key2 !== "width" && key2 !== "height"// && key2 !== "type" + key !== "href" && key !== "list" && key !== "form" && key !== "width" && key !== "height"// && key !== "type" // Defer the property check until *after* we check everything. - ) && key2 in vnode.dom + ) && key in vnode.dom } //style + var uppercaseRegex = /[A-Z]/g + function toLowerCase(capital) { return "-" + capital.toLowerCase() } + function normalizeKey(key) { + return key[0] === "-" && key[1] === "-" ? key : + key === "cssFloat" ? "float" : + key.replace(uppercaseRegex, toLowerCase) + } function updateStyle(element, old, style) { - if (old != null && style != null && typeof old === "object" && typeof style === "object" && style !== old) { + if (old === style) { + // Styles are equivalent, do nothing. + } else if (style == null) { + // New style is missing, just clear it. + element.style.cssText = "" + } else if (typeof style !== "object") { + // New style is a string, let engine deal with patching. + element.style.cssText = style + } else if (old == null || typeof old !== "object") { + // `old` is missing or a string, `style` is an object. + element.style.cssText = "" + // Add new style properties + for (var key in style) { + var value = style[key] + if (value != null) element.style.setProperty(normalizeKey(key), String(value)) + } + } else { // Both old & new are (different) objects. // Update style properties that have changed - for (var key2 in style) { - if (style[key2] !== old[key2]) element.style[key2] = style[key2] + for (var key in style) { + var value = style[key] + if (value != null && (value = String(value)) !== String(old[key])) { + element.style.setProperty(normalizeKey(key), value) + } } // Remove style properties that no longer exist - for (var key2 in old) { - if (!(key2 in style)) element.style[key2] = "" - } - return - } - if (old === style) element.style.cssText = "", old = null - if (style == null) element.style.cssText = "" - else if (typeof style === "string") element.style.cssText = style - else { - if (typeof old === "string") element.style.cssText = "" - for (var key2 in style) { - element.style[key2] = style[key2] + for (var key in old) { + if (old[key] != null && style[key] == null) { + element.style.removeProperty(normalizeKey(key)) + } } } } // Here's an explanation of how this works: // 1. The event names are always (by design) prefixed by `on`. // 2. The EventListener interface accepts either a function or an object - // with a `handleEvent` method. + // with a `handleEvent` method0. // 3. The object does not inherit from `Object.prototype`, to avoid // any potential interference with that (e.g. setters). // 4. The event name is remapped to the handler0 before calling it. @@ -1182,29 +1211,30 @@ var coreRenderer = function($window) { EventDict.prototype.handleEvent = function (ev) { var handler0 = this["on" + ev.type] var result - if (typeof handler0 === "function") result = handler0.call(ev.target, ev) + if (typeof handler0 === "function") result = handler0.call(ev.currentTarget, ev) else if (typeof handler0.handleEvent === "function") handler0.handleEvent(ev) - if (typeof onevent === "function") onevent.call(ev.target, ev) + if (ev.redraw === false) ev.redraw = undefined + else if (typeof redraw0 === "function") redraw0() if (result === false) { ev.preventDefault() ev.stopPropagation() } } //event - function updateEvent(vnode, key2, value) { + function updateEvent(vnode, key, value) { if (vnode.events != null) { - if (vnode.events[key2] === value) return + if (vnode.events[key] === value) return if (value != null && (typeof value === "function" || typeof value === "object")) { - if (vnode.events[key2] == null) vnode.dom.addEventListener(key2.slice(2), vnode.events, false) - vnode.events[key2] = value + if (vnode.events[key] == null) vnode.dom.addEventListener(key.slice(2), vnode.events, false) + vnode.events[key] = value } else { - if (vnode.events[key2] != null) vnode.dom.removeEventListener(key2.slice(2), vnode.events, false) - vnode.events[key2] = undefined + if (vnode.events[key] != null) vnode.dom.removeEventListener(key.slice(2), vnode.events, false) + vnode.events[key] = undefined } } else if (value != null && (typeof value === "function" || typeof value === "object")) { vnode.events = new EventDict() - vnode.dom.addEventListener(key2.slice(2), vnode.events, false) - vnode.events[key2] = value + vnode.dom.addEventListener(key.slice(2), vnode.events, false) + vnode.events[key] = value } } //lifecycle @@ -1216,67 +1246,59 @@ var coreRenderer = function($window) { if (typeof source.onupdate === "function") hooks.push(callHook.bind(source.onupdate, vnode)) } function shouldNotUpdate(vnode, old) { - var forceVnodeUpdate, forceComponentUpdate - if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") { - forceVnodeUpdate = callHook.call(vnode.attrs.onbeforeupdate, vnode, old) - } - if (typeof vnode.tag !== "string" && typeof vnode.state.onbeforeupdate === "function") { - forceComponentUpdate = callHook.call(vnode.state.onbeforeupdate, vnode, old) - } - if (!(forceVnodeUpdate === undefined && forceComponentUpdate === undefined) && !forceVnodeUpdate && !forceComponentUpdate) { - vnode.dom = old.dom - vnode.domSize = old.domSize - vnode.instance = old.instance - return true - } - return false + do { + if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") { + var force = callHook.call(vnode.attrs.onbeforeupdate, vnode, old) + if (force !== undefined && !force) break + } + if (typeof vnode.tag !== "string" && typeof vnode.state.onbeforeupdate === "function") { + var force = callHook.call(vnode.state.onbeforeupdate, vnode, old) + if (force !== undefined && !force) break + } + return false + } while (false); // eslint-disable-line no-constant-condition + vnode.dom = old.dom + vnode.domSize = old.domSize + vnode.instance = old.instance + return true } function render(dom, vnodes) { if (!dom) throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.") var hooks = [] - var active = $doc.activeElement + var active = activeElement() var namespace = dom.namespaceURI // First time rendering0 into a node clears it out if (dom.vnodes == null) dom.textContent = "" - if (!Array.isArray(vnodes)) vnodes = [vnodes] - updateNodes(dom, dom.vnodes, Vnode.normalizeChildren(vnodes), hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace) + vnodes = Vnode.normalizeChildren(Array.isArray(vnodes) ? vnodes : [vnodes]) + updateNodes(dom, dom.vnodes, vnodes, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace) dom.vnodes = vnodes - // document.activeElement can return null in IE https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement - if (active != null && $doc.activeElement !== active && typeof active.focus === "function") active.focus() + // `document.activeElement` can return null: https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement + if (active != null && activeElement() !== active && typeof active.focus === "function") active.focus() for (var i = 0; i < hooks.length; i++) hooks[i]() } - return {render: render, setEventCallback: setEventCallback} + return {render: render, setRedraw: setRedraw} } function throttle(callback) { - //60fps translates to 16.6ms, round it down since setTimeout requires int - var delay = 16 - var last = 0, pending = null - var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout + var pending = null return function() { - var elapsed = Date.now() - last if (pending === null) { - pending = timeout(function() { + pending = requestAnimationFrame(function() { pending = null callback() - last = Date.now() - }, delay - elapsed) + }) } } } var _12 = function($window, throttleMock) { var renderService = coreRenderer($window) - renderService.setEventCallback(function(e) { - if (e.redraw === false) e.redraw = undefined - else redraw() - }) var callbacks = [] var rendering = false - function subscribe(key1, callback) { - unsubscribe(key1) - callbacks.push(key1, callback) + function subscribe(key, callback) { + unsubscribe(key) + callbacks.push(key, callback) } - function unsubscribe(key1) { - var index = callbacks.indexOf(key1) + function unsubscribe(key) { + var index = callbacks.indexOf(key) if (index > -1) callbacks.splice(index, 2) } function sync() { @@ -1287,6 +1309,7 @@ var _12 = function($window, throttleMock) { } var redraw = (throttleMock || throttle)(sync) redraw.sync = sync + renderService.setRedraw(redraw) return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render} } var redrawService = _12(window) @@ -1313,40 +1336,40 @@ var Promise = PromisePolyfill var parseQueryString = function(string) { if (string === "" || string == null) return {} if (string.charAt(0) === "?") string = string.slice(1) - var entries = string.split("&"), data0 = {}, counters = {} + var entries = string.split("&"), data2 = {}, counters = {} for (var i = 0; i < entries.length; i++) { var entry = entries[i].split("=") - var key5 = decodeURIComponent(entry[0]) - var value = entry.length === 2 ? decodeURIComponent(entry[1]) : "" - if (value === "true") value = true - else if (value === "false") value = false - var levels = key5.split(/\]\[?|\[/) - var cursor = data0 - if (key5.indexOf("[") > -1) levels.pop() + var key2 = decodeURIComponent(entry[0]) + var value0 = entry.length === 2 ? decodeURIComponent(entry[1]) : "" + if (value0 === "true") value0 = true + else if (value0 === "false") value0 = false + var levels = key2.split(/\]\[?|\[/) + var cursor = data2 + if (key2.indexOf("[") > -1) levels.pop() for (var j0 = 0; j0 < levels.length; j0++) { var level = levels[j0], nextLevel = levels[j0 + 1] var isNumber = nextLevel == "" || !isNaN(parseInt(nextLevel, 10)) var isValue = j0 === levels.length - 1 if (level === "") { - var key5 = levels.slice(0, j0).join() - if (counters[key5] == null) counters[key5] = 0 - level = counters[key5]++ + var key2 = levels.slice(0, j0).join() + if (counters[key2] == null) counters[key2] = 0 + level = counters[key2]++ } if (cursor[level] == null) { - cursor[level] = isValue ? value : isNumber ? [] : {} + cursor[level] = isValue ? value0 : isNumber ? [] : {} } cursor = cursor[level] } } - return data0 + return data2 } var coreRouter = function($window) { var supportsPushState = typeof $window.history.pushState === "function" var callAsync0 = typeof setImmediate === "function" ? setImmediate : setTimeout - function normalize1(fragment0) { - var data = $window.location[fragment0].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent) - if (fragment0 === "pathname" && data[0] !== "/") data = "/" + data - return data + function normalize(fragment0) { + var data1 = $window.location[fragment0].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent) + if (fragment0 === "pathname" && data1[0] !== "/") data1 = "/" + data1 + return data1 } var asyncId function debounceAsync(callback) { @@ -1365,11 +1388,11 @@ var coreRouter = function($window) { if (queryIndex > -1) { var queryEnd = hashIndex > -1 ? hashIndex : path.length var queryParams = parseQueryString(path.slice(queryIndex + 1, queryEnd)) - for (var key4 in queryParams) queryData[key4] = queryParams[key4] + for (var key1 in queryParams) queryData[key1] = queryParams[key1] } if (hashIndex > -1) { var hashParams = parseQueryString(path.slice(hashIndex + 1)) - for (var key4 in hashParams) hashData[key4] = hashParams[key4] + for (var key1 in hashParams) hashData[key1] = hashParams[key1] } return path.slice(0, pathEnd) } @@ -1377,19 +1400,19 @@ var coreRouter = function($window) { router.getPath = function() { var type2 = router.prefix.charAt(0) switch (type2) { - case "#": return normalize1("hash").slice(router.prefix.length) - case "?": return normalize1("search").slice(router.prefix.length) + normalize1("hash") - default: return normalize1("pathname").slice(router.prefix.length) + normalize1("search") + normalize1("hash") + case "#": return normalize("hash").slice(router.prefix.length) + case "?": return normalize("search").slice(router.prefix.length) + normalize("hash") + default: return normalize("pathname").slice(router.prefix.length) + normalize("search") + normalize("hash") } } - router.setPath = function(path, data, options) { + router.setPath = function(path, data1, options) { var queryData = {}, hashData = {} path = parsePath(path, queryData, hashData) - if (data != null) { - for (var key4 in data) queryData[key4] = data[key4] - path = path.replace(/:([^\/]+)/g, function(match2, token) { + if (data1 != null) { + for (var key1 in data1) queryData[key1] = data1[key1] + path = path.replace(/:([^\/]+)/g, function(match1, token) { delete queryData[token] - return data[token] + return data1[token] }) } var query = buildQueryString(queryData) @@ -1445,9 +1468,9 @@ var _21 = function($window, redrawService0) { function run1() { if (render1 != null) redrawService0.render(root, render1(Vnode(component, attrs3.key, attrs3))) } - var redraw2 = function() { + var redraw3 = function() { run1() - redraw2 = redrawService0.redraw + redraw3 = redrawService0.redraw } redrawService0.subscribe(root, run1) var bail = function(path) { @@ -1460,7 +1483,7 @@ var _21 = function($window, redrawService0) { component = comp != null && (typeof comp.view === "function" || typeof comp === "function")? comp : "div" attrs3 = params, currentPath = path, lastUpdate = null render1 = (routeResolver.render || identity).bind(routeResolver) - redraw2() + redraw3() } if (payload.view || typeof payload === "function") update({}, payload) else { @@ -1473,16 +1496,16 @@ var _21 = function($window, redrawService0) { } }, bail) } - route.set = function(path, data, options) { + route.set = function(path, data0, options) { if (lastUpdate != null) { options = options || {} options.replace = true } lastUpdate = null - routeService.setPath(path, data, options) + routeService.setPath(path, data0, options) } route.get = function() {return currentPath} - route.prefix = function(prefix0) {routeService.prefix = prefix0} + route.prefix = function(prefix) {routeService.prefix = prefix} var link = function(options, vnode1) { vnode1.dom.setAttribute("href", routeService.prefix + vnode1.attrs.href) vnode1.dom.onclick = function(e) { @@ -1498,28 +1521,24 @@ var _21 = function($window, redrawService0) { if (args0.tag == null) return link.bind(link, args0) return link({}, args0) } - route.param = function(key3) { - if(typeof attrs3 !== "undefined" && typeof key3 !== "undefined") return attrs3[key3] + route.param = function(key0) { + if(typeof attrs3 !== "undefined" && typeof key0 !== "undefined") return attrs3[key0] return attrs3 } return route } m.route = _21(window, redrawService) -m.withAttr = function(attrName, callback, context) { - return function(e) { - callback.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName)) - } -} -var _29 = coreRenderer(window) -m.render = _29.render +var _28 = coreRenderer(window) +m.render = _28.render m.redraw = redrawService.redraw m.request = requestService.request m.jsonp = requestService.jsonp m.parseQueryString = parseQueryString m.buildQueryString = buildQueryString -m.version = "1.1.3" +m.version = "2.0.0-rc.1" m.vnode = Vnode m.PromisePolyfill = PromisePolyfill export default m -export var m = m.m,trust = m.trust,fragment = m.fragment,mount = m.mount,route = m.route,withAttr = m.withAttr,render = m.render,redraw = m.redraw,request = m.request,jsonp = m.jsonp,parseQueryString = m.parseQueryString,buildQueryString = m.buildQueryString,version = m.version,vnode = m.vnode,PromisePolyfill = m.PromisePolyfill \ No newline at end of file +var _m = m.m,_trust = m.trust,_fragment = m.fragment,_mount = m.mount,_route = m.route,_render = m.render,_redraw = m.redraw,_request = m.request,_jsonp = m.jsonp,_parseQueryString = m.parseQueryString,_buildQueryString = m.buildQueryString,_version = m.version,_vnode = m.vnode,_PromisePolyfill = m.PromisePolyfill +export {_m as m,_trust as trust,_fragment as fragment,_mount as mount,_route as route,_render as render,_redraw as redraw,_request as request,_jsonp as jsonp,_parseQueryString as parseQueryString,_buildQueryString as buildQueryString,_version as version,_vnode as vnode,_PromisePolyfill as PromisePolyfill} \ No newline at end of file diff --git a/stream/stream.mjs b/stream/stream.mjs index 940e6e5d..0a0aad7b 100644 --- a/stream/stream.mjs +++ b/stream/stream.mjs @@ -1,156 +1,151 @@ /* eslint-enable */ +Stream.SKIP = {} +Stream.lift = lift +Stream.scan = scan +Stream.merge = merge +Stream.combine = combine +Stream.scanMerge = scanMerge +Stream["fantasy-land/of"] = Stream -var guid = 0, HALT = {} -function createStream() { - function stream() { - if (arguments.length > 0 && arguments[0] !== HALT) updateStream(stream, arguments[0]) - return stream._state.value +let warnedHalt = false +Object.defineProperty(Stream, "HALT", { + get: function() { + warnedHalt && console.log("HALT is deprecated and has been renamed to SKIP"); + warnedHalt = true + return Stream.SKIP } - initStream(stream) +}) - if (arguments.length > 0 && arguments[0] !== HALT) updateStream(stream, arguments[0]) +function Stream(value) { + var dependentStreams = [] + var dependentFns = [] + + function stream(v) { + if (arguments.length && v !== Stream.SKIP && open(stream)) { + value = v + stream.changing() + stream.state = "active" + dependentStreams.forEach(function(s, i) { s(dependentFns[i](value)) }) + } + + return value + } + + stream.constructor = Stream + stream.state = arguments.length && value !== Stream.SKIP ? "active" : "pending" + + stream.changing = function() { + open(stream) && (stream.state = "changing") + dependentStreams.forEach(function(s) { + s.dependent && s.dependent.changing() + s.changing() + }) + } + + stream.map = function(fn, ignoreInitial) { + var target = stream.state === "active" && ignoreInitial !== Stream.SKIP + ? Stream(fn(value)) + : Stream() + + dependentStreams.push(target) + dependentFns.push(fn) + return target + } + + let end + function createEnd() { + end = Stream() + end.map(function(value) { + if (value === true) { + stream.state = "ended" + dependentStreams.length = dependentFns.length = 0 + } + return value + }) + return end + } + + stream.toJSON = function() { return value != null && typeof value.toJSON === "function" ? value.toJSON() : value } + + stream["fantasy-land/map"] = stream.map + stream["fantasy-land/ap"] = function(x) { return combine(function(s1, s2) { return s1()(s2()) }, [x, stream]) } + + Object.defineProperty(stream, "end", { + get: function() { return end || createEnd() } + }) return stream } -function initStream(stream) { - stream.constructor = createStream - stream._state = {id: guid++, value: undefined, state: 0, derive: undefined, recover: undefined, deps: {}, parents: [], endStream: undefined, unregister: undefined} - stream.map = stream["fantasy-land/map"] = map, stream["fantasy-land/ap"] = ap, stream["fantasy-land/of"] = createStream - stream.toJSON = toJSON - - Object.defineProperties(stream, { - end: {get: function() { - if (!stream._state.endStream) { - var endStream = createStream() - endStream.map(function(value) { - if (value === true) { - unregisterStream(stream) - endStream._state.unregister = function(){unregisterStream(endStream)} - } - return value - }) - stream._state.endStream = endStream - } - return stream._state.endStream - }} - }) -} -function updateStream(stream, value) { - updateState(stream, value) - for (var id in stream._state.deps) updateDependency(stream._state.deps[id], false) - if (stream._state.unregister != null) stream._state.unregister() - finalize(stream) -} -function updateState(stream, value) { - stream._state.value = value - stream._state.changed = true - if (stream._state.state !== 2) stream._state.state = 1 -} -function updateDependency(stream, mustSync) { - var state = stream._state, parents = state.parents - if (parents.length > 0 && parents.every(active) && (mustSync || parents.some(changed))) { - var value = stream._state.derive() - if (value === HALT) return unregisterStream(stream) - updateState(stream, value) - } -} -function finalize(stream) { - stream._state.changed = false - for (var id in stream._state.deps) stream._state.deps[id]._state.changed = false -} function combine(fn, streams) { - if (!streams.every(valid)) throw new Error("Ensure that each item passed to stream.combine/stream.merge is a stream") - return initDependency(createStream(), streams, function() { - return fn.apply(this, streams.concat([streams.filter(changed)])) + var ready = streams.every(function(s) { + if (s.constructor !== Stream) + throw new Error("Ensure that each item passed to stream.combine/stream.merge/lift is a stream") + return s.state === "active" }) + var stream = ready + ? Stream(fn.apply(null, streams.concat([streams]))) + : Stream() + + let changed = [] + + streams.forEach(function(s) { + s.map(function(value) { + changed.push(s) + if (ready || streams.every(function(s) { return s.state !== "pending" })) { + ready = true + stream(fn.apply(null, streams.concat([changed]))) + changed = [] + } + return value + }, Stream.SKIP).parent = stream + }) + + return stream } -function initDependency(dep, streams, derive) { - var state = dep._state - state.derive = derive - state.parents = streams.filter(notEnded) - - registerDependency(dep, state.parents) - updateDependency(dep, true) - - return dep -} -function registerDependency(stream, parents) { - for (var i = 0; i < parents.length; i++) { - parents[i]._state.deps[stream._state.id] = stream - registerDependency(stream, parents[i]._state.parents) - } -} -function unregisterStream(stream) { - for (var i = 0; i < stream._state.parents.length; i++) { - var parent = stream._state.parents[i] - delete parent._state.deps[stream._state.id] - } - for (var id in stream._state.deps) { - var dependent = stream._state.deps[id] - var index = dependent._state.parents.indexOf(stream) - if (index > -1) dependent._state.parents.splice(index, 1) - } - stream._state.state = 2 //ended - stream._state.deps = {} -} - -function map(fn) {return combine(function(stream) {return fn(stream())}, [this])} -function ap(stream) {return combine(function(s1, s2) {return s1()(s2())}, [stream, this])} -function toJSON() {return this._state.value != null && typeof this._state.value.toJSON === "function" ? this._state.value.toJSON() : this._state.value} - -function valid(stream) {return stream._state } -function active(stream) {return stream._state.state === 1} -function changed(stream) {return stream._state.changed} -function notEnded(stream) {return stream._state.state !== 2} - function merge(streams) { - return combine(function() { - return streams.map(function(s) {return s()}) - }, streams) + return combine(function() { return streams.map(function(s) { return s() }) }, streams) } -function scan(reducer, seed, stream) { - var newStream = combine(function (s) { - var next = reducer(seed, s._state.value) - if (next !== HALT) return seed = next - return HALT - }, [stream]) - - if (newStream._state.state === 0) newStream(seed) - - return newStream +function scan(fn, acc, origin) { + var stream = origin.map(function(v) { + acc = fn(acc, v) + return acc + }) + stream(acc) + return stream } function scanMerge(tuples, seed) { - var streams = tuples.map(function(tuple) { - var stream = tuple[0] - if (stream._state.state === 0) stream(undefined) - return stream - }) + var streams = tuples.map(function(tuple) { return tuple[0] }) - var newStream = combine(function() { + var stream = combine(function() { var changed = arguments[arguments.length - 1] - - streams.forEach(function(stream, idx) { - if (changed.indexOf(stream) > -1) { - seed = tuples[idx][1](seed, stream._state.value) - } + streams.forEach(function(stream, i) { + if (changed.indexOf(stream) > -1) + seed = tuples[i][1](seed, stream()) }) return seed }, streams) - return newStream + stream(seed) + + return stream } -createStream["fantasy-land/of"] = createStream -createStream.merge = merge -createStream.combine = combine -createStream.scan = scan -createStream.scanMerge = scanMerge -createStream.HALT = HALT +function lift() { + var fn = arguments[0] + var streams = Array.prototype.slice.call(arguments, 1) + return merge(streams).map(function(streams) { + return fn.apply(undefined, streams) + }) +} + +function open(s) { + return s.state === "pending" || s.state === "active" || s.state === "changing" +} export default createStream \ No newline at end of file