diff --git a/mithril.js b/mithril.js index 4418ccd9..b19b564e 100644 --- a/mithril.js +++ b/mithril.js @@ -293,38 +293,130 @@ var buildQueryString = function(object) { else args.push(encodeURIComponent(key0) + (value1 != null && value1 !== "" ? "=" + encodeURIComponent(value1) : "")) } } +/** @constructor */ +var Promise = function(executor) { + if (!(this instanceof Promise)) throw new Error("Promise must be called with `new`") + if (typeof executor !== "function") throw new TypeError("executor must be a function") + var self0 = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false) + var instance = self0._instance = {resolvers: resolvers, rejectors: rejectors} + var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout + function handler(list, shouldAbsorb) { + return function execute(value2) { + var then + try { + if (shouldAbsorb && value2 != null && (typeof value2 === "object" || typeof value2 === "function") && typeof (then = value2.then) === "function") { + if (value2 === self0) throw new TypeError("Promise can't be resolved w/ itself") + executeOnce(then.bind(value2)) + } + else { + callAsync(function() { + if (!shouldAbsorb && list.length === 0) console.error("Possible unhandled promise rejection:", value2) + for (var i = 0; i < list.length; i++) list[i](value2) + resolvers.length = 0, rejectors.length = 0 + instance.state = shouldAbsorb + instance.retry = function() {execute(value2)} + }) + } + } + catch (e) { + rejectCurrent(e) + } + } + } + function executeOnce(then) { + var runs = 0 + function run0(fn) { + return function(value2) { + if (runs++ > 0) return + fn(value2) + } + } + var onerror = run0(rejectCurrent) + try {then(run0(resolveCurrent), onerror)} catch (e) {onerror(e)} + } + executeOnce(executor) +} +Promise.prototype.then = function(onFulfilled, onRejection) { + var self0 = this, instance = self0._instance + function handle(callback, list, next, state0) { + list.push(function(value2) { + if (typeof callback !== "function") next(value2) + else try {resolveNext(callback(value2))} catch (e) {if (rejectNext) rejectNext(e)} + }) + if (typeof instance.retry === "function" && state0 === instance.state) instance.retry() + } + var resolveNext, rejectNext + var promise = new Promise(function(resolve0, reject0) {resolveNext = resolve0, rejectNext = reject0}) + handle(onFulfilled, instance.resolvers, resolveNext, true), handle(onRejection, instance.rejectors, rejectNext, false) + return promise +} +Promise.prototype.catch = function(onRejection) { + return this.then(null, onRejection) +} +Promise.resolve = function(value2) { + if (value2 instanceof Promise) return value2 + return new Promise(function(resolve0) {resolve0(value2)}) +} +Promise.reject = function(value2) { + return new Promise(function(resolve0, reject0) {reject0(value2)}) +} +Promise.all = function(list) { + return new Promise(function(resolve0, reject0) { + var total = list.length, count = 0, values = [] + if (list.length === 0) resolve0([]) + else for (var i = 0; i < list.length; i++) { + (function(i) { + function consume(value2) { + count++ + values[i] = value2 + if (count === total) resolve0(values) + } + if (list[i] != null && (typeof list[i] === "object" || typeof list[i] === "function") && typeof list[i].then === "function") { + list[i].then(consume, reject0) + } + else consume(list[i]) + })(i) + } + }) +} +Promise.race = function(list) { + return new Promise(function(resolve0, reject0) { + for (var i = 0; i < list.length; i++) { + list[i].then(resolve0, reject0) + } + }) +} var _9 = function($window, Stream0) { var callbackCount = 0 var oncompletion function setCompletionCallback(callback) {oncompletion = callback} - - function request(args) { + function request(args, extra) { + if(typeof args === "string"){ + var url = args + if(typeof extra === "object") args = extra + else args = {} + if(typeof args.url === "undefined") args.url = url + } + if(typeof args.method === "undefined") args.method = "GET" var stream0 = Stream0() if (args.initialValue !== undefined) stream0(args.initialValue) args.method = args.method.toUpperCase() - var useBody = typeof args.useBody === "boolean" ? args.useBody : args.method !== "GET" && args.method !== "TRACE" - if (typeof args.serialize !== "function") args.serialize = typeof FormData !== "undefined" && args.data instanceof FormData ? function(value0) {return value0} : JSON.stringify if (typeof args.deserialize !== "function") args.deserialize = deserialize if (typeof args.extract !== "function") args.extract = extract - args.url = interpolate(args.url, args.data) if (useBody) args.data = args.serialize(args.data) else args.url = assemble(args.url, args.data) - var xhr = new $window.XMLHttpRequest() xhr.open(args.method, args.url, typeof args.async === "boolean" ? args.async : true, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined) - if (args.serialize === JSON.stringify && useBody) { xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8") } if (args.deserialize === deserialize) { xhr.setRequestHeader("Accept", "application/json, text/*") } - if (typeof args.config === "function") xhr = args.config(xhr, args) || xhr - xhr.onreadystatechange = function() { if (xhr.readyState === 4) { try { @@ -344,16 +436,13 @@ var _9 = function($window, Stream0) { if (typeof oncompletion === "function") oncompletion() } } - if (useBody && (args.data != null)) xhr.send(args.data) else xhr.send() - return stream0 } function jsonp(args) { var stream0 = Stream0() if (args.initialValue !== undefined) stream0(args.initialValue) - var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ var script = $window.document.createElement("script") $window[callbackName] = function(data) { @@ -400,7 +489,6 @@ var _9 = function($window, Stream0) { catch (e) {throw new Error(data)} } function extract(xhr) {return xhr.responseText} - function cast(type0, data) { if (typeof type0 === "function") { if (data instanceof Array) { @@ -412,11 +500,10 @@ var _9 = function($window, Stream0) { } return data } - return {request: request, jsonp: jsonp, setCompletionCallback: setCompletionCallback} } var requestService = _9(window, Stream) -var _12 = function() { +var _13 = function() { var callbacks = [] function unsubscribe(callback) { var index0 = callbacks.indexOf(callback) @@ -429,9 +516,9 @@ var _12 = function() { } return {subscribe: callbacks.push.bind(callbacks), unsubscribe: unsubscribe, publish: publish} } -var redrawService = _12() +var redrawService = _13() requestService.setCompletionCallback(redrawService.publish) -var _14 = function($window) { +var _15 = function($window) { var $doc = $window.document var $emptyFragment = $doc.createDocumentFragment() var onevent @@ -517,7 +604,7 @@ var _14 = function($window) { return element } function createComponent(vnode, hooks, ns) { - // For object literals since `Vnode()` always sets the `state0` field. + // For object literals since `Vnode()` always sets the `state1` field. if (!vnode.state) vnode.state = {} assign(vnode.state, vnode.tag) var view = vnode.tag.view @@ -672,7 +759,7 @@ var _14 = function($window) { if (vnode.tag === "textarea") { if (vnode.attrs == null) vnode.attrs = {} if (vnode.text != null) { - vnode.attrs.value = vnode.text //FIXME handle multiple children + vnode.attrs.value = vnode.text //FIXME handle0 multiple children vnode.text = undefined } } @@ -835,26 +922,26 @@ var _14 = function($window) { setAttr(vnode, key1, null, attrs2[key1], ns) } } - function setAttr(vnode, key1, old, value2, ns) { + function setAttr(vnode, key1, old, value3, ns) { var element = vnode.dom - if (key1 === "key" || (old === value2 && !isFormAttribute(vnode, key1)) && typeof value2 !== "object" || typeof value2 === "undefined" || isLifecycleMethod(key1)) return + if (key1 === "key" || (old === value3 && !isFormAttribute(vnode, key1)) && typeof value3 !== "object" || typeof value3 === "undefined" || isLifecycleMethod(key1)) return var nsLastIndex = key1.indexOf(":") if (nsLastIndex > -1 && key1.substr(0, nsLastIndex) === "xlink") { - element.setAttributeNS("http://www.w3.org/1999/xlink", key1.slice(nsLastIndex + 1), value2) + element.setAttributeNS("http://www.w3.org/1999/xlink", key1.slice(nsLastIndex + 1), value3) } - else if (key1[0] === "o" && key1[1] === "n" && typeof value2 === "function") updateEvent(vnode, key1, value2) - else if (key1 === "style") updateStyle(element, old, value2) + else if (key1[0] === "o" && key1[1] === "n" && typeof value3 === "function") updateEvent(vnode, key1, value3) + else if (key1 === "style") updateStyle(element, old, value3) else if (key1 in element && !isAttribute(key1) && ns === undefined) { - //setting input[value2] to same value2 by typing on focused element moves cursor to end in Chrome - if (vnode.tag === "input" && key1 === "value" && vnode.dom.value === value2 && vnode.dom === $doc.activeElement) return - element[key1] = value2 + //setting input[value3] to same value3 by typing on focused element moves cursor to end in Chrome + if (vnode.tag === "input" && key1 === "value" && vnode.dom.value === value3 && vnode.dom === $doc.activeElement) return + element[key1] = value3 } else { - if (typeof value2 === "boolean") { - if (value2) element.setAttribute(key1, "") + if (typeof value3 === "boolean") { + if (value3) element.setAttribute(key1, "") else element.removeAttribute(key1) } - else element.setAttribute(key1 === "className" ? "class" : key1, value2) + else element.setAttribute(key1 === "className" ? "class" : key1, value3) } } function setLateAttrs(vnode) { @@ -910,19 +997,19 @@ var _14 = function($window) { } } //event - function updateEvent(vnode, key1, value2) { + function updateEvent(vnode, key1, value3) { var element = vnode.dom var callback = function(e) { - var result = value2.call(element, e) + var result = value3.call(element, e) if (typeof onevent === "function") onevent.call(element, e) return result } - if (key1 in element) element[key1] = typeof value2 === "function" ? callback : null + if (key1 in element) element[key1] = typeof value3 === "function" ? callback : null else { var eventName = key1.slice(2) if (vnode.events === undefined) vnode.events = {} if (vnode.events[key1] != null) element.removeEventListener(eventName, vnode.events[key1], false) - if (typeof value2 === "function") { + if (typeof value3 === "function") { vnode.events[key1] = callback element.addEventListener(eventName, vnode.events[key1], false) } @@ -966,7 +1053,7 @@ var _14 = function($window) { } return {render: render, setEventCallback: setEventCallback} } -var renderService = _14(window) +var renderService = _15(window) var throttle = function(callback1) { //60fps translates to 16.6ms, round it down since setTimeout requires int var time = 16 @@ -988,7 +1075,7 @@ var throttle = function(callback1) { } } var autoredraw = function(root, renderer, pubsub, callback0) { - var run1 = throttle(callback0) + var run2 = throttle(callback0) if (renderer != null) { renderer.setEventCallback(function(e) { if (e.redraw !== false) pubsub.publish() @@ -996,11 +1083,11 @@ var autoredraw = function(root, renderer, pubsub, callback0) { } if (pubsub != null) { if (root.redraw) pubsub.unsubscribe(root.redraw) - pubsub.subscribe(run1) + pubsub.subscribe(run2) } - return root.redraw = run1 + return root.redraw = run2 } -var _18 = function(renderer, pubsub) { +var _19 = function(renderer, pubsub) { return function(root, component) { if (component === null) { renderer.render(root, []) @@ -1010,13 +1097,13 @@ var _18 = function(renderer, pubsub) { } if (component.view == null) throw new Error("m.mount(element, component) expects a component, not a vnode") - var run0 = autoredraw(root, renderer, pubsub, function() { + var run1 = autoredraw(root, renderer, pubsub, function() { renderer.render(root, Vnode(component, undefined, undefined, undefined, undefined, undefined)) }) - run0() + run1() } } -m.mount = _18(renderService, redrawService) +m.mount = _19(renderService, redrawService) var mount = m.mount var parseQueryString = function(string) { if (string === "" || string == null) return {} @@ -1025,9 +1112,9 @@ var parseQueryString = function(string) { for (var i = 0; i < entries.length; i++) { var entry = entries[i].split("=") var key3 = decodeURIComponent(entry[0]) - var value4 = entry.length === 2 ? decodeURIComponent(entry[1]) : "" - if (value4 === "true") value4 = true - else if (value4 === "false") value4 = false + var value5 = entry.length === 2 ? decodeURIComponent(entry[1]) : "" + if (value5 === "true") value5 = true + else if (value5 === "false") value5 = false var levels = key3.split(/\]\[?|\[/) var cursor = data0 if (key3.indexOf("[") > -1) levels.pop() @@ -1041,7 +1128,7 @@ var parseQueryString = function(string) { level = counters[key3]++ } if (cursor[level] == null) { - cursor[level] = isValue ? value4 : isNumber ? [] : {} + cursor[level] = isValue ? value5 : isNumber ? [] : {} } cursor = cursor[level] } @@ -1050,9 +1137,9 @@ var parseQueryString = function(string) { } var coreRouter = function($window) { var supportsPushState = typeof $window.history.pushState === "function" - var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout + var callAsync0 = typeof setImmediate === "function" ? setImmediate : setTimeout var prefix1 = "#!" - function setPrefix(value3) {prefix1 = value3} + function setPrefix(value4) {prefix1 = value4} function normalize(fragment0) { var data = $window.location[fragment0].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent) if (fragment0 === "pathname" && data[0] !== "/") data = "/" + data @@ -1062,7 +1149,7 @@ var coreRouter = function($window) { function debounceAsync(f) { return function() { if (asyncId != null) return - asyncId = callAsync(function() { + asyncId = callAsync0(function() { asyncId = null f() }) @@ -1112,7 +1199,7 @@ var coreRouter = function($window) { } else $window.location.href = prefix1 + path } - function defineRoutes(routes, resolve1, reject0) { + function defineRoutes(routes, resolve2, reject1) { if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute) else if (prefix1.charAt(0) === "#") $window.onhashchange = resolveRoute resolveRoute() @@ -1131,12 +1218,12 @@ var coreRouter = function($window) { for (var i = 0; i < keys.length; i++) { params[keys[i].replace(/:|\./g, "")] = decodeURIComponent(values[i]) } - resolve1(routes[route0], params, path, route0) + resolve2(routes[route0], params, path, route0) }) return } } - reject0(path, params) + reject1(path, params) } return resolveRoute } @@ -1153,7 +1240,7 @@ var coreRouter = function($window) { } return {setPrefix: setPrefix, getPath: getPath, setPath: setPath, defineRoutes: defineRoutes, link: link} } -var _24 = function($window, mount0) { +var _25 = function($window, mount0) { var router = coreRouter($window) var currentResolve, currentComponent, currentRender, currentArgs, currentPath var RouteComponent = {view: function() { @@ -1170,8 +1257,8 @@ var _24 = function($window, mount0) { router.defineRoutes(routes, function(payload, args0, path) { var isResolver = typeof payload.view !== "function" var render1 = defaultRender - var resolve0 = currentResolve = function (component) { - if (resolve0 !== currentResolve) return + var resolve1 = currentResolve = function (component) { + if (resolve1 !== currentResolve) return currentResolve = null currentComponent = component != null ? component : isResolver ? "div" : payload currentRender = render1 @@ -1180,14 +1267,14 @@ var _24 = function($window, mount0) { root.redraw(true) } var onmatch = function() { - resolve0() + resolve1() } if (isResolver) { if (typeof payload.render === "function") render1 = payload.render.bind(payload) if (typeof payload.onmatch === "function") onmatch = payload.onmatch } - onmatch.call(payload, resolve0, args0, path) + onmatch.call(payload, resolve1, args0, path) }, function() { router.setPath(defaultRoute, null, {replace: true}) }) @@ -1198,7 +1285,7 @@ var _24 = function($window, mount0) { route.get = function() {return currentPath} return route } -m.route = _24(window, mount) +m.route = _25(window, mount) m.withAttr = function(attrName, callback2, context) { return function(e) { return callback2.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName)) diff --git a/mithril.min.js b/mithril.min.js index 1dd518c5..daac7489 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1,44 +1,44 @@ -new function(){function u(c,f,r,g,k,h){return{tag:c,key:f,attrs:r,children:g,text:k,dom:h,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}function v(c){if(null==c||"string"!==typeof c&&null==c.view)throw Error("The selector must be either a string or a component.");if("string"===typeof c&&void 0===K[c]){for(var f,r,g=[],k={};f=R.exec(c);){var h=f[1],y=f[2];""===h&&""!==y?r=y:"#"===h?k.id=y:"."===h?g.push(y):"["===f[3][0]&&((h=f[6])&&(h=h.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")), -k[f[4]]=h||!0)}0e.filter(I).length)throw Error("Ensure that each item passed to m.prop.combine/m.prop.merge is a stream"); -return t(f(),e,function(){var n=e.filter(d);if(0e.indexOf("?")?"?":"&";e+=g+f}return e}function k(e){try{return""!==e?JSON.parse(e):null}catch(m){throw Error(e);}}function h(e){return e.responseText}function y(e,c){if("function"===typeof e)if(c instanceof Array)for(var f=0;fw.status||304===w.status)m(y(e.type,c));else{var f=Error(w.responseText),g;for(g in c)f[g]=c[g];m.error(f)}}catch(S){m.error(S)}"function"===typeof p&&p()}};x&&null!=e.data?w.send(e.data):w.send();return m},jsonp:function(e){var m=f();void 0!==e.initialValue&&m(e.initialValue);var h=e.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+z++,k=c.document.createElement("script");c[h]=function(f){k.parentNode.removeChild(k);m(y(e.type, -f));"function"===typeof p&&p();delete c[h]};k.onerror=function(){k.parentNode.removeChild(k);m.error(Error("JSONP request failed"));"function"===typeof p&&p();delete c[h]};null==e.data&&(e.data={});e.url=r(e.url,e.data);e.data[e.callbackKey||"callback"]=h;k.src=g(e.url,e.data);c.document.documentElement.appendChild(k);return m},setCompletionCallback:function(e){p=e}}}(window,P),M=function(){var c=[];return{subscribe:c.push.bind(c),unsubscribe:function(f){f=c.indexOf(f);-1=q&&x>=A;){var t=b[q],l=d[A];if(t!==l||n)if(null!=t&&null!=l&&t.key===l.key)q++,A++,h(a,t,l,c,z(b,q,e),n,g),n&&t.tag===l.tag&&p(a,y(t),e);else if(t=b[k],t!==l||n)if(null!=t&&null!=l&&t.key===l.key)h(a,t,l,c,z(b,k+1,e),n,g),(n||A=q&&x>=A;){t=b[k];l=d[x];if(t!==l||n)if(null!=t&&null!=l&&t.key===l.key)h(a,t,l,c,z(b,k+1,e),n,g),n&&t.tag===l.tag&&p(a,y(t),e),null!=t.dom&&(e=t.dom),k--;else{if(!w){w=b;var t=k,C={},u;for(u=0;ue.filter(I).length)throw Error("Ensure that each item passed to m.prop.combine/m.prop.merge is a stream"); +return r(f(),e,function(){var m=e.filter(d);if(0e.indexOf("?")?"?":"&";e+=g+f}return e}function k(e){try{return""!==e?JSON.parse(e):null}catch(w){throw Error(e);}}function h(e){return e.responseText}function x(e,c){if("function"===typeof e)if(c instanceof Array)for(var f=0;fp.status||304===p.status)A(x(e.type,c));else{var f=Error(p.responseText),g;for(g in c)f[g]=c[g];A.error(f)}}catch(S){A.error(S)}"function"===typeof t&&t()}};l&&null!=e.data?p.send(e.data):p.send();return A},jsonp:function(e){var h=f();void 0!==e.initialValue&&h(e.initialValue);var l=e.callbackName||"_mithril_"+ +Math.round(1E16*Math.random())+"_"+z++,k=c.document.createElement("script");c[l]=function(f){k.parentNode.removeChild(k);h(x(e.type,f));"function"===typeof t&&t();delete c[l]};k.onerror=function(){k.parentNode.removeChild(k);h.error(Error("JSONP request failed"));"function"===typeof t&&t();delete c[l]};null==e.data&&(e.data={});e.url=n(e.url,e.data);e.data[e.callbackKey||"callback"]=l;k.src=g(e.url,e.data);c.document.documentElement.appendChild(k);return h},setCompletionCallback:function(e){t=e}}}(window, +P),M=function(){var c=[];return{subscribe:c.push.bind(c),unsubscribe:function(f){f=c.indexOf(f);-1=q&&k>=B;){var r=b[q],y=d[B];if(r!==y||m)if(null!=r&&null!=y&&r.key===y.key)q++,B++,h(a,r,y,c,z(b,q,e),m,g),m&&r.tag===y.tag&&t(a,x(r),e);else if(r= +b[l],r!==y||m)if(null!=r&&null!=y&&r.key===y.key)h(a,r,y,c,z(b,l+1,e),m,g),(m||B=q&&k>=B;){r=b[l];y=d[k];if(r!==y||m)if(null!=r&&null!=y&&r.key===y.key)h(a,r,y,c,z(b,l+1,e),m,g),m&&r.tag===y.tag&&t(a,x(r),e),null!=r.dom&&(e=r.dom),l--;else{if(!p){p=b;var r=l,u={},A;for(A=0;A