diff --git a/README.md b/README.md index 29420f29..1dcc001c 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,14 @@ Note: This branch is a sneak peek for the upcoming version 1.0. It's a rewrite f This rewrite aims to fix longstanding API design issues, significantly improve performance, and clean up the codebase. +## Early Preview + +You can install this via NPN using this command: + +``` +npm install lhorie/mithril.js#rewrite +``` + ## Status Code still is in flux. Most notably, there's no promise polyfill yet and there are several use cases that still need to be polished. DO NOT USE IN PRODUCTION YET! diff --git a/api/mount.js b/api/mount.js index b42e3d93..4a790307 100644 --- a/api/mount.js +++ b/api/mount.js @@ -1,10 +1,10 @@ "use strict" -var createRenderer = require("../render/render") +var coreRenderer = require("../render/render") var throttle = require("../api/throttle") module.exports = function($window, redraw) { - var renderer = createRenderer($window) + var renderer = coreRenderer($window) return function(root, component) { var run = throttle(function() { renderer.render(root, {tag: component}) diff --git a/api/router.js b/api/router.js index 95eef3c1..f2e5dcf8 100644 --- a/api/router.js +++ b/api/router.js @@ -1,12 +1,12 @@ "use strict" -var createRenderer = require("../render/render") -var createRouter = require("../router/router") +var coreRenderer = require("../render/render") +var coreRouter = require("../router/router") var throttle = require("../api/throttle") module.exports = function($window, redraw) { - var renderer = createRenderer($window) - var router = createRouter($window) + var renderer = coreRenderer($window) + var router = coreRouter($window) var route = function(root, defaultRoute, routes) { var replay = router.defineRoutes(routes, function(component, args) { renderer.render(root, {tag: component, attrs: args}) diff --git a/api/tests/test-mount.js b/api/tests/test-mount.js index 7f6d00f1..93c721f9 100644 --- a/api/tests/test-mount.js +++ b/api/tests/test-mount.js @@ -4,7 +4,7 @@ var o = require("../../ospec/ospec") var domMock = require("../../test-utils/domMock") var m = require("../../render/hyperscript") -var createMounter = require("../mount") +var apiMounter = require("../../api/mount") o.spec("m.mount", function() { var FRAME_BUDGET = 1000 / 60 diff --git a/api/tests/test-router.js b/api/tests/test-router.js index 624e492c..44ce523f 100644 --- a/api/tests/test-router.js +++ b/api/tests/test-router.js @@ -5,7 +5,7 @@ var pushStateMock = require("../../test-utils/pushStateMock") var domMock = require("../../test-utils/domMock") var m = require("../../render/hyperscript") -var router = require("../../api/router") +var apiRouter = require("../../api/router") o.spec("m.route", function() { var FRAME_BUDGET = 1000 / 60 @@ -23,7 +23,7 @@ o.spec("m.route", function() { root = $window.document.body redraw = {} - route = router($window, redraw) + route = apiRouter($window, redraw) }) o("updates redraw object", function() { diff --git a/bundler/bundler.js b/bundler/bundler.js index 46787186..04cd847c 100644 --- a/bundler/bundler.js +++ b/bundler/bundler.js @@ -4,21 +4,23 @@ var fs = require("fs") var path = require("path") var modules = {} +var usedVariables = {} function resolve(dir, data) { var replacements = [] - data = data.replace(/((?:var|let|const|)\s*)([\w_$]+)(\s*=\s*)require\(([^\)]+)\)/g, function(match, def, variable, eq, dep) { + data = data.replace(/((?:var|let|const|)[\t ]*)([\w_$\.]+)(\s*=\s*)require\(([^\)]+)\)/g, function(match, def, variable, eq, dep) { + usedVariables[variable] = usedVariables[variable] ? usedVariables[variable]++ : 1 + var filename = new Function("return " + dep).call() - var pathname = path.dirname(path.resolve(dir, filename)) - var normalized = path.normalize(dir + "/" + filename) + var normalized = path.resolve(dir, filename) + var pathname = path.dirname(normalized) if (modules[normalized] === undefined) { modules[normalized] = variable - return resolve(pathname, - fs.readFileSync(dir + "/" + filename + ".js", "utf8") - .replace(/"use strict"\s*/gm, "") - .replace(/module\.exports\s*=\s*/gm, def + variable + eq) - //.replace(/module\.exports(\.[\w_$]|\["[^\"]"\])/, def + variable + eq + "{}\n" + variable + "$1") - ) + var exported = fixCollisions(fs.readFileSync(dir + "/" + filename + ".js", "utf8")) + .replace(/"use strict"\s*/gm, "") // remove extraneous "use strict" + .replace(/module\.exports\s*=\s*/gm, def + variable + eq) + //.replace(/module\.exports(\.[\w_$]|\["[^\"]"\])/, def + variable + eq + "{}\n" + variable + "$1") + return resolve(pathname, exported) } else { if (modules[normalized] !== variable) { @@ -33,6 +35,25 @@ function resolve(dir, data) { } } return data + .replace(/(?:var|let|const)[\t ]([\w_$\.]+)(\s*=\s*)\1([\r\n;]+)/g, "$3") // remove assignments to itself + .replace(/(\r\n){2,}/g, "$1$1") // remove multiple consecutive line breaks } -fs.writeFileSync("mithril.js", resolve(".", fs.readFileSync("index.js", "utf8")), "utf8") +function fixCollisions(code) { + for (var variable in usedVariables) { + var collision = new RegExp("\\b" + variable + "\\b(?![\"'`])", "g") + var exported = new RegExp("module\\.exports\\s*=\\s*" + variable) + if (collision.test(code) && !exported.test(code)) { + var fixed = variable + usedVariables[variable]++ + code = code.replace(collision, fixed) + } + } + return code +} + +function bundle(input, output) { + var code = resolve(".", fs.readFileSync(input, "utf8")) + if (new Function(code)) fs.writeFileSync(output, code, "utf8") +} + +bundle("index.js", "mithril.js") diff --git a/index.js b/index.js index 3fd438ac..4d6ae79b 100644 --- a/index.js +++ b/index.js @@ -2,19 +2,19 @@ var m = require("./render/hyperscript") var trust = require("./render/trust") -var createRenderer = require("./render/render") -var createMounter = require("./api/mount") -var createRouterInstance = require("./api/router") -var createRequester = require("./request/request") +var coreRenderer = require("./render/render") +var apiMounter = require("./api/mount") +var apiRouter = require("./api/router") +var coreRequester = require("./request/request") var redraw = {run: function() {}} m.redraw = function() { redraw.run() } m.trust = trust -m.render = createRenderer(window).render -m.mount = createMounter(window, redraw) -m.route = createRouterInstance(window, redraw) -m.request = createRequester(window, Promise).ajax +m.render = coreRenderer(window).render +m.mount = apiMounter(window, redraw) +m.route = apiRouter(window, redraw) +m.request = coreRequester(window, Promise).ajax module.exports = m diff --git a/mithril.js b/mithril.js index c82f1fdf..ddb8f1bd 100644 --- a/mithril.js +++ b/mithril.js @@ -15,8 +15,6 @@ Node.normalizeChildren = function normalizeChildren(children) { return children } -var Node = Node - var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[.+?\])/g, attrParser = /\[(.+?)(?:\s*=\s*("|'|)(.*?)\2)?\]/ var selectorCache = {} function hyperscript(selector) { @@ -91,500 +89,11 @@ function changeNS(ns, vnode) { var m = hyperscript - - var trust = function(html) { return Node("<", undefined, undefined, html, undefined, undefined) } - -var createRenderer = function($window) { - var $doc = $window.document - - var onevent - function setEventCallback(callback) {return onevent = callback} - - //create - function createNodes(parent, vnodes, start, end, hooks, nextSibling) { - for (var i = start; i < end; i++) { - var vnode = vnodes[i] - if (vnode != null) { - insertNode(parent, createNode(vnode, hooks), nextSibling) - } - } - } - function createNode(vnode, hooks) { - var tag = vnode.tag - if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) - if (typeof tag === "string") { - switch (tag) { - case "#": return createText(vnode) - case "<": return createHTML(vnode) - case "[": return createFragment(vnode, hooks) - default: return createElement(vnode, hooks) - } - } - else return createComponent(vnode, hooks) - } - function createText(vnode) { - return vnode.dom = $doc.createTextNode(vnode.children) - } - function createHTML(vnode) { - var match = vnode.children.match(/^\s*?<(\w+)/im) || [] - var parent = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"}[match[1]] || "div" - var temp = $doc.createElement(parent) - - temp.innerHTML = vnode.children - vnode.dom = temp.firstChild - vnode.domSize = temp.childNodes.length - var fragment = $doc.createDocumentFragment() - var child - while (child = temp.firstChild) { - fragment.appendChild(child) - } - return fragment - } - function createFragment(vnode, hooks) { - var fragment = $doc.createDocumentFragment() - if (vnode.children != null) { - var children = vnode.children - createNodes(fragment, children, 0, children.length, hooks, null) - } - vnode.dom = fragment.firstChild - vnode.domSize = fragment.childNodes.length - return fragment - } - function createElement(vnode, hooks) { - var tag = vnode.tag - var ns = vnode.ns - - var attrs = vnode.attrs - var is = attrs && attrs.is - - var element = ns ? - is ? $doc.createElementNS(ns, tag, is) : $doc.createElementNS(ns, tag) : - is ? $doc.createElement(tag, is) : $doc.createElement(tag) - vnode.dom = element - - if (attrs != null) { - setAttrs(vnode, attrs) - } - - if (vnode.text != null) { - if (vnode.text !== "") element.textContent = vnode.text - else vnode.children = [Node("#", undefined, undefined, vnode.text, undefined, undefined)] - } - - if (vnode.children != null) { - var children = vnode.children - createNodes(element, children, 0, children.length, hooks, null) - setLateAttrs(vnode) - } - return element - } - function createComponent(vnode, hooks) { - vnode.state = copy(vnode.tag) - - initLifecycle(vnode.tag, vnode, hooks) - vnode.instance = Node.normalize(vnode.tag.view.call(vnode.state, vnode)) - var element = createNode(vnode.instance, hooks) - vnode.dom = vnode.instance.dom - vnode.domSize = vnode.instance.domSize - return element - } - - //update - function updateNodes(parent, old, vnodes, hooks, nextSibling) { - if (old == null && vnodes == null) return - else if (old == null) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling) - else if (vnodes == null) removeNodes(parent, old, 0, old.length, vnodes) - else { - var recycling = isRecyclable(old, vnodes) - if (recycling) old = old.concat(old.pool) - - var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map - while (oldEnd >= oldStart && end >= start) { - var o = old[oldStart], v = vnodes[start] - if (o === v) oldStart++, start++ - else if (o != null && v != null && o.key === v.key) { - oldStart++, start++ - updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling) - if (recycling) insertNode(parent, toFragment(o), nextSibling) - } - else { - var o = old[oldEnd] - if (o === v) oldEnd--, start++ - else if (o != null && v != null && o.key === v.key) { - updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling) - insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling)) - oldEnd--, start++ - } - else break - } - } - while (oldEnd >= oldStart && end >= start) { - var o = old[oldEnd], v = vnodes[end] - if (o === v) oldEnd--, end-- - else if (o != null && v != null && o.key === v.key) { - updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling) - if (recycling) insertNode(parent, toFragment(o), nextSibling) - nextSibling = o.dom - oldEnd--, end-- - } - else { - if (!map) map = getKeyMap(old, oldEnd) - if (v != null) { - var oldIndex = map[v.key] - if (oldIndex != null) { - var movable = old[oldIndex] - updateNode(parent, movable, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling) - insertNode(parent, toFragment(movable), nextSibling) - old[oldIndex].skip = true - nextSibling = movable.dom - } - else { - var dom = createNode(v, hooks) - insertNode(parent, dom, nextSibling) - nextSibling = dom - } - } - end-- - } - if (end < start) break - } - createNodes(parent, vnodes, start, end + 1, hooks, nextSibling) - removeNodes(parent, old, oldStart, oldEnd + 1, vnodes) - } - } - function updateNode(parent, old, vnode, hooks, nextSibling, recycling) { - var oldTag = old.tag, tag = vnode.tag - if (oldTag === tag) { - vnode.state = old.state - vnode.events = old.events - if (shouldUpdate(vnode, old)) return - if (vnode.attrs != null) { - updateLifecycle(vnode.attrs, vnode, hooks, recycling) - } - if (typeof oldTag === "string") { - switch (oldTag) { - case "#": updateText(old, vnode); break - case "<": updateHTML(parent, old, vnode, nextSibling); break - case "[": updateFragment(parent, old, vnode, hooks, nextSibling); break - default: updateElement(old, vnode, hooks) - } - } - else updateComponent(parent, old, vnode, hooks, nextSibling, recycling) - } - else { - removeNode(parent, old, null, false) - insertNode(parent, createNode(vnode, hooks), nextSibling) - } - } - function updateText(old, vnode) { - if (old.children.toString() !== vnode.children.toString()) { - old.dom.nodeValue = vnode.children - } - vnode.dom = old.dom - } - function updateHTML(parent, old, vnode, nextSibling) { - if (old.children !== vnode.children) { - toFragment(old) - insertNode(parent, createHTML(vnode), nextSibling) - } - else vnode.dom = old.dom - } - function updateFragment(parent, old, vnode, hooks, nextSibling) { - updateNodes(parent, old.children, vnode.children, hooks, nextSibling) - var domSize = 0, children = vnode.children - vnode.dom = null - if (children != null) { - for (var i = 0; i < children.length; i++) { - var child = children[i] - if (child != null) { - if (vnode.dom == null) vnode.dom = child.dom - domSize += child.domSize || 1 - } - } - if (domSize !== 1) vnode.domSize = domSize - } - } - function updateElement(old, vnode, hooks) { - var element = vnode.dom = old.dom - if (vnode.tag === "textarea") { - if (vnode.attrs == null) vnode.attrs = {} - if (vnode.text != null) vnode.attrs.value = vnode.text //FIXME handle multiple children - } - updateAttrs(vnode, old.attrs, vnode.attrs) - if (old.text != null && vnode.text != null && vnode.text !== "") { - if (old.text.toString() !== vnode.text.toString()) old.dom.firstChild.nodeValue = vnode.text - } - else { - if (old.text != null) old.children = [Node("#", undefined, undefined, old.text, undefined, old.dom.firstChild)] - if (vnode.text != null) vnode.children = [Node("#", undefined, undefined, vnode.text, undefined, undefined)] - updateNodes(element, old.children, vnode.children, hooks, null) - } - } - function updateComponent(parent, old, vnode, hooks, nextSibling, recycling) { - vnode.instance = Node.normalize(vnode.tag.view.call(vnode.state, vnode)) - updateLifecycle(vnode.tag, vnode, hooks, recycling) - updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, recycling) - vnode.dom = vnode.instance.dom - vnode.domSize = vnode.instance.domSize - } - function isRecyclable(old, vnodes) { - if (old.pool != null && Math.abs(old.pool.length - vnodes.length) <= Math.abs(old.length - vnodes.length)) { - var oldChildrenLength = old[0] && old[0].children && old[0].children.length || 0 - var poolChildrenLength = old.pool[0] && old.pool[0].children && old.pool[0].children.length || 0 - var vnodesChildrenLength = vnodes[0] && vnodes[0].children && vnodes[0].children.length || 0 - if (Math.abs(poolChildrenLength - vnodesChildrenLength) <= Math.abs(oldChildrenLength - vnodesChildrenLength)) { - return true - } - } - return false - } - function getKeyMap(vnodes, end) { - var map = {}, i = 0 - for (var i = 0; i < end; i++) { - var vnode = vnodes[i] - if (vnode != null) { - var key = vnode.key - if (key != null) map[key] = i - } - } - return map - } - function toFragment(vnode) { - var count = vnode.domSize - if (count != null) { - var fragment = $doc.createDocumentFragment() - if (count > 0) { - var dom = vnode.dom - while (--count) fragment.appendChild(dom.nextSibling) - fragment.insertBefore(dom, fragment.firstChild) - } - return fragment - } - else return vnode.dom - } - function getNextSibling(vnodes, i, nextSibling) { - for (; i < vnodes.length; i++) { - if (vnodes[i] != null) return vnodes[i].dom - } - return nextSibling - } - - function insertNode(parent, dom, nextSibling) { - if (nextSibling && nextSibling.parentNode) parent.insertBefore(dom, nextSibling) - else parent.appendChild(dom) - } - - //remove - function removeNodes(parent, vnodes, start, end, context) { - for (var i = start; i < end; i++) { - var vnode = vnodes[i] - if (vnode != null) { - if (vnode.skip) vnode.skip = undefined - else removeNode(parent, vnode, context, false) - } - } - } - function removeNode(parent, vnode, context, deferred) { - if (deferred === false) { - var expected = 0, called = 0 - var callback = function() { - if (++called === expected) removeNode(parent, vnode, context, true) - } - if (vnode.attrs && vnode.attrs.onbeforeremove) { - expected++ - vnode.attrs.onbeforeremove.call(vnode, vnode, callback) - } - if (typeof vnode.tag !== "string" && vnode.tag.onbeforeremove) { - expected++ - vnode.tag.onbeforeremove.call(vnode, vnode, callback) - } - if (expected > 0) return - } - - onremove(vnode) - if (vnode.dom) { - var count = vnode.domSize || 1 - if (count > 1) { - var dom = vnode.dom - while (--count) { - parent.removeChild(dom.nextSibling) - } - } - if (vnode.dom.parentNode != null) parent.removeChild(vnode.dom) - if (context != null && vnode.domSize == null && !hasIntegrationMethods(vnode)) { //TODO test custom elements - if (!context.pool) context.pool = [vnode] - else context.pool.push(vnode) - } - } - } - function onremove(vnode) { - if (vnode.attrs && vnode.attrs.onremove) vnode.attrs.onremove.call(vnode.state, vnode) - if (typeof vnode.tag !== "string" && vnode.tag.onremove) vnode.tag.onremove.call(vnode.state, vnode) - - var children = vnode.children - if (children instanceof Array) { - for (var i = 0; i < children.length; i++) { - var child = children[i] - if (child != null) onremove(child) - } - } - } - - //attrs - function setAttrs(vnode, attrs) { - for (var key in attrs) { - setAttr(vnode, key, null, attrs[key]) - } - } - function setAttr(vnode, key, old, value) { - var element = vnode.dom - if (key === "key" || (old === value && !isFormAttribute(vnode, key)) || typeof value === "undefined" || isLifecycleMethod(key)) return - var nsLastIndex = key.indexOf(":") - if (nsLastIndex > -1 && key.substr(0, nsLastIndex) === "xlink") { - element.setAttributeNS("http://www.w3.org/1999/xlink", key.slice(nsLastIndex + 1), value) - } - else if (key[0] === "o" && key[1] === "n" && typeof value === "function") updateEvent(vnode, key, value) - else if (key === "style") updateStyle(element, old, value) - else if (key in element && !isAttribute(key) && vnode.ns === undefined) { - //setting input[value] to same value by typing on focused element moves cursor to end in Chrome - if (vnode.tag === "input" && key === "value" && vnode.dom.value === value && vnode.dom === $doc.activeElement) return - element[key] = value - } - else { - if (typeof value === "boolean") { - if (value) element.setAttribute(key, "") - else element.removeAttribute(key) - } - else element.setAttribute(key === "className" ? "class" : key, value) - } - } - function setLateAttrs(vnode) { - var attrs = vnode.attrs - if (vnode.tag === "select" && attrs != null) { - if ("value" in attrs) setAttr(vnode, "value", null, attrs.value) - if ("selectedIndex" in attrs) setAttr(vnode, "selectedIndex", null, attrs.selectedIndex) - } - } - function updateAttrs(vnode, old, attrs) { - if (attrs != null) { - for (var key in attrs) { - setAttr(vnode, key, old && old[key], attrs[key]) - } - } - if (old != null) { - for (var key in old) { - if (attrs == null || !(key in attrs)) { - if (key !== "key") vnode.dom.removeAttribute(key) - } - } - } - } - function isFormAttribute(vnode, attr) { - return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === $doc.activeElement - } - function isLifecycleMethod(attr) { - return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "shouldUpdate" - } - function isAttribute(attr) { - return attr === "href" || attr === "list" || attr === "form"// || attr === "type" || attr === "width" || attr === "height" - } - function hasIntegrationMethods(vnode) { - return vnode.attrs != null && (vnode.attrs.oncreate || vnode.attrs.onupdate || vnode.attrs.onbeforeremove || vnode.attrs.onremove) - } - - //style - function updateStyle(element, old, style) { - if (style == null) element.style = "" - else if (typeof style === "string") element.style = style - else { - if (typeof old === "string") element.style = "" - for (var key in style) { - element.style[key] = style[key] - } - if (old != null && typeof old !== "string") { - for (var key in old) { - if (!(key in style)) element.style[key] = "" - } - } - } - } - - //event - function updateEvent(vnode, key, value) { - var element = vnode.dom - var callback = function(e) { - var result = value.call(element, e) - if (typeof onevent === "function") onevent.call(element, e) - return result - } - if (key in element) element[key] = callback - else { - var eventName = key.slice(2) - if (vnode.events === undefined) vnode.events = {} - if (vnode.events[key] != null) element.removeEventListener(eventName, vnode.events[key], false) - vnode.events[key] = callback - element.addEventListener(eventName, vnode.events[key], false) - } - } - - //lifecycle - function initLifecycle(source, vnode, hooks) { - if (source.oninit != null) source.oninit.call(vnode.state, vnode) - if (source.oncreate != null) hooks.push(source.oncreate.bind(vnode.state, vnode)) - } - function updateLifecycle(source, vnode, hooks, recycling) { - if (recycling) initLifecycle(source, vnode, hooks) - else if (source.onupdate != null) hooks.push(source.onupdate.bind(vnode.state, vnode)) - } - function shouldUpdate(vnode, old) { - var forceVnodeUpdate, forceComponentUpdate - if (vnode.attrs != null && typeof vnode.attrs.shouldUpdate === "function") forceVnodeUpdate = vnode.attrs.shouldUpdate.call(vnode.state, vnode, old) - if (typeof vnode.tag !== "string" && typeof vnode.tag.shouldUpdate === "function") forceComponentUpdate = vnode.tag.shouldUpdate.call(vnode.state, 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 - } - - function copy(data) { - if (data instanceof Array) { - var output = [] - for (var i = 0; i < data.length; i++) output[i] = copy(data[i]) - return output - } - else if (typeof data === "object") { - var output = {} - for (var i in data) output[i] = copy(data[i]) - return output - } - return data - } - - function render(dom, vnodes) { - var hooks = [] - var active = $doc.activeElement - if (dom.vnodes == null) dom.vnodes = [] - - if (!(vnodes instanceof Array)) vnodes = [vnodes] - updateNodes(dom, dom.vnodes, Node.normalizeChildren(vnodes), hooks, null) - for (var i = 0; i < hooks.length; i++) hooks[i]() - dom.vnodes = vnodes - if ($doc.activeElement !== active) active.focus() - } - - return {render: render, setEventCallback: setEventCallback} -} - - - -var createRenderer = function($window) { +var coreRenderer = function($window) { var $doc = $window.document var onevent @@ -1070,12 +579,11 @@ var createRenderer = function($window) { var throttle = function(callback) { //60fps translates to 16.6ms, round it down since setTimeout requires int - var time = 16 + var time = 16 var last = 0, pending = null var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout return function(synchronous) { var now = new Date().getTime() - var diff = now - last if (synchronous === true || last === 0 || now - last >= time) { last = now callback() @@ -1090,9 +598,8 @@ var throttle = function(callback) { } } - -var createMounter = function($window, redraw) { - var renderer = createRenderer($window) +var apiMounter = function($window, redraw) { + var renderer = coreRenderer($window) return function(root, component) { var run = throttle(function() { renderer.render(root, {tag: component}) @@ -1105,8 +612,7 @@ var createMounter = function($window, redraw) { } } - -var buildQueryString = function buildQueryString(object) { +var buildQueryString = function(object) { if (Object.prototype.toString.call(object) !== "[object Object]") return "" var args = [] @@ -1129,7 +635,7 @@ var buildQueryString = function buildQueryString(object) { else args.push(encodeURIComponent(key) + (value != null && value !== "" ? "=" + encodeURIComponent(value) : "")) } } -var parseQueryString = function parseQueryString(string) { +var parseQueryString = function(string) { if (string === "" || string == null) return {} if (string.charAt(0) === "?") string = string.slice(1) @@ -1170,7 +676,7 @@ var parseQueryString = function parseQueryString(string) { return data } -var createRouter = function($window) { +var coreRouter = function($window) { var supportsPushState = typeof $window.history.pushState === "function" && $window.location.protocol !== "file:" var prefix = "#!" @@ -1274,10 +780,9 @@ var createRouter = function($window) { return {setPrefix: setPrefix, getPath: getPath, setPath: setPath, defineRoutes: defineRoutes, link: link} } - -var createRouterInstance = function($window, redraw) { - var renderer = createRenderer($window) - var router = createRouter($window) +var apiRouter = function($window, redraw) { + var renderer = coreRenderer($window) + var router = coreRouter($window) var route = function(root, defaultRoute, routes) { var replay = router.defineRoutes(routes, function(component, args) { renderer.render(root, {tag: component, attrs: args}) @@ -1295,9 +800,7 @@ var createRouterInstance = function($window, redraw) { return route } - - -var createRequester = function($window, Promise) { +var coreRequester = function($window, Promise) { var callbackCount = 0 function ajax(args) { @@ -1362,7 +865,7 @@ var createRequester = function($window, Promise) { resolve(data) $window[callbackKey] = undefined } - script.onerror = function(e) { + script.onerror = function() { script.parentNode.removeChild(script) reject(new Error("JSONP request failed")) $window[callbackKey] = undefined @@ -1407,15 +910,16 @@ var createRequester = function($window, Promise) { return {ajax: ajax, jsonp: jsonp} } + var redraw = {run: function() {}} m.redraw = function() { redraw.run() } m.trust = trust -m.render = createRenderer(window).render -m.mount = createMounter(window, redraw) -m.route = createRouterInstance(window, redraw) -m.request = createRequester(window, Promise).ajax +m.render = coreRenderer(window).render +m.mount = apiMounter(window, redraw) +m.route = apiRouter(window, redraw) +m.request = coreRequester(window, Promise).ajax module.exports = m diff --git a/querystring/build.js b/querystring/build.js index 74253624..61a21ba5 100644 --- a/querystring/build.js +++ b/querystring/build.js @@ -1,6 +1,6 @@ "use strict" -module.exports = function buildQueryString(object) { +module.exports = function(object) { if (Object.prototype.toString.call(object) !== "[object Object]") return "" var args = [] diff --git a/querystring/parse.js b/querystring/parse.js index b9148d0b..2783cf27 100644 --- a/querystring/parse.js +++ b/querystring/parse.js @@ -1,6 +1,6 @@ "use strict" -module.exports = function parseQueryString(string) { +module.exports = function(string) { if (string === "" || string == null) return {} if (string.charAt(0) === "?") string = string.slice(1)