Merge branch 'rewrite' into multi-mount-test
This commit is contained in:
commit
e43d638f54
15 changed files with 515 additions and 194 deletions
|
|
@ -6,7 +6,7 @@ module.exports = function(root, renderer, pubsub, callback) {
|
|||
var run = throttle(callback)
|
||||
if (renderer != null) {
|
||||
renderer.setEventCallback(function(e) {
|
||||
if (e.redraw !== false) run()
|
||||
if (e.redraw !== false) pubsub.publish()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ module.exports = function($window, renderer, pubsub) {
|
|||
renderer.render(root, Node(payload, null, args, undefined, undefined, undefined))
|
||||
}
|
||||
}, function() {
|
||||
router.setPath(defaultRoute)
|
||||
router.setPath(defaultRoute, null, {replace: true})
|
||||
})
|
||||
autoredraw(root, renderer, pubsub, replay)
|
||||
}
|
||||
|
|
@ -31,6 +31,6 @@ module.exports = function($window, renderer, pubsub) {
|
|||
route.prefix = router.setPrefix
|
||||
route.set = router.setPath
|
||||
route.get = router.getPath
|
||||
|
||||
|
||||
return route
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,45 @@ o.spec("route", function() {
|
|||
})
|
||||
})
|
||||
|
||||
o("default route doesn't break back button", function(done) {
|
||||
$window.location.href = "http://google.com"
|
||||
route(root, "/a", {
|
||||
"/a" : {
|
||||
view: function() {
|
||||
return m("div")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
setTimeout(function() {
|
||||
o(root.firstChild.nodeName).equals("DIV")
|
||||
|
||||
$window.history.back()
|
||||
|
||||
o($window.location.pathname).equals("/")
|
||||
|
||||
done()
|
||||
}, FRAME_BUDGET)
|
||||
})
|
||||
|
||||
o("default route does not inherit params", function(done) {
|
||||
$window.location.href = "/invalid?foo=bar"
|
||||
route(root, "/a", {
|
||||
"/a" : {
|
||||
oninit: init,
|
||||
view: function() {
|
||||
return m("div")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function init(vnode) {
|
||||
o(vnode.attrs).deepEquals({})
|
||||
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
||||
o("redraws when render function is executed", function(done) {
|
||||
var onupdate = o.spy()
|
||||
var oninit = o.spy()
|
||||
|
|
|
|||
14
docs/prop.md
14
docs/prop.md
|
|
@ -4,6 +4,7 @@
|
|||
- [Static members](#static-members)
|
||||
- [prop.combine](#prop-combine)
|
||||
- [prop.reject](#prop-reject)
|
||||
- [prop.merge](#prop-merge)
|
||||
- [prop.HALT](#prop-halt)
|
||||
- [Instance members](#static-members)
|
||||
- [stream.run](#stream-run)
|
||||
|
|
@ -85,6 +86,19 @@ Argument | Type | Required | Description
|
|||
|
||||
[How to read signatures](signatures.md)
|
||||
|
||||
##### prop.merge
|
||||
|
||||
Creates a stream whose value is the array of values from an array of streams
|
||||
|
||||
`stream = m.prop.merge(streams)`
|
||||
|
||||
Argument | Type | Required | Description
|
||||
------------ | -------------------- | -------- | ---
|
||||
`streams` | `Array<Stream>` | Yes | A list of streams
|
||||
**returns** | `Stream` | | Returns a stream whose value is an array of input stream values
|
||||
|
||||
[How to read signatures](signatures.md)
|
||||
|
||||
##### prop.HALT
|
||||
|
||||
A special value that can be returned to stream callbacks to halt execution of downstreams
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
- [Reading/writing the current route](#readingwriting-the-current-route)
|
||||
- [Accessing route params](#accessing-route-params)
|
||||
- [Setting route prefix](#setting-route-prefix)
|
||||
- [m.request](#mrequest)
|
||||
|
||||
## `config` function
|
||||
|
||||
|
|
@ -270,3 +271,57 @@ m.route.mode = "pathname";
|
|||
```js
|
||||
m.route.prefix("");
|
||||
```
|
||||
|
||||
## m.request
|
||||
|
||||
[m.request](request.md) now returns an [m.prop stream](prop.md) instead of a promise. The main difference is you'll have to use `.run` to get similar functionality as a promise's `.then`:
|
||||
|
||||
### `v0.2.x`
|
||||
|
||||
```js
|
||||
m.request({ method: 'GET', url: 'https://api.github.com/' })
|
||||
.then(function (responseBody) {
|
||||
return m.request({ method: 'GET', url: responseBody.emojis_url });
|
||||
})
|
||||
.then(function (emojis) {
|
||||
console.log("+1 url:", emojis['+1']);
|
||||
});
|
||||
```
|
||||
|
||||
### `v1.x`
|
||||
|
||||
```js
|
||||
m.request({ method: 'GET', url: 'https://api.github.com/' })
|
||||
.run(function (responseBody) {
|
||||
return m.request({ method: 'GET', url: responseBody.emojis_url });
|
||||
})
|
||||
.run(function (emojis) {
|
||||
console.log("+1 url:", emojis['+1']);
|
||||
});
|
||||
```
|
||||
|
||||
The equivalent of `m.sync` is now `m.prop.sync`:
|
||||
|
||||
### `v0.2.x`
|
||||
|
||||
```js
|
||||
m.sync([
|
||||
m.request({ method: 'GET', url: 'https://api.github.com/users/lhorie' }),
|
||||
m.request({ method: 'GET', url: 'https://api.github.com/users/isiahmeadows' }),
|
||||
])
|
||||
.then(function (users) {
|
||||
console.log("Contributors:", users[0].name, "and", users[1].name);
|
||||
});
|
||||
```
|
||||
|
||||
### `v1.x`
|
||||
|
||||
```js
|
||||
m.prop.sync([
|
||||
m.request({ method: 'GET', url: 'https://api.github.com/users/lhorie' }),
|
||||
m.request({ method: 'GET', url: 'https://api.github.com/users/isiahmeadows' }),
|
||||
])
|
||||
.run(function (users) {
|
||||
console.log("Contributors:", users[0].name, "and", users[1].name);
|
||||
});
|
||||
```
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ The `tag` property of a vnode determines its type. There are five vnode types:
|
|||
Vnode type | Example | Description
|
||||
------------ | ------------------------------ | ---
|
||||
Element | `{tag: "div"}` | Represents a DOM element.
|
||||
Fragment | `{tag: "[", children: []}` | Represents a list of DOM elements whose parent DOM element may also contain other elements that are not in the fragment.
|
||||
Fragment | `{tag: "[", children: []}` | Represents a list of DOM elements whose parent DOM element may also contain other elements that are not in the fragment. When using the [`m()`](hyperscript.md) helper function, fragment vnodes can only be created by nesting arrays into the `children` parameter of `m()`. `m("[")` does not create a valid vnode.
|
||||
Text | `{tag: "#", children: ""}` | Represents a DOM text node.
|
||||
Trusted HTML | `{tag: "<", children: "<br>"}` | Represents a list of DOM elements from an HTML string.
|
||||
Component | `{tag: ExampleComponent}` | If `tag` is a Javascript object with a `view` method, the vnode represents the DOM generated by rendering the component.
|
||||
|
|
|
|||
1
index.js
1
index.js
|
|
@ -19,6 +19,7 @@ m.trust = require("./render/trust")
|
|||
m.prop = Stream.stream
|
||||
m.prop.combine = Stream.combine
|
||||
m.prop.reject = Stream.reject
|
||||
m.prop.merge = Stream.merge
|
||||
m.prop.HALT = Stream.HALT
|
||||
m.withAttr = require("./util/withAttr")
|
||||
m.render = renderService.render
|
||||
|
|
|
|||
81
mithril.js
81
mithril.js
|
|
@ -7,18 +7,15 @@ function createStream() {
|
|||
return stream._state.value
|
||||
}
|
||||
initStream(stream, arguments)
|
||||
|
||||
if (arguments.length > 0) updateStream(stream, arguments[0], undefined)
|
||||
|
||||
return stream
|
||||
}
|
||||
function initStream(stream, args) {
|
||||
stream.constructor = createStream
|
||||
stream._state = {id: guid++, value: undefined, error: undefined, state: 0, derive: undefined, recover: undefined, deps: {}, parents: [], errorStream: undefined, endStream: undefined}
|
||||
stream.map = map, stream.ap = ap, stream.of = createStream
|
||||
stream.valueOf = valueOf, stream.toJSON = toJSON
|
||||
stream.valueOf = valueOf, stream.toJSON = toJSON, stream.toString = valueOf
|
||||
stream.run = run, stream.catch = doCatch
|
||||
|
||||
Object.defineProperties(stream, {
|
||||
error: {get: function() {
|
||||
if (!stream._state.errorStream) {
|
||||
|
|
@ -58,7 +55,10 @@ function updateState(stream, value, error) {
|
|||
if (recovered === HALT) return
|
||||
updateValues(stream, recovered, undefined)
|
||||
}
|
||||
catch (e) {updateValues(stream, undefined, e)}
|
||||
catch (e) {
|
||||
updateValues(stream, undefined, e)
|
||||
reportUncaughtError(stream, e)
|
||||
}
|
||||
}
|
||||
else updateValues(stream, value, error)
|
||||
stream._state.changed = true
|
||||
|
|
@ -81,6 +81,7 @@ function updateDependency(stream, mustSync) {
|
|||
}
|
||||
catch (e) {
|
||||
updateState(stream, undefined, e)
|
||||
reportUncaughtError(stream, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -96,6 +97,13 @@ function finalize(stream) {
|
|||
stream._state.changed = false
|
||||
for (var id in stream._state.deps) stream._state.deps[id]._state.changed = false
|
||||
}
|
||||
function reportUncaughtError(stream, e) {
|
||||
if (Object.keys(stream._state.deps).length === 0) {
|
||||
setTimeout(function() {
|
||||
if (Object.keys(stream._state.deps).length === 0) console.error(e)
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
function run(fn) {
|
||||
var self = createStream(), stream = this
|
||||
return initDependency(self, [stream], function() {
|
||||
|
|
@ -130,10 +138,8 @@ function initDependency(dep, streams, derive, recover) {
|
|||
state.derive = derive
|
||||
state.recover = recover
|
||||
state.parents = streams.filter(notEnded)
|
||||
|
||||
registerDependency(dep, state.parents)
|
||||
updateDependency(dep, true)
|
||||
|
||||
return dep
|
||||
}
|
||||
function registerDependency(stream, parents) {
|
||||
|
|
@ -168,7 +174,12 @@ function reject(e) {
|
|||
stream.error(e)
|
||||
return stream
|
||||
}
|
||||
var Stream = {stream: createStream, combine: combine, reject: reject, HALT: HALT}
|
||||
function merge(streams) {
|
||||
return combine(function () {
|
||||
return streams.map(function (s) {return s()})
|
||||
}, streams)
|
||||
}
|
||||
var Stream = {stream: createStream, merge: merge, combine: combine, reject: reject, HALT: HALT}
|
||||
function Node(tag, key, attrs, children, text, dom) {
|
||||
return {tag: tag, key: key, attrs: attrs, children: children, text: text, dom: dom, domSize: undefined, state: {}, events: undefined, instance: undefined}
|
||||
}
|
||||
|
|
@ -328,10 +339,13 @@ var renderService = function($window) {
|
|||
if (vnode.instance != null) {
|
||||
var element = createNode(vnode.instance, hooks, ns)
|
||||
vnode.dom = vnode.instance.dom
|
||||
vnode.domSize = vnode.instance.domSize
|
||||
vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0
|
||||
return element
|
||||
}
|
||||
else return $emptyFragment
|
||||
else {
|
||||
vnode.domSize = 0
|
||||
return $emptyFragment
|
||||
}
|
||||
}
|
||||
//update
|
||||
function updateNodes(parent, old, vnodes, hooks, nextSibling, ns) {
|
||||
|
|
@ -341,12 +355,12 @@ var renderService = function($window) {
|
|||
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) {
|
||||
else if (o != null && v != null && o.key === v.key && o.tag === v.tag) {
|
||||
oldStart++, start++
|
||||
updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling, ns)
|
||||
if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
|
||||
|
|
@ -354,7 +368,7 @@ var renderService = function($window) {
|
|||
else {
|
||||
var o = old[oldEnd]
|
||||
if (o === v) oldEnd--, start++
|
||||
else if (o != null && v != null && o.key === v.key) {
|
||||
else if (o != null && v != null && o.key === v.key && o.tag === v.tag) {
|
||||
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
|
||||
insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling))
|
||||
oldEnd--, start++
|
||||
|
|
@ -365,10 +379,10 @@ var renderService = function($window) {
|
|||
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) {
|
||||
else if (o != null && v != null && o.key === v.key && o.tag === v.tag) {
|
||||
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
|
||||
if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
|
||||
nextSibling = o.dom
|
||||
if (o.dom != null) nextSibling = o.dom
|
||||
oldEnd--, end--
|
||||
}
|
||||
else {
|
||||
|
|
@ -380,7 +394,7 @@ var renderService = function($window) {
|
|||
updateNode(parent, movable, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
|
||||
insertNode(parent, toFragment(movable), nextSibling)
|
||||
old[oldIndex].skip = true
|
||||
nextSibling = movable.dom
|
||||
if (movable.dom != null) nextSibling = movable.dom
|
||||
}
|
||||
else {
|
||||
var dom = createNode(v, hooks, undefined)
|
||||
|
|
@ -440,7 +454,7 @@ var renderService = function($window) {
|
|||
if (children != null) {
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var child = children[i]
|
||||
if (child != null) {
|
||||
if (child != null && child.dom != null) {
|
||||
if (vnode.dom == null) vnode.dom = child.dom
|
||||
domSize += child.domSize || 1
|
||||
}
|
||||
|
|
@ -479,7 +493,12 @@ var renderService = function($window) {
|
|||
}
|
||||
else if (old.instance != null) {
|
||||
removeNode(parent, old.instance, null, false)
|
||||
vnode.dom = vnode.domSize = undefined
|
||||
vnode.dom = undefined
|
||||
vnode.domSize = 0
|
||||
}
|
||||
else {
|
||||
vnode.dom = old.dom
|
||||
vnode.domSize = old.domSize
|
||||
}
|
||||
}
|
||||
function isRecyclable(old, vnodes) {
|
||||
|
|
@ -506,7 +525,7 @@ var renderService = function($window) {
|
|||
}
|
||||
function toFragment(vnode) {
|
||||
var count = vnode.domSize
|
||||
if (count != null) {
|
||||
if (count != null || vnode.dom == null) {
|
||||
var fragment = $doc.createDocumentFragment()
|
||||
if (count > 0) {
|
||||
var dom = vnode.dom
|
||||
|
|
@ -519,7 +538,7 @@ var renderService = function($window) {
|
|||
}
|
||||
function getNextSibling(vnodes, i, nextSibling) {
|
||||
for (; i < vnodes.length; i++) {
|
||||
if (vnodes[i] != null) return vnodes[i].dom
|
||||
if (vnodes[i] != null && vnodes[i].dom != null) return vnodes[i].dom
|
||||
}
|
||||
return nextSibling
|
||||
}
|
||||
|
|
@ -572,11 +591,14 @@ var renderService = function($window) {
|
|||
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)
|
||||
if (vnode.instance != null) onremove(vnode.instance)
|
||||
else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -699,12 +721,12 @@ var renderService = function($window) {
|
|||
function copy(data) {
|
||||
if (data instanceof Array) {
|
||||
var output = []
|
||||
for (var i = 0; i < data.length; i++) output[i] = copy(data[i])
|
||||
for (var i = 0; i < data.length; i++) output[i] = data[i]
|
||||
return output
|
||||
}
|
||||
else if (typeof data === "object") {
|
||||
var output = {}
|
||||
for (var i in data) output[i] = copy(data[i])
|
||||
for (var i in data) output[i] = data[i]
|
||||
return output
|
||||
}
|
||||
return data
|
||||
|
|
@ -1030,7 +1052,7 @@ var autoredraw = function(root, renderer, pubsub, callback) {
|
|||
var run = throttle(callback)
|
||||
if (renderer != null) {
|
||||
renderer.setEventCallback(function(e) {
|
||||
if (e.redraw !== false) run()
|
||||
if (e.redraw !== false) pubsub.publish()
|
||||
})
|
||||
}
|
||||
if (pubsub != null) {
|
||||
|
|
@ -1058,7 +1080,7 @@ m.route = function($window, renderer, pubsub) {
|
|||
renderer.render(root, Node(payload, null, args, undefined, undefined, undefined))
|
||||
}
|
||||
}, function() {
|
||||
router.setPath(defaultRoute)
|
||||
router.setPath(defaultRoute, null, {replace: true})
|
||||
})
|
||||
autoredraw(root, renderer, pubsub, replay)
|
||||
}
|
||||
|
|
@ -1083,6 +1105,7 @@ m.trust = function(html) {
|
|||
m.prop = Stream.stream
|
||||
m.prop.combine = Stream.combine
|
||||
m.prop.reject = Stream.reject
|
||||
m.prop.merge = Stream.merge
|
||||
m.prop.HALT = Stream.HALT
|
||||
m.withAttr = function(attrName, callback, context) {
|
||||
return function(e) {
|
||||
|
|
|
|||
38
mithril.min.js
vendored
Normal file
38
mithril.min.js
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
(function(){function y(){function a(){0<arguments.length&&G(a,arguments[0],void 0);return a._state.value}M(a,arguments);0<arguments.length&&G(a,arguments[0],void 0);return a}function M(a,b){a.constructor=y;a._state={id:Y++,value:void 0,error:void 0,state:0,derive:void 0,recover:void 0,deps:{},parents:[],errorStream:void 0,endStream:void 0};a.map=Z;a.ap=aa;a.of=y;a.valueOf=N;a.toJSON=ba;a.toString=N;a.run=ca;a["catch"]=da;Object.defineProperties(a,{error:{get:function(){if(!a._state.errorStream){var b=
|
||||
function(){0<arguments.length&&G(a,void 0,arguments[0]);return a._state.error};M(b,[]);C(b,[a],O,O);a._state.errorStream=b}return a._state.errorStream}},end:{get:function(){if(!a._state.endStream){var b=y();b.map(function(e){!0===e&&(P(a),P(b));return e});a._state.endStream=b}return a._state.endStream}}})}function G(a,b,h){D(a,b,h);for(var e in a._state.deps)Q(a._state.deps[e],!1);a._state.changed=!1;for(var f in a._state.deps)a._state.deps[f]._state.changed=!1}function D(a,b,h){h=R(b,h);if(void 0!==
|
||||
h&&"function"===typeof a._state.recover)try{var e=a._state.recover();if(e===E)return;a._state.value=e;a._state.error=void 0}catch(f){a._state.value=void 0,a._state.error=f}else a._state.value=b,a._state.error=h;a._state.changed=!0;2!==a._state.state&&(a._state.state=1)}function Q(a,b){var h=a._state,e=h.parents;if(0<e.length&&e.filter(ea).length===e.length&&(b||0<e.filter(S).length))if(e=e.filter(T),0<e.length)D(a,void 0,e[0]._state.error);else try{var f=h.derive();f!==E&&D(a,f,void 0)}catch(k){D(a,
|
||||
void 0,k)}}function R(a,b){null!=a&&a.constructor===y&&(b=void 0!==a._state.error?a._state.error:R(a._state.value,a._state.error));return b}function ca(a){var b=y(),h=this;return C(b,[h],function(){return U(b,a(h()))},void 0)}function da(a){var b=y(),h=this;return C(b,[h],function(){return h._state.value},function(){return U(b,a(h._state.error))})}function H(a,b){return C(y(),b,function(){var h=b.filter(T);if(0<h.length)throw h[0]._state.error;return a.apply(this,b.concat([b.filter(S)]))},void 0)}
|
||||
function U(a,b){if(null!=b&&b.constructor===y){b.error.map(a.error);b.map(a);if(0===b._state.state)return E;if(b._state.error)throw b._state.error;b=b._state.value}return b}function C(a,b,h,e){var f=a._state;f.derive=h;f.recover=e;f.parents=b.filter(fa);V(a,f.parents);Q(a,!0);return a}function V(a,b){for(var h=0;h<b.length;h++)b[h]._state.deps[a._state.id]=a,V(a,b[h]._state.parents)}function P(a){for(var b=0;b<a._state.parents.length;b++)delete a._state.parents[b]._state.deps[a._state.id];for(var h in a._state.deps){var b=
|
||||
a._state.deps[h],e=b._state.parents.indexOf(a);-1<e&&b._state.parents.splice(e,1)}a._state.state=2;a._state.deps={}}function Z(a){return H(function(b){return a(b())},[this])}function aa(a){return H(function(a,h){return a()(h())},[this,a])}function N(){return this._state.value}function ba(){return JSON.stringify(this._state.value)}function ea(a){return 1===a._state.state}function S(a){return a._state.changed}function fa(a){return 2!==a._state.state}function T(a){return a._state.error}function r(a,
|
||||
b,h,e,f,k){return{tag:a,key:b,attrs:h,children:e,text:f,dom:k,domSize:void 0,state:{},events:void 0,instance:void 0}}var Y=0,O=function(){},E={},z={stream:y,combine:H,reject:function(a){var b=y();b.error(a);return b},HALT:E};r.normalize=function(a){return a instanceof Array?r("[",void 0,void 0,r.normalizeChildren(a),void 0,void 0):null!=a&&"object"!==typeof a?r("#",void 0,void 0,a,void 0,void 0):a};r.normalizeChildren=function(a){for(var b=0;b<a.length;b++)a[b]=r.normalize(a[b]);return a};var ga=
|
||||
/(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g,I={},n=function(a){if("string"===typeof a&&void 0===I[a]){for(var b,h,e=[],f={};b=ga.exec(a);){var k=b[1],l=b[2];""===k&&""!==l?h=l:"#"===k?f.id=l:"."===k?e.push(l):"["===b[3][0]&&((k=b[6])&&(k=k.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")),f[b[4]]=k||!0)}0<e.length&&(f.className=e.join(" "));I[a]=function(a,b){var d=!1,e,k,l=a.className||a["class"],w;for(w in f)a[w]=f[w];void 0!==l&&(void 0!==a["class"]&&(a["class"]=
|
||||
void 0,a.className=l),void 0!==f.className&&(a.className=f.className+" "+l));for(w in a)if("key"!==w){d=!0;break}b instanceof Array&&1==b.length&&null!=b[0]&&"#"===b[0].tag?k=b[0].children:e=b;return r(h||"div",a.key,d?a:void 0,e,k,void 0)}}var d;null!=arguments[1]&&("object"!==typeof arguments[1]||void 0!==arguments[1].tag||arguments[1]instanceof Array)?e=1:(d=arguments[1],e=2);if(arguments.length===e+1)b=arguments[e]instanceof Array?arguments[e]:[arguments[e]];else for(b=[];e<arguments.length;e++)b.push(arguments[e]);
|
||||
return"string"===typeof a?I[a](d||{},r.normalizeChildren(b)):r(a,d&&d.key,d||{},r.normalizeChildren(b),void 0,void 0)},J=function(a){function b(a,c,g,b,d,e,f){for(;g<b;g++){var k=c[g];null!=k&&m(a,h(k,d,f),e)}}function h(a,c,g){var d=a.tag;null!=a.attrs&&n(a.attrs,a,c);if("string"===typeof d)switch(d){case "#":return a.dom=q.createTextNode(a.children);case "<":return e(a);case "[":var m=q.createDocumentFragment();null!=a.children&&(d=a.children,b(m,d,0,d.length,c,null,g));a.dom=m.firstChild;a.domSize=
|
||||
m.childNodes.length;return m;default:var f=a.tag;switch(a.tag){case "svg":g="http://www.w3.org/2000/svg";break;case "math":g="http://www.w3.org/1998/Math/MathML"}var k=(d=a.attrs)&&d.is,f=g?k?q.createElementNS(g,f,k):q.createElementNS(g,f):k?q.createElement(f,k):q.createElement(f);a.dom=f;if(null!=d)for(m in k=g,d)B(a,m,null,d[m],k);null!=a.text&&(""!==a.text?f.textContent=a.text:a.children=[r("#",void 0,void 0,a.text,void 0,void 0)]);null!=a.children&&(m=a.children,b(f,m,0,m.length,c,null,g),c=a.attrs,
|
||||
"select"===a.tag&&null!=c&&("value"in c&&B(a,"value",null,c.value,void 0),"selectedIndex"in c&&B(a,"selectedIndex",null,c.selectedIndex,void 0)));return f}else return a.state=z(a.tag),n(a.tag,a,c),a.instance=r.normalize(a.tag.view.call(a.state,a)),null!=a.instance?(c=h(a.instance,c,g),a.dom=a.instance.dom,a.domSize=a.instance.domSize,a=c):a=ha,a}function e(a){var c={caption:"table",thead:"table",tbody:"table",tfoot:"table",tr:"tbody",th:"tr",td:"tr",colgroup:"table",col:"colgroup"}[(a.children.match(/^\s*?<(\w+)/im)||
|
||||
[])[1]]||"div",c=q.createElement(c);c.innerHTML=a.children;a.dom=c.firstChild;a.domSize=c.childNodes.length;a=q.createDocumentFragment();for(var g;g=c.firstChild;)a.appendChild(g);return a}function f(a,c,g,e,f,p){if(null!=c||null!=g)if(null==c)b(a,g,0,g.length,e,f,void 0);else if(null==g)A(a,c,0,c.length,g);else{var t;a:{if(null!=c.pool&&Math.abs(c.pool.length-g.length)<=Math.abs(c.length-g.length)&&(t=g[0]&&g[0].children&&g[0].children.length||0,Math.abs((c.pool[0]&&c.pool[0].children&&c.pool[0].children.length||
|
||||
0)-t)<=Math.abs((c[0]&&c[0].children&&c[0].children.length||0)-t))){t=!0;break a}t=!1}t&&(c=c.concat(c.pool));for(var B=0,w=0,u=c.length-1,r=g.length-1,n;u>=B&&r>=w;){var v=c[B],x=g[w];if(v===x)B++,w++;else if(null!=v&&null!=x&&v.key===x.key)B++,w++,k(a,v,x,e,d(c,B,f),t,p),t&&v.tag===x.tag&&m(a,l(v),f);else if(v=c[u],v===x)u--,w++;else if(null!=v&&null!=x&&v.key===x.key)k(a,v,x,e,d(c,u+1,f),t,p),m(a,l(v),d(c,B,f)),u--,w++;else break}for(;u>=B&&r>=w;){v=c[u];x=g[r];if(v===x)u--;else if(null!=v&&null!=
|
||||
x&&v.key===x.key)k(a,v,x,e,d(c,u+1,f),t,p),t&&v.tag===x.tag&&m(a,l(v),f),f=v.dom,u--;else{if(!n){n=c;var v=u,q={},y;for(y=0;y<v;y++){var z=n[y];null!=z&&(z=z.key,null!=z&&(q[z]=y))}n=q}null!=x&&(v=n[x.key],null!=v?(q=c[v],k(a,q,x,e,d(c,u+1,f),t,p),m(a,l(q),f),c[v].skip=!0,f=q.dom):(x=h(x,e,void 0),m(a,x,f),f=x))}r--;if(r<w)break}b(a,g,w,r+1,e,f,void 0);A(a,c,B,u+1,g)}}function k(a,c,g,b,d,A,t){var u=c.tag;if(u===g.tag){g.state=c.state;g.events=c.events;var w;var n;null!=g.attrs&&"function"===typeof g.attrs.onbeforeupdate&&
|
||||
(w=g.attrs.onbeforeupdate.call(g.state,g,c));"string"!==typeof g.tag&&"function"===typeof g.tag.onbeforeupdate&&(n=g.tag.onbeforeupdate.call(g.state,g,c));void 0===w&&void 0===n||w||n?w=!1:(g.dom=c.dom,g.domSize=c.domSize,g.instance=c.instance,w=!0);if(!w)if(null!=g.attrs&&y(g.attrs,g,b,A),"string"===typeof u)switch(u){case "#":c.children.toString()!==g.children.toString()&&(c.dom.nodeValue=g.children);g.dom=c.dom;break;case "<":c.children!==g.children?(l(c),m(a,e(g),d)):g.dom=c.dom;break;case "[":f(a,
|
||||
c.children,g.children,b,d,t);c=0;b=g.children;g.dom=null;if(null!=b){for(var q=0;q<b.length;q++)a=b[q],null!=a&&(null==g.dom&&(g.dom=a.dom),c+=a.domSize||1);1!==c&&(g.domSize=c)}break;default:a=t;d=g.dom=c.dom;switch(g.tag){case "svg":a="http://www.w3.org/2000/svg";break;case "math":a="http://www.w3.org/1998/Math/MathML"}"textarea"===g.tag&&(null==g.attrs&&(g.attrs={}),null!=g.text&&(g.attrs.value=g.text));A=c.attrs;t=g.attrs;u=a;if(null!=t)for(q in t)B(g,q,A&&A[q],t[q],u);if(null!=A)for(q in A)null!=
|
||||
t&&q in t||"key"!==q&&g.dom.removeAttribute(q);null!=c.text&&null!=g.text&&""!==g.text?c.text.toString()!==g.text.toString()&&(c.dom.firstChild.nodeValue=g.text):(null!=c.text&&(c.children=[r("#",void 0,void 0,c.text,void 0,c.dom.firstChild)]),null!=g.text&&(g.children=[r("#",void 0,void 0,g.text,void 0,void 0)]),f(d,c.children,g.children,b,null,a))}else g.instance=r.normalize(g.tag.view.call(g.state,g)),y(g.tag,g,b,A),null!=g.instance?(null==c.instance?m(a,h(g.instance,b,t),d):k(a,c.instance,g.instance,
|
||||
b,d,A,t),g.dom=g.instance.dom,g.domSize=g.instance.domSize):null!=c.instance&&(p(a,c.instance,null,!1),g.dom=g.domSize=void 0)}else p(a,c,null,!1),m(a,h(g,b,void 0),d)}function l(a){var c=a.domSize;if(null!=c){var b=q.createDocumentFragment();if(0<c){for(a=a.dom;--c;)b.appendChild(a.nextSibling);b.insertBefore(a,b.firstChild)}return b}return a.dom}function d(a,c,b){for(;c<a.length;c++)if(null!=a[c])return a[c].dom;return b}function m(a,c,b){b&&b.parentNode?a.insertBefore(c,b):a.appendChild(c)}function A(a,
|
||||
c,b,d,f){for(;b<d;b++){var e=c[b];null!=e&&(e.skip?e.skip=void 0:p(a,e,f,!1))}}function p(a,c,b,d){if(!1===d){var f=0,e=0;d=function(){++e===f&&p(a,c,b,!0)};c.attrs&&c.attrs.onbeforeremove&&(f++,c.attrs.onbeforeremove.call(c,c,d));"string"!==typeof c.tag&&c.tag.onbeforeremove&&(f++,c.tag.onbeforeremove.call(c,c,d));if(0<f)return}t(c);if(c.dom){d=c.domSize||1;if(1<d)for(var m=c.dom;--d;)a.removeChild(m.nextSibling);null!=c.dom.parentNode&&a.removeChild(c.dom);null==b||null!=c.domSize||u(c.attrs)||
|
||||
"string"!==typeof c.tag||(b.pool?b.pool.push(c):b.pool=[c])}}function t(a){a.attrs&&a.attrs.onremove&&a.attrs.onremove.call(a.state,a);"string"!==typeof a.tag&&a.tag.onremove&&a.tag.onremove.call(a.state,a);a=a.children;if(a instanceof Array)for(var c=0;c<a.length;c++){var b=a[c];null!=b&&t(b)}}function B(a,c,b,d,f){var e=a.dom;if("key"!==c&&(b!==d||"value"===c||"checked"===c||"selectedIndex"===c||"selected"===c&&a.dom===q.activeElement||"object"===typeof d)&&"undefined"!==typeof d&&"oninit"!==c&&
|
||||
"oncreate"!==c&&"onupdate"!==c&&"onremove"!==c&&"onbeforeremove"!==c&&"onbeforeupdate"!==c){var m=c.indexOf(":");if(-1<m&&"xlink"===c.substr(0,m))e.setAttributeNS("http://www.w3.org/1999/xlink",c.slice(m+1),d);else if("o"===c[0]&&"n"===c[1]&&"function"===typeof d)w(a,c,d);else if("style"===c)if(a=b,a===d&&(e.style="",a=null),null==d)e.style="";else if("string"===typeof d)e.style=d;else{"string"===typeof a&&(e.style="");for(var h in d)e.style[h]=d[h];if(null!=a&&"string"!==typeof a)for(h in a)h in
|
||||
d||(e.style[h]="")}else if(c in e&&"href"!==c&&"list"!==c&&"form"!==c&&void 0===f){if("input"!==a.tag||"value"!==c||a.dom.value!==d||a.dom!==q.activeElement)e[c]=d}else"boolean"===typeof d?d?e.setAttribute(c,""):e.removeAttribute(c):e.setAttribute("className"===c?"class":c,d)}}function u(a){return null!=a&&(a.oncreate||a.onupdate||a.onbeforeremove||a.onremove)}function w(a,c,b){var d=a.dom,e=function(a){var c=b.call(d,a);"function"===typeof C&&C.call(d,a);return c};if(c in d)d[c]=e;else{var f=c.slice(2);
|
||||
void 0===a.events&&(a.events={});null!=a.events[c]&&d.removeEventListener(f,a.events[c],!1);a.events[c]=e;d.addEventListener(f,a.events[c],!1)}}function n(a,c,b){"function"===typeof a.oninit&&a.oninit.call(c.state,c);"function"===typeof a.oncreate&&b.push(a.oncreate.bind(c.state,c))}function y(a,c,b,d){d?n(a,c,b):"function"===typeof a.onupdate&&b.push(a.onupdate.bind(c.state,c))}function z(a){if(a instanceof Array){for(var c=[],b=0;b<a.length;b++)c[b]=z(a[b]);return c}if("object"===typeof a){c={};
|
||||
for(b in a)c[b]=z(a[b]);return c}return a}var q=a.document,ha=q.createDocumentFragment(),C;return{render:function(a,b){var d=[],e=q.activeElement;null==a.vnodes&&(a.vnodes=[]);b instanceof Array||(b=[b]);f(a,a.vnodes,r.normalizeChildren(b),d,null,void 0);for(var m=0;m<d.length;m++)d[m]();a.vnodes=b;q.activeElement!==e&&e.focus()},setEventCallback:function(a){return C=a}}}(window),F=function(){var a=[];return{subscribe:a.push.bind(a),unsubscribe:function(b){b=a.indexOf(b);-1<b&&a.splice(b,1)},publish:function(){for(var b=
|
||||
0;b<a.length;b++)a[b].apply(this,arguments)}}}(),K=function(a){function b(a,e){if(e instanceof Array)for(var l=0;l<e.length;l++)b(a+"["+l+"]",e[l]);else if("[object Object]"===Object.prototype.toString.call(e))for(l in e)b(a+"["+l+"]",e[l]);else h.push(encodeURIComponent(a)+(null!=e&&""!==e?"="+encodeURIComponent(e):""))}if("[object Object]"!==Object.prototype.toString.call(a))return"";var h=[],e;for(e in a)b(e,a[e]);return h.join("&")},L=function(a){function b(a,b){if(null==b)return a;for(var e=
|
||||
a.match(/:[^\/]+/gi)||[],f=0;f<e.length;f++){var h=e[f].slice(1);null!=b[h]&&(a=a.replace(e[f],b[h]),delete b[h])}return a}function h(a,b){var e=K(b);if(""!==e){var f=0>a.indexOf("?")?"?":"&";a+=f+e}return a}function e(a){try{return""!==a?JSON.parse(a):null}catch(b){throw Error(a);}}function f(a){return a.responseText}var k=0,l;return{xhr:function(d){var m=z.stream();void 0!==d.initialValue&&m(d.initialValue);var k="boolean"===typeof d.useBody?d.useBody:"GET"!==d.method&&"TRACE"!==d.method;"function"!==
|
||||
typeof d.serialize&&(d.serialize=JSON.stringify);"function"!==typeof d.deserialize&&(d.deserialize=e);"function"!==typeof d.extract&&(d.extract=f);d.url=b(d.url,d.data);k?d.data=d.serialize(d.data):d.url=h(d.url,d.data);var p=new a.XMLHttpRequest;p.open(d.method,d.url,"boolean"===typeof d.async?d.async:!0,"string"===typeof d.user?d.user:void 0,"string"===typeof d.password?d.password:void 0);d.serialize===JSON.stringify&&k&&p.setRequestHeader("Content-Type","application/json; charset=utf-8");d.deserialize===
|
||||
e&&p.setRequestHeader("Accept","application/json, text/*");"function"===typeof d.config&&(p=d.config(p,d)||p);p.onreadystatechange=function(){if(4===p.readyState){try{var a=d.deserialize(d.extract(p,d));if(200<=p.status&&300>p.status){if("function"===typeof d.type)if(a instanceof Array)for(var b=0;b<a.length;b++)a[b]=new d.type(a[b]);else a=new d.type(a);m(a)}else{var b=Error(p.responseText),e;for(e in a)b[e]=a[e];m.error(b)}}catch(f){m.error(f)}"function"===typeof l&&l()}};k?p.send(d.data):p.send();
|
||||
return m},jsonp:function(d){var e=z.stream(),f=d.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+k++,p=a.document.createElement("script");a[f]=function(b){p.parentNode.removeChild(p);e(b);"function"===typeof l&&l();delete a[f]};p.onerror=function(){p.parentNode.removeChild(p);e.error(Error("JSONP request failed"));"function"===typeof l&&l();delete a[f]};null==d.data&&(d.data={});d.url=b(d.url,d.data);d.data[d.callbackKey||"callback"]=f;p.src=h(d.url,d.data);a.document.documentElement.appendChild(p);
|
||||
return e},setCompletionCallback:function(a){l=a}}}(window);L.setCompletionCallback(F.publish);n.version="1.0.0";n.request=L.xhr;n.jsonp=L.jsonp;var W=function(a){if(""===a||null==a)return{};"?"===a.charAt(0)&&(a=a.slice(1));a=a.split("&");for(var b={},h={},e=0;e<a.length;e++){var f=a[e].split("="),k=decodeURIComponent(f[0]),f=2===f.length?decodeURIComponent(f[1]):"",l=Number(f);""!==f&&!isNaN(l)||"NaN"===f?f=l:"true"===f?f=!0:"false"===f?f=!1:(l=new Date(f),isNaN(l.getTime())||(f=l));var l=k.split(/\]\[?|\[/),
|
||||
d=b;-1<k.indexOf("[")&&l.pop();for(var m=0;m<l.length;m++){var k=l[m],A=l[m+1],A=""==A||!isNaN(parseInt(A,10)),p=m===l.length-1;""===k&&(k=l.slice(0,m).join(),null==h[k]&&(h[k]=0),k=h[k]++);null==d[k]&&(d[k]=p?f:A?[]:{});d=d[k]}}return b},ia=function(a){function b(b){var d=a.location[b].replace(/(?:%[a-f89][a-f0-9])+/gim,decodeURIComponent);"pathname"===b&&"/"!==d[0]&&(d="/"+d);return d}function h(a,b,d){var e=a.indexOf("?"),f=a.indexOf("#"),h=-1<e?e:-1<f?f:a.length;if(-1<e){var e=W(a.slice(e+1,-1<
|
||||
f?f:a.length)),k;for(k in e)b[k]=e[k]}if(-1<f)for(k in b=W(a.slice(f+1)),b)d[k]=b[k];return a.slice(0,h)}function e(){switch(d.charAt(0)){case "#":return b("hash").slice(d.length);case "?":return b("search").slice(d.length)+b("hash");default:return b("pathname").slice(d.length)+b("search")+b("hash")}}function f(b,e,f){var l={},n={};b=h(b,l,n);if(null!=e){for(var u in e)l[u]=e[u];b=b.replace(/:([^\/]+)/g,function(a,b){delete l[b];return e[b]})}(u=K(l))&&(b+="?"+u);(n=K(n))&&(b+="#"+n);k?(f&&f.replace?
|
||||
a.history.replaceState(null,null,d+b):a.history.pushState(null,null,d+b),a.onpopstate()):a.location.href=d+b}var k="function"===typeof a.history.pushState&&"file:"!==a.location.protocol,l="function"===typeof setImmediate?setImmediate:setTimeout,d="#!";return{setPrefix:function(a){d=a},getPath:e,setPath:f,defineRoutes:function(b,f,p){function n(){var a=e(),d={},k=h(a,d,d);l(function(){for(var e in b){var h=new RegExp("^"+e.replace(/:[^\/]+?\.{3}/g,"(.*?)").replace(/:[^\/]+/g,"([^\\/]+)")+"/?$");if(h.test(k)){k.replace(h,
|
||||
function(){for(var h=e.match(/:[^\/]+/g)||[],k=[].slice.call(arguments,1,-2),l=0;l<h.length;l++)d[h[l].replace(/:|\./g,"")]=decodeURIComponent(k[l]);f(b[e],d,a,e)});return}}p(a,d)})}k?a.onpopstate=n:"#"===d.charAt(0)&&(a.onhashchange=n);n();return n},link:function(a){a.dom.setAttribute("href",d+a.attrs.href);a.dom.onclick=function(b){b.preventDefault();b.redraw=!1;f(a.attrs.href,void 0,void 0)}}}},ja=function(a){var b=0,h=null,e="function"===typeof requestAnimationFrame?requestAnimationFrame:setTimeout;
|
||||
return function(f){var k=(new Date).getTime();!0===f||0===b||16<=k-b?(b=k,a()):null===h&&(h=e(function(){h=null;a();b=(new Date).getTime()},16-(k-b)))}},X=function(a,b,h,e){var f=ja(e);null!=b&&b.setEventCallback(function(a){!1!==a.redraw&&f()});null!=h&&(a.redraw&&h.unsubscribe(a.redraw),h.subscribe(f));return a.redraw=f};n.route=function(a,b,h){var e=ia(a);a=function(a,k,l){var d=null,m=null;l=e.defineRoutes(l,function(e,h,k,l){if("function"!==typeof e.view){"function"!==typeof e.render&&(e.render=
|
||||
function(a){return a});var n=function(k){d=l;m=k;b.render(a,e.render(r(k,null,h,void 0,void 0,void 0)))};"function"!==typeof e.resolve&&(e.resolve=function(){n(m)});l!==d?e.resolve(n,h,k,l):n(m)}else b.render(a,r(e,null,h,void 0,void 0,void 0))},function(){e.setPath(k)});X(a,b,h,l)};a.link=e.link;a.prefix=e.setPrefix;a.set=e.setPath;a.get=e.getPath;return a}(window,J,F);n.mount=function(a,b){return function(h,e){X(h,a,b,function(){a.render(h,{tag:e})})()}}(J,F);n.trust=function(a){return r("<",void 0,
|
||||
void 0,a,void 0,void 0)};n.prop=z.stream;n.prop.combine=z.combine;n.prop.reject=z.reject;n.prop.HALT=z.HALT;n.withAttr=function(a,b,h){return function(e){return b.call(h||this,a in e.currentTarget?e.currentTarget[a]:e.currentTarget.getAttribute(a))}};n.render=J.render;n.redraw=F.publish;"object"===typeof module?module.exports=n:window.m=n})();
|
||||
|
|
@ -98,10 +98,13 @@ module.exports = function($window) {
|
|||
if (vnode.instance != null) {
|
||||
var element = createNode(vnode.instance, hooks, ns)
|
||||
vnode.dom = vnode.instance.dom
|
||||
vnode.domSize = vnode.instance.domSize
|
||||
vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0
|
||||
return element
|
||||
}
|
||||
else return $emptyFragment
|
||||
else {
|
||||
vnode.domSize = 0
|
||||
return $emptyFragment
|
||||
}
|
||||
}
|
||||
|
||||
//update
|
||||
|
|
@ -112,12 +115,12 @@ module.exports = function($window) {
|
|||
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) {
|
||||
else if (o != null && v != null && o.key === v.key && o.tag === v.tag) {
|
||||
oldStart++, start++
|
||||
updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling, ns)
|
||||
if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
|
||||
|
|
@ -125,7 +128,7 @@ module.exports = function($window) {
|
|||
else {
|
||||
var o = old[oldEnd]
|
||||
if (o === v) oldEnd--, start++
|
||||
else if (o != null && v != null && o.key === v.key) {
|
||||
else if (o != null && v != null && o.key === v.key && o.tag === v.tag) {
|
||||
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
|
||||
insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling))
|
||||
oldEnd--, start++
|
||||
|
|
@ -136,10 +139,10 @@ module.exports = function($window) {
|
|||
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) {
|
||||
else if (o != null && v != null && o.key === v.key && o.tag === v.tag) {
|
||||
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
|
||||
if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
|
||||
nextSibling = o.dom
|
||||
if (o.dom != null) nextSibling = o.dom
|
||||
oldEnd--, end--
|
||||
}
|
||||
else {
|
||||
|
|
@ -151,7 +154,7 @@ module.exports = function($window) {
|
|||
updateNode(parent, movable, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns)
|
||||
insertNode(parent, toFragment(movable), nextSibling)
|
||||
old[oldIndex].skip = true
|
||||
nextSibling = movable.dom
|
||||
if (movable.dom != null) nextSibling = movable.dom
|
||||
}
|
||||
else {
|
||||
var dom = createNode(v, hooks, undefined)
|
||||
|
|
@ -211,7 +214,7 @@ module.exports = function($window) {
|
|||
if (children != null) {
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var child = children[i]
|
||||
if (child != null) {
|
||||
if (child != null && child.dom != null) {
|
||||
if (vnode.dom == null) vnode.dom = child.dom
|
||||
domSize += child.domSize || 1
|
||||
}
|
||||
|
|
@ -250,7 +253,12 @@ module.exports = function($window) {
|
|||
}
|
||||
else if (old.instance != null) {
|
||||
removeNode(parent, old.instance, null, false)
|
||||
vnode.dom = vnode.domSize = undefined
|
||||
vnode.dom = undefined
|
||||
vnode.domSize = 0
|
||||
}
|
||||
else {
|
||||
vnode.dom = old.dom
|
||||
vnode.domSize = old.domSize
|
||||
}
|
||||
}
|
||||
function isRecyclable(old, vnodes) {
|
||||
|
|
@ -277,7 +285,7 @@ module.exports = function($window) {
|
|||
}
|
||||
function toFragment(vnode) {
|
||||
var count = vnode.domSize
|
||||
if (count != null) {
|
||||
if (count != null || vnode.dom == null) {
|
||||
var fragment = $doc.createDocumentFragment()
|
||||
if (count > 0) {
|
||||
var dom = vnode.dom
|
||||
|
|
@ -290,7 +298,7 @@ module.exports = function($window) {
|
|||
}
|
||||
function getNextSibling(vnodes, i, nextSibling) {
|
||||
for (; i < vnodes.length; i++) {
|
||||
if (vnodes[i] != null) return vnodes[i].dom
|
||||
if (vnodes[i] != null && vnodes[i].dom != null) return vnodes[i].dom
|
||||
}
|
||||
return nextSibling
|
||||
}
|
||||
|
|
@ -346,12 +354,14 @@ module.exports = function($window) {
|
|||
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)
|
||||
if (vnode.instance != null) onremove(vnode.instance)
|
||||
else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -479,12 +489,12 @@ module.exports = function($window) {
|
|||
function copy(data) {
|
||||
if (data instanceof Array) {
|
||||
var output = []
|
||||
for (var i = 0; i < data.length; i++) output[i] = copy(data[i])
|
||||
for (var i = 0; i < data.length; i++) output[i] = data[i]
|
||||
return output
|
||||
}
|
||||
else if (typeof data === "object") {
|
||||
var output = {}
|
||||
for (var i in data) output[i] = copy(data[i])
|
||||
for (var i in data) output[i] = data[i]
|
||||
return output
|
||||
}
|
||||
return data
|
||||
|
|
|
|||
|
|
@ -640,10 +640,11 @@ o.spec("component", function() {
|
|||
})
|
||||
})
|
||||
o.spec("state", function() {
|
||||
o("deep copies state", function() {
|
||||
o("copies state", function() {
|
||||
var called = 0
|
||||
var data = {a: 1}
|
||||
var component = {
|
||||
data: [{a: 1}],
|
||||
data: data,
|
||||
oninit: init,
|
||||
view: function() {
|
||||
return ""
|
||||
|
|
@ -653,7 +654,27 @@ o.spec("component", function() {
|
|||
render(root, [{tag: component}])
|
||||
|
||||
function init(vnode) {
|
||||
o(vnode.state.data).deepEquals([{a: 1}])
|
||||
o(vnode.state.data).deepEquals(data)
|
||||
o(vnode.state.data).equals(data)
|
||||
}
|
||||
})
|
||||
o("state copy is shallow", function() {
|
||||
var called = 0
|
||||
var body = {a: 1}
|
||||
var data = [body]
|
||||
var component = {
|
||||
data: data,
|
||||
oninit: init,
|
||||
view: function() {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
render(root, [{tag: component}])
|
||||
|
||||
function init(vnode) {
|
||||
o(vnode.state.data).equals(data)
|
||||
o(vnode.state.data[0]).equals(body)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -79,6 +79,39 @@ o.spec("onremove", function() {
|
|||
o(remove.this).equals(vnode.state)
|
||||
o(remove.args[0]).equals(vnode)
|
||||
})
|
||||
o("calls onremove on nested component", function() {
|
||||
var spy = o.spy()
|
||||
var comp = {
|
||||
view: function() {return m(outer)}
|
||||
}
|
||||
var outer = {
|
||||
view: function() {return m(inner)}
|
||||
}
|
||||
var inner = {
|
||||
onremove: spy,
|
||||
view: function() {return m("div")}
|
||||
}
|
||||
render(root, {tag: comp})
|
||||
render(root, null)
|
||||
|
||||
o(spy.callCount).equals(1)
|
||||
})
|
||||
o("calls onremove on nested component child", function() {
|
||||
var spy = o.spy()
|
||||
var comp = {
|
||||
view: function() {return m(outer)}
|
||||
}
|
||||
var outer = {
|
||||
view: function() {return m(inner, m("a", {onremove: spy}))}
|
||||
}
|
||||
var inner = {
|
||||
view: function(vnode) {return m("div", vnode.children)}
|
||||
}
|
||||
render(root, {tag: comp})
|
||||
render(root, null)
|
||||
|
||||
o(spy.callCount).equals(1)
|
||||
})
|
||||
o("does not set onremove as an event handler", function() {
|
||||
var remove = o.spy()
|
||||
var vnode = {tag: "div", attrs: {onremove: remove}, children: []}
|
||||
|
|
|
|||
|
|
@ -813,4 +813,36 @@ o.spec("updateNodes", function() {
|
|||
o(root.childNodes[0].nodeName).equals("A")
|
||||
o(root.childNodes[1].nodeName).equals("B")
|
||||
})
|
||||
o("fragment child toggles from null when followed by null component then tag", function() {
|
||||
var component = {view: function() {return null}}
|
||||
var vnodes = [{tag: "[", children: [{tag: "a"}, {tag: component}, {tag: "b"}]}]
|
||||
var temp = [{tag: "[", children: [null, {tag: component}, {tag: "b"}]}]
|
||||
var updated = [{tag: "[", children: [{tag: "a"}, {tag: component}, {tag: "b"}]}]
|
||||
|
||||
render(root, vnodes)
|
||||
render(root, temp)
|
||||
render(root, updated)
|
||||
|
||||
o(root.childNodes.length).equals(2)
|
||||
o(root.childNodes[0].nodeName).equals("A")
|
||||
o(root.childNodes[1].nodeName).equals("B")
|
||||
})
|
||||
o("fragment child toggles from null in component when followed by null component then tag", function() {
|
||||
var flag = true
|
||||
var a = {view: function() {return flag ? {tag: "a"} : null}}
|
||||
var b = {view: function() {return null}}
|
||||
var vnodes = [{tag: "[", children: [{tag: a}, {tag: b}, {tag: "s"}]}]
|
||||
var temp = [{tag: "[", children: [{tag: a}, {tag: b}, {tag: "s"}]}]
|
||||
var updated = [{tag: "[", children: [{tag: a}, {tag: b}, {tag: "s"}]}]
|
||||
|
||||
render(root, vnodes)
|
||||
flag = false
|
||||
render(root, temp)
|
||||
flag = true
|
||||
render(root, updated)
|
||||
|
||||
o(root.childNodes.length).equals(2)
|
||||
o(root.childNodes[0].nodeName).equals("A")
|
||||
o(root.childNodes[1].nodeName).equals("S")
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -7,18 +7,18 @@ function createStream() {
|
|||
return stream._state.value
|
||||
}
|
||||
initStream(stream, arguments)
|
||||
|
||||
|
||||
if (arguments.length > 0) updateStream(stream, arguments[0], undefined)
|
||||
|
||||
|
||||
return stream
|
||||
}
|
||||
function initStream(stream, args) {
|
||||
stream.constructor = createStream
|
||||
stream._state = {id: guid++, value: undefined, error: undefined, state: 0, derive: undefined, recover: undefined, deps: {}, parents: [], errorStream: undefined, endStream: undefined}
|
||||
stream.map = map, stream.ap = ap, stream.of = createStream
|
||||
stream.valueOf = valueOf, stream.toJSON = toJSON
|
||||
stream.valueOf = valueOf, stream.toJSON = toJSON, stream.toString = valueOf
|
||||
stream.run = run, stream.catch = doCatch
|
||||
|
||||
|
||||
Object.defineProperties(stream, {
|
||||
error: {get: function() {
|
||||
if (!stream._state.errorStream) {
|
||||
|
|
@ -58,7 +58,10 @@ function updateState(stream, value, error) {
|
|||
if (recovered === HALT) return
|
||||
updateValues(stream, recovered, undefined)
|
||||
}
|
||||
catch (e) {updateValues(stream, undefined, e)}
|
||||
catch (e) {
|
||||
updateValues(stream, undefined, e)
|
||||
reportUncaughtError(stream, e)
|
||||
}
|
||||
}
|
||||
else updateValues(stream, value, error)
|
||||
stream._state.changed = true
|
||||
|
|
@ -81,6 +84,7 @@ function updateDependency(stream, mustSync) {
|
|||
}
|
||||
catch (e) {
|
||||
updateState(stream, undefined, e)
|
||||
reportUncaughtError(stream, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -96,6 +100,13 @@ function finalize(stream) {
|
|||
stream._state.changed = false
|
||||
for (var id in stream._state.deps) stream._state.deps[id]._state.changed = false
|
||||
}
|
||||
function reportUncaughtError(stream, e) {
|
||||
if (Object.keys(stream._state.deps).length === 0) {
|
||||
setTimeout(function() {
|
||||
if (Object.keys(stream._state.deps).length === 0) console.error(e)
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
function run(fn) {
|
||||
var self = createStream(), stream = this
|
||||
|
|
@ -132,10 +143,10 @@ function initDependency(dep, streams, derive, recover) {
|
|||
state.derive = derive
|
||||
state.recover = recover
|
||||
state.parents = streams.filter(notEnded)
|
||||
|
||||
|
||||
registerDependency(dep, state.parents)
|
||||
updateDependency(dep, true)
|
||||
|
||||
|
||||
return dep
|
||||
}
|
||||
function registerDependency(stream, parents) {
|
||||
|
|
@ -174,4 +185,10 @@ function reject(e) {
|
|||
return stream
|
||||
}
|
||||
|
||||
module.exports = {stream: createStream, combine: combine, reject: reject, HALT: HALT}
|
||||
function merge(streams) {
|
||||
return combine(function () {
|
||||
return streams.map(function (s) {return s()})
|
||||
}, streams)
|
||||
}
|
||||
|
||||
module.exports = {stream: createStream, merge: merge, combine: combine, reject: reject, HALT: HALT}
|
||||
|
|
|
|||
|
|
@ -11,24 +11,24 @@ o.spec("stream", function() {
|
|||
var initialValue = stream()
|
||||
stream(2)
|
||||
var newValue = stream()
|
||||
|
||||
|
||||
o(initialValue).equals(1)
|
||||
o(newValue).equals(2)
|
||||
})
|
||||
o("has undefined value by default", function() {
|
||||
var stream = Stream.stream()
|
||||
|
||||
|
||||
o(stream()).equals(undefined)
|
||||
})
|
||||
o("can update to undefined", function() {
|
||||
var stream = Stream.stream(1)
|
||||
stream(undefined)
|
||||
|
||||
|
||||
o(stream()).equals(undefined)
|
||||
})
|
||||
o("can be stream of streams", function() {
|
||||
var stream = Stream.stream(Stream.stream(1))
|
||||
|
||||
|
||||
o(stream()()).equals(1)
|
||||
})
|
||||
})
|
||||
|
|
@ -36,41 +36,41 @@ o.spec("stream", function() {
|
|||
o("transforms value", function() {
|
||||
var stream = Stream.stream()
|
||||
var doubled = Stream.combine(function(s) {return s() * 2}, [stream])
|
||||
|
||||
|
||||
stream(2)
|
||||
|
||||
|
||||
o(doubled()).equals(4)
|
||||
})
|
||||
o("transforms default value", function() {
|
||||
var stream = Stream.stream(2)
|
||||
var doubled = Stream.combine(function(s) {return s() * 2}, [stream])
|
||||
|
||||
|
||||
o(doubled()).equals(4)
|
||||
})
|
||||
o("transforms multiple values", function() {
|
||||
var s1 = Stream.stream()
|
||||
var s2 = Stream.stream()
|
||||
var added = Stream.combine(function(s1, s2) {return s1() + s2()}, [s1, s2])
|
||||
|
||||
|
||||
s1(2)
|
||||
s2(3)
|
||||
|
||||
|
||||
o(added()).equals(5)
|
||||
})
|
||||
o("transforms multiple default values", function() {
|
||||
var s1 = Stream.stream(2)
|
||||
var s2 = Stream.stream(3)
|
||||
var added = Stream.combine(function(s1, s2) {return s1() + s2()}, [s1, s2])
|
||||
|
||||
|
||||
o(added()).equals(5)
|
||||
})
|
||||
o("transforms mixed default and late-bound values", function() {
|
||||
var s1 = Stream.stream(2)
|
||||
var s2 = Stream.stream()
|
||||
var added = Stream.combine(function(s1, s2) {return s1() + s2()}, [s1, s2])
|
||||
|
||||
|
||||
s2(3)
|
||||
|
||||
|
||||
o(added()).equals(5)
|
||||
})
|
||||
o("combines atomically", function() {
|
||||
|
|
@ -82,9 +82,9 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return b() + c()
|
||||
}, [b, c])
|
||||
|
||||
|
||||
a(3)
|
||||
|
||||
|
||||
o(d()).equals(15)
|
||||
o(count).equals(1)
|
||||
})
|
||||
|
|
@ -97,7 +97,7 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return b() + c()
|
||||
}, [b, c])
|
||||
|
||||
|
||||
o(d()).equals(15)
|
||||
o(count).equals(1)
|
||||
})
|
||||
|
|
@ -108,10 +108,10 @@ o.spec("stream", function() {
|
|||
var c = Stream.combine(function(a, b, changed) {
|
||||
streams = changed
|
||||
}, [a, b])
|
||||
|
||||
|
||||
a(3)
|
||||
b(5)
|
||||
|
||||
|
||||
o(streams.length).equals(1)
|
||||
o(streams[0]).equals(b)
|
||||
})
|
||||
|
|
@ -122,9 +122,9 @@ o.spec("stream", function() {
|
|||
var c = Stream.combine(function(a, b, changed) {
|
||||
streams = changed
|
||||
}, [a, b])
|
||||
|
||||
|
||||
a(7)
|
||||
|
||||
|
||||
o(streams.length).equals(1)
|
||||
o(streams[0]).equals(a)
|
||||
})
|
||||
|
|
@ -133,7 +133,7 @@ o.spec("stream", function() {
|
|||
var b = Stream.combine(function(a) {
|
||||
return undefined
|
||||
}, [a])
|
||||
|
||||
|
||||
o(b()).equals(undefined)
|
||||
})
|
||||
o("combine can return stream", function() {
|
||||
|
|
@ -141,7 +141,7 @@ o.spec("stream", function() {
|
|||
var b = Stream.combine(function(a) {
|
||||
return Stream.stream(2)
|
||||
}, [a])
|
||||
|
||||
|
||||
o(b()()).equals(2)
|
||||
})
|
||||
o("combine can return pending stream", function() {
|
||||
|
|
@ -149,7 +149,7 @@ o.spec("stream", function() {
|
|||
var b = Stream.combine(function(a) {
|
||||
return Stream.stream()
|
||||
}, [a])
|
||||
|
||||
|
||||
o(b()()).equals(undefined)
|
||||
})
|
||||
o("combine can halt", function() {
|
||||
|
|
@ -162,48 +162,73 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return 1
|
||||
})
|
||||
|
||||
|
||||
o(b()).equals(undefined)
|
||||
})
|
||||
})
|
||||
o.spec("merge", function() {
|
||||
o("transforms an array of streams to an array of values", function() {
|
||||
var all = Stream.merge([
|
||||
Stream.stream(10),
|
||||
Stream.stream("20"),
|
||||
Stream.stream({value: 30}),
|
||||
])
|
||||
|
||||
o(all()).deepEquals([10, "20", {value: 30}])
|
||||
})
|
||||
o("remains pending until all streams are active", function() {
|
||||
var straggler = Stream.stream()
|
||||
|
||||
var all = Stream.merge([
|
||||
Stream.stream(10),
|
||||
Stream.stream("20"),
|
||||
straggler,
|
||||
])
|
||||
|
||||
o(all()).equals(undefined)
|
||||
|
||||
straggler(30)
|
||||
o(all()).deepEquals([10, "20", 30])
|
||||
})
|
||||
})
|
||||
o.spec("end", function() {
|
||||
o("end stream works", function() {
|
||||
var stream = Stream.stream()
|
||||
var doubled = Stream.combine(function(stream) {return stream() * 2}, [stream])
|
||||
|
||||
|
||||
stream.end(true)
|
||||
|
||||
|
||||
stream(3)
|
||||
|
||||
|
||||
o(doubled()).equals(undefined)
|
||||
})
|
||||
o("end stream works with default value", function() {
|
||||
var stream = Stream.stream(2)
|
||||
var doubled = Stream.combine(function(stream) {return stream() * 2}, [stream])
|
||||
|
||||
|
||||
stream.end(true)
|
||||
|
||||
|
||||
stream(3)
|
||||
|
||||
|
||||
o(doubled()).equals(4)
|
||||
})
|
||||
o("cannot add downstream to ended stream", function() {
|
||||
var stream = Stream.stream(2)
|
||||
stream.end(true)
|
||||
|
||||
|
||||
var doubled = Stream.combine(function(stream) {return stream() * 2}, [stream])
|
||||
stream(3)
|
||||
|
||||
|
||||
o(doubled()).equals(undefined)
|
||||
})
|
||||
o("upstream does not affect ended stream", function() {
|
||||
var stream = Stream.stream(2)
|
||||
var doubled = Stream.combine(function(stream) {return stream() * 2}, [stream])
|
||||
|
||||
|
||||
doubled.end(true)
|
||||
|
||||
|
||||
stream(4)
|
||||
|
||||
|
||||
o(doubled()).equals(4)
|
||||
})
|
||||
})
|
||||
|
|
@ -211,16 +236,16 @@ o.spec("stream", function() {
|
|||
o("error() works", function() {
|
||||
var stream = Stream.stream()
|
||||
var errored = Stream.combine(function(stream) {throw new Error("error")}, [stream])
|
||||
|
||||
|
||||
stream(3)
|
||||
|
||||
|
||||
o(errored()).equals(undefined)
|
||||
o(errored.error().message).equals("error")
|
||||
})
|
||||
o("error() works with default value", function() {
|
||||
var stream = Stream.stream(3)
|
||||
var errored = Stream.combine(function(stream) {throw new Error("error")}, [stream])
|
||||
|
||||
|
||||
o(errored()).equals(undefined)
|
||||
o(errored.error().message).equals("error")
|
||||
})
|
||||
|
|
@ -230,9 +255,9 @@ o.spec("stream", function() {
|
|||
if (typeof stream() !== "number") throw new Error("error")
|
||||
else return stream() * 2
|
||||
}, [stream])
|
||||
|
||||
|
||||
stream(3)
|
||||
|
||||
|
||||
o(doubled()).equals(6)
|
||||
o(doubled.error()).equals(undefined)
|
||||
})
|
||||
|
|
@ -243,9 +268,9 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return 2
|
||||
})
|
||||
|
||||
|
||||
stream.error(new Error("error"))
|
||||
|
||||
|
||||
o(handled()).equals(2)
|
||||
o(handled.error()).equals(undefined)
|
||||
o(count).equals(1)
|
||||
|
|
@ -262,7 +287,7 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return value * 3
|
||||
})
|
||||
|
||||
|
||||
o(stream()).equals(undefined)
|
||||
o(stream.error().message).equals("error")
|
||||
o(count).equals(0)
|
||||
|
|
@ -279,7 +304,7 @@ o.spec("stream", function() {
|
|||
return value * 3
|
||||
})
|
||||
stream.error(new Error("error"))
|
||||
|
||||
|
||||
o(mapped()).equals(undefined)
|
||||
o(mapped.error().message).equals("error")
|
||||
o(count).equals(0)
|
||||
|
|
@ -287,13 +312,13 @@ o.spec("stream", function() {
|
|||
o("error.map works", function() {
|
||||
var stream = Stream.stream(1)
|
||||
var mappedFromError = stream.error.map(function(value) {
|
||||
return "from" + value.message
|
||||
if (value) return "from" + value.message
|
||||
})
|
||||
|
||||
|
||||
o(mappedFromError()).equals(undefined)
|
||||
|
||||
|
||||
stream.error(new Error("error"))
|
||||
|
||||
|
||||
o(mappedFromError()).equals("fromerror")
|
||||
})
|
||||
o("error from error.map propagates", function() {
|
||||
|
|
@ -304,11 +329,11 @@ o.spec("stream", function() {
|
|||
.map(function(value) {
|
||||
return "a" + value
|
||||
})
|
||||
|
||||
|
||||
o(mappedFromError()).equals(undefined)
|
||||
|
||||
|
||||
stream.error(new Error("error"))
|
||||
|
||||
|
||||
o(mappedFromError()).equals("afromerror")
|
||||
})
|
||||
o("error thrown from error.map propagates downstream", function() {
|
||||
|
|
@ -317,15 +342,15 @@ o.spec("stream", function() {
|
|||
var mappedFromError = stream.error.map(function(value) {
|
||||
throw new Error("b")
|
||||
})
|
||||
|
||||
|
||||
var downstream = mappedFromError.map(function() {
|
||||
count++
|
||||
})
|
||||
|
||||
|
||||
o(mappedFromError()).equals(undefined)
|
||||
|
||||
|
||||
stream.error(new Error("a"))
|
||||
|
||||
|
||||
o(mappedFromError()).equals(undefined)
|
||||
o(mappedFromError.error().message).equals("b")
|
||||
o(downstream()).equals(undefined)
|
||||
|
|
@ -341,7 +366,7 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return 1
|
||||
})
|
||||
|
||||
|
||||
o(stream()).equals(undefined)
|
||||
o(count).equals(0)
|
||||
})
|
||||
|
|
@ -350,15 +375,15 @@ o.spec("stream", function() {
|
|||
var error = stream.error.map(function(value) {
|
||||
return Stream.stream(1)
|
||||
})
|
||||
|
||||
|
||||
o(error()()).equals(1)
|
||||
})
|
||||
o("combined stream of two errored streams adopts error from first", function() {
|
||||
var a = Stream.stream(1)
|
||||
var b = Stream.combine(function(a) {throw new Error("error from b")}, [a])
|
||||
var c = Stream.combine(function(a) {throw new Error("error from c")}, [a])
|
||||
var d = Stream.combine(function(a, b) {return 2}, [a, b])
|
||||
|
||||
var d = Stream.combine(function(b, c) {return 2}, [b, c])
|
||||
|
||||
o(d()).equals(undefined)
|
||||
o(d.error().message).equals("error from b")
|
||||
})
|
||||
|
|
@ -366,7 +391,7 @@ o.spec("stream", function() {
|
|||
o.spec("reject", function() {
|
||||
o("reject works", function() {
|
||||
var stream = Stream.reject(new Error("error"))
|
||||
|
||||
|
||||
o(stream()).equals(undefined)
|
||||
o(stream.error().message).equals("error")
|
||||
})
|
||||
|
|
@ -381,7 +406,7 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return value * 3
|
||||
})
|
||||
|
||||
|
||||
o(stream()).equals(undefined)
|
||||
o(stream.error().message).equals("error")
|
||||
})
|
||||
|
|
@ -390,9 +415,9 @@ o.spec("stream", function() {
|
|||
var doubled = stream.map(function(value) {
|
||||
return value * 2
|
||||
})
|
||||
|
||||
|
||||
stream(1)
|
||||
|
||||
|
||||
o(doubled()).equals(2)
|
||||
o(stream.error()).equals(undefined)
|
||||
})
|
||||
|
|
@ -404,7 +429,7 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return a() + b()
|
||||
}, [a, b])
|
||||
|
||||
|
||||
o(combined()).equals(undefined)
|
||||
o(combined.error().message).equals("a")
|
||||
o(count).equals(0)
|
||||
|
|
@ -414,29 +439,29 @@ o.spec("stream", function() {
|
|||
o("works", function() {
|
||||
var stream = Stream.stream()
|
||||
var doubled = stream.run(function(value) {return value * 2})
|
||||
|
||||
|
||||
stream(3)
|
||||
|
||||
|
||||
o(doubled()).equals(6)
|
||||
})
|
||||
o("works with default value", function() {
|
||||
var stream = Stream.stream(3)
|
||||
var doubled = stream.run(function(value) {return value * 2})
|
||||
|
||||
|
||||
o(doubled()).equals(6)
|
||||
})
|
||||
o("works with undefined value", function() {
|
||||
var stream = Stream.stream()
|
||||
var mapped = stream.run(function(value) {return String(value)})
|
||||
|
||||
|
||||
stream(undefined)
|
||||
|
||||
|
||||
o(mapped()).equals("undefined")
|
||||
})
|
||||
o("works with default undefined value", function() {
|
||||
var stream = Stream.stream(undefined)
|
||||
var mapped = stream.run(function(value) {return String(value)})
|
||||
|
||||
|
||||
o(mapped()).equals("undefined")
|
||||
})
|
||||
o("works with stream that throws", function() {
|
||||
|
|
@ -447,7 +472,7 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return value
|
||||
})
|
||||
|
||||
|
||||
o(errored()).equals(undefined)
|
||||
o(errored.error().message).equals("error")
|
||||
o(mapped()).equals(undefined)
|
||||
|
|
@ -462,20 +487,20 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return value
|
||||
})
|
||||
|
||||
|
||||
o(mapped()).equals(undefined)
|
||||
o(count).equals(0)
|
||||
})
|
||||
o("works with active stream", function() {
|
||||
var stream = Stream.stream(undefined)
|
||||
var mapped = stream.run(function(value) {return Stream.stream(1)})
|
||||
|
||||
|
||||
o(mapped()).equals(1)
|
||||
})
|
||||
o("works with errored stream", function() {
|
||||
var stream = Stream.stream(undefined)
|
||||
var mapped = stream.run(function(value) {return Stream.reject(new Error("error"))})
|
||||
|
||||
|
||||
o(mapped()).equals(undefined)
|
||||
o(mapped.error().message).equals("error")
|
||||
})
|
||||
|
|
@ -486,36 +511,36 @@ o.spec("stream", function() {
|
|||
ended.end(true)
|
||||
return ended
|
||||
})
|
||||
|
||||
|
||||
stream(3)
|
||||
|
||||
|
||||
o(mapped()).equals(2)
|
||||
})
|
||||
o("works when active stream updates", function() {
|
||||
var stream = Stream.stream(undefined)
|
||||
var absorbed = Stream.stream(1)
|
||||
var mapped = stream.run(function(value) {return absorbed})
|
||||
|
||||
|
||||
absorbed(2)
|
||||
|
||||
|
||||
o(mapped()).equals(2)
|
||||
|
||||
|
||||
absorbed(3)
|
||||
|
||||
|
||||
o(mapped()).equals(3)
|
||||
})
|
||||
o("works when updating stream to errored state", function() {
|
||||
var stream = Stream.stream(undefined)
|
||||
var absorbed = Stream.stream(1)
|
||||
var mapped = stream.run(function(value) {return absorbed})
|
||||
|
||||
|
||||
absorbed.error(new Error("error"))
|
||||
|
||||
|
||||
o(mapped()).equals(undefined)
|
||||
o(mapped.error().message).equals("error")
|
||||
|
||||
|
||||
absorbed.error(new Error("another error"))
|
||||
|
||||
|
||||
o(mapped()).equals(undefined)
|
||||
o(mapped.error().message).equals("another error")
|
||||
})
|
||||
|
|
@ -523,18 +548,18 @@ o.spec("stream", function() {
|
|||
var stream = Stream.stream(undefined)
|
||||
var absorbed = Stream.stream()
|
||||
var mapped = stream.run(function(value) {return absorbed})
|
||||
|
||||
|
||||
absorbed(2)
|
||||
|
||||
|
||||
o(mapped()).equals(2)
|
||||
})
|
||||
o("works when updating pending stream to errored state", function() {
|
||||
var stream = Stream.stream(undefined)
|
||||
var absorbed = Stream.stream()
|
||||
var mapped = stream.run(function(value) {return absorbed})
|
||||
|
||||
|
||||
absorbed.error(new Error("error"))
|
||||
|
||||
|
||||
o(mapped()).equals(undefined)
|
||||
o(mapped.error().message).equals("error")
|
||||
})
|
||||
|
|
@ -542,14 +567,14 @@ o.spec("stream", function() {
|
|||
var stream = Stream.stream(undefined)
|
||||
var absorbed = Stream.stream(1)
|
||||
var mapped = stream.run(function(value) {return absorbed})
|
||||
|
||||
|
||||
absorbed.error(new Error("error"))
|
||||
|
||||
|
||||
o(mapped()).equals(undefined)
|
||||
o(mapped.error().message).equals("error")
|
||||
|
||||
|
||||
absorbed(2)
|
||||
|
||||
|
||||
o(mapped()).equals(2)
|
||||
o(mapped.error()).equals(undefined)
|
||||
})
|
||||
|
|
@ -564,7 +589,7 @@ o.spec("stream", function() {
|
|||
.map(function(value) {
|
||||
return value + "mapped"
|
||||
})
|
||||
|
||||
|
||||
o(count).equals(1)
|
||||
o(stream()).equals("noerrormapped")
|
||||
o(stream.error()).equals(undefined)
|
||||
|
|
@ -578,7 +603,7 @@ o.spec("stream", function() {
|
|||
.map(function(value) {
|
||||
return value + "mapped"
|
||||
})
|
||||
|
||||
|
||||
o(count).equals(1)
|
||||
o(stream()).equals("noerrormapped")
|
||||
o(stream.error()).equals(undefined)
|
||||
|
|
@ -593,9 +618,9 @@ o.spec("stream", function() {
|
|||
.map(function(value) {
|
||||
return value + "mapped"
|
||||
})
|
||||
|
||||
|
||||
stream("a")
|
||||
|
||||
|
||||
o(count).equals(0)
|
||||
o(handled()).equals("aamapped")
|
||||
o(handled.error()).equals(undefined)
|
||||
|
|
@ -609,7 +634,7 @@ o.spec("stream", function() {
|
|||
.map(function(value) {
|
||||
return value + "mapped"
|
||||
})
|
||||
|
||||
|
||||
o(count).equals(0)
|
||||
o(stream()).equals("aamapped")
|
||||
o(stream.error()).equals(undefined)
|
||||
|
|
@ -619,7 +644,7 @@ o.spec("stream", function() {
|
|||
throw new Error("b")
|
||||
})
|
||||
var mapped = stream.map(function(value) {return value + "ok"})
|
||||
|
||||
|
||||
o(stream()).equals(undefined)
|
||||
o(stream.error().message).equals("b")
|
||||
o(mapped()).equals(undefined)
|
||||
|
|
@ -627,7 +652,7 @@ o.spec("stream", function() {
|
|||
})
|
||||
o("catch can return undefined", function() {
|
||||
var stream = Stream.reject(new Error("b")).catch(function(e) {}).map(function(value) {return String(value)})
|
||||
|
||||
|
||||
o(stream()).equals("undefined")
|
||||
o(stream.error()).equals(undefined)
|
||||
})
|
||||
|
|
@ -641,7 +666,7 @@ o.spec("stream", function() {
|
|||
count++
|
||||
return String(value)
|
||||
})
|
||||
|
||||
|
||||
o(mapped()).equals(undefined)
|
||||
o(count).equals(0)
|
||||
})
|
||||
|
|
@ -651,7 +676,7 @@ o.spec("stream", function() {
|
|||
return stream
|
||||
})
|
||||
.map(function(value) {return String(value)})
|
||||
|
||||
|
||||
o(mapped()).equals("1")
|
||||
})
|
||||
o("catch absorbs errored stream", function() {
|
||||
|
|
@ -660,7 +685,7 @@ o.spec("stream", function() {
|
|||
return stream
|
||||
})
|
||||
.map(function(value) {return String(value)})
|
||||
|
||||
|
||||
o(mapped()).equals(undefined)
|
||||
o(mapped.error().message).equals("a")
|
||||
})
|
||||
|
|
@ -669,7 +694,7 @@ o.spec("stream", function() {
|
|||
var b = a.map(function(value) {return value + "b"}).catch(function(e) {})
|
||||
var c = a.map(function(value) {return value + "c"})
|
||||
var d = Stream.combine(function(b, c) {return b() + c()}, [b, c])
|
||||
|
||||
|
||||
o(d()).equals(undefined)
|
||||
o(d.error().message).equals("a")
|
||||
})
|
||||
|
|
@ -685,7 +710,7 @@ o.spec("stream", function() {
|
|||
.map(function(value) {
|
||||
return value + "mapped"
|
||||
})
|
||||
|
||||
|
||||
o(stream()).equals("noerrormapped")
|
||||
})
|
||||
o("catches nested wrapped rejected stream", function() {
|
||||
|
|
@ -702,7 +727,7 @@ o.spec("stream", function() {
|
|||
.map(function(value) {
|
||||
return value + "mapped"
|
||||
})
|
||||
|
||||
|
||||
o(stream()).equals("noerrormapped")
|
||||
})
|
||||
})
|
||||
|
|
@ -717,6 +742,19 @@ o.spec("stream", function() {
|
|||
o(Stream.stream([1, 2, 3]).valueOf()).deepEquals([1, 2, 3])
|
||||
o(Stream.stream().valueOf()).equals(undefined)
|
||||
})
|
||||
o("allows implicit value access in mathematical operations", function() {
|
||||
o(Stream.stream(1) + Stream.stream(1)).equals(2)
|
||||
})
|
||||
})
|
||||
o.spec("toString", function() {
|
||||
o("aliases valueOf", function() {
|
||||
var stream = Stream.stream(1)
|
||||
|
||||
o(stream.toString).equals(stream.valueOf)
|
||||
})
|
||||
o("allows implicit value access in string operations", function() {
|
||||
o(Stream.stream("a") + Stream.stream("b")).equals("ab")
|
||||
})
|
||||
})
|
||||
o.spec("toJSON", function() {
|
||||
o("works", function() {
|
||||
|
|
@ -734,35 +772,35 @@ o.spec("stream", function() {
|
|||
o("works", function() {
|
||||
var stream = Stream.stream()
|
||||
var doubled = stream.map(function(value) {return value * 2})
|
||||
|
||||
|
||||
stream(3)
|
||||
|
||||
|
||||
o(doubled()).equals(6)
|
||||
})
|
||||
o("works with default value", function() {
|
||||
var stream = Stream.stream(3)
|
||||
var doubled = stream.map(function(value) {return value * 2})
|
||||
|
||||
|
||||
o(doubled()).equals(6)
|
||||
})
|
||||
o("works with undefined value", function() {
|
||||
var stream = Stream.stream()
|
||||
var mapped = stream.map(function(value) {return String(value)})
|
||||
|
||||
|
||||
stream(undefined)
|
||||
|
||||
|
||||
o(mapped()).equals("undefined")
|
||||
})
|
||||
o("works with default undefined value", function() {
|
||||
var stream = Stream.stream(undefined)
|
||||
var mapped = stream.map(function(value) {return String(value)})
|
||||
|
||||
|
||||
o(mapped()).equals("undefined")
|
||||
})
|
||||
o("works with pending stream", function() {
|
||||
var stream = Stream.stream(undefined)
|
||||
var mapped = stream.map(function(value) {return Stream.stream()})
|
||||
|
||||
|
||||
o(mapped()()).equals(undefined)
|
||||
})
|
||||
})
|
||||
|
|
@ -771,26 +809,26 @@ o.spec("stream", function() {
|
|||
var apply = Stream.stream(function(value) {return value * 2})
|
||||
var stream = Stream.stream(3)
|
||||
var applied = apply.ap(stream)
|
||||
|
||||
|
||||
o(applied()).equals(6)
|
||||
|
||||
|
||||
apply(function(value) {return value / 3})
|
||||
|
||||
|
||||
o(applied()).equals(1)
|
||||
|
||||
|
||||
stream(9)
|
||||
|
||||
|
||||
o(applied()).equals(3)
|
||||
})
|
||||
o("works with undefined value", function() {
|
||||
var apply = Stream.stream(function(value) {return String(value)})
|
||||
var stream = Stream.stream(undefined)
|
||||
var applied = apply.ap(stream)
|
||||
|
||||
|
||||
o(applied()).equals("undefined")
|
||||
|
||||
|
||||
apply(function(value) {return String(value) + "a"})
|
||||
|
||||
|
||||
o(applied()).equals("undefineda")
|
||||
})
|
||||
})
|
||||
|
|
@ -799,18 +837,18 @@ o.spec("stream", function() {
|
|||
o("identity", function() {
|
||||
var stream = Stream.stream(3)
|
||||
var mapped = stream.map(function(value) {return value})
|
||||
|
||||
|
||||
o(stream()).equals(mapped())
|
||||
})
|
||||
o("composition", function() {
|
||||
function f(x) {return x * 2}
|
||||
function g(x) {return x * x}
|
||||
|
||||
|
||||
var stream = Stream.stream(3)
|
||||
|
||||
|
||||
var mapped = stream.map(function(value) {return f(g(value))})
|
||||
var composed = stream.map(g).map(f)
|
||||
|
||||
|
||||
o(mapped()).equals(18)
|
||||
o(mapped()).equals(composed())
|
||||
})
|
||||
|
|
@ -820,7 +858,7 @@ o.spec("stream", function() {
|
|||
var a = Stream.stream(function(value) {return value * 2})
|
||||
var u = Stream.stream(function(value) {return value * 3})
|
||||
var v = Stream.stream(5)
|
||||
|
||||
|
||||
var mapped = a.map(function(f) {
|
||||
return function(g) {
|
||||
return function(x) {
|
||||
|
|
@ -828,9 +866,9 @@ o.spec("stream", function() {
|
|||
}
|
||||
}
|
||||
}).ap(u).ap(v)
|
||||
|
||||
|
||||
var composed = a.ap(u.ap(v))
|
||||
|
||||
|
||||
o(mapped()).equals(30)
|
||||
o(mapped()).equals(composed())
|
||||
})
|
||||
|
|
@ -839,7 +877,7 @@ o.spec("stream", function() {
|
|||
o("identity", function() {
|
||||
var a = Stream.stream().of(function(value) {return value})
|
||||
var v = Stream.stream(5)
|
||||
|
||||
|
||||
o(a.ap(v)()).equals(5)
|
||||
o(a.ap(v)()).equals(v())
|
||||
})
|
||||
|
|
@ -847,7 +885,7 @@ o.spec("stream", function() {
|
|||
var a = Stream.stream(0)
|
||||
var f = function(value) {return value * 2}
|
||||
var x = 3
|
||||
|
||||
|
||||
o(a.of(f).ap(a.of(x))()).equals(6)
|
||||
o(a.of(f).ap(a.of(x))()).equals(a.of(f(x))())
|
||||
})
|
||||
|
|
@ -855,10 +893,10 @@ o.spec("stream", function() {
|
|||
var u = Stream.stream(function(value) {return value * 2})
|
||||
var a = Stream.stream()
|
||||
var y = 3
|
||||
|
||||
|
||||
o(u.ap(a.of(y))()).equals(6)
|
||||
o(u.ap(a.of(y))()).equals(a.of(function(f) {return f(y)}).ap(u)())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue