simplify streams, lint docs
This commit is contained in:
parent
a7f8018df9
commit
6ce2a384ec
20 changed files with 1271 additions and 2132 deletions
115
stream/stream.js
Normal file
115
stream/stream.js
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
"use strict"
|
||||
|
||||
var guid = 0, noop = function() {}, HALT = {}
|
||||
function createStream() {
|
||||
function stream() {
|
||||
if (arguments.length > 0 && arguments[0] !== HALT) updateStream(stream, arguments[0])
|
||||
return stream._state.value
|
||||
}
|
||||
initStream(stream)
|
||||
|
||||
if (arguments.length > 0 && arguments[0] !== HALT) updateStream(stream, arguments[0])
|
||||
|
||||
return stream
|
||||
}
|
||||
function initStream(stream) {
|
||||
stream.constructor = createStream
|
||||
stream._state = {id: guid++, value: undefined, state: 0, derive: undefined, recover: undefined, deps: {}, parents: [], endStream: undefined}
|
||||
stream.map = stream["fantasy-land/map"] = map, stream["fantasy-land/ap"] = ap, stream["fantasy-land/of"] = createStream
|
||||
stream.valueOf = valueOf, stream.toJSON = toJSON, stream.toString = valueOf
|
||||
|
||||
Object.defineProperties(stream, {
|
||||
end: {get: function() {
|
||||
if (!stream._state.endStream) {
|
||||
var endStream = createStream()
|
||||
endStream.map(function(value) {
|
||||
if (value === true) unregisterStream(stream), unregisterStream(endStream)
|
||||
return value
|
||||
})
|
||||
stream._state.endStream = endStream
|
||||
}
|
||||
return stream._state.endStream
|
||||
}}
|
||||
})
|
||||
}
|
||||
function updateStream(stream, value) {
|
||||
updateState(stream, value)
|
||||
for (var id in stream._state.deps) updateDependency(stream._state.deps[id], false)
|
||||
finalize(stream)
|
||||
}
|
||||
function updateState(stream, value) {
|
||||
stream._state.value = value
|
||||
stream._state.changed = true
|
||||
if (stream._state.state !== 2) stream._state.state = 1
|
||||
}
|
||||
function updateDependency(stream, mustSync) {
|
||||
var state = stream._state, parents = state.parents
|
||||
if (parents.length > 0 && parents.filter(active).length === parents.length && (mustSync || parents.filter(changed).length > 0)) {
|
||||
var value = stream._state.derive()
|
||||
if (value === HALT) return false
|
||||
updateState(stream, value)
|
||||
}
|
||||
}
|
||||
function finalize(stream) {
|
||||
stream._state.changed = false
|
||||
for (var id in stream._state.deps) stream._state.deps[id]._state.changed = false
|
||||
}
|
||||
|
||||
function combine(fn, streams) {
|
||||
if (streams.length > streams.filter(valid).length) throw new Error("Ensure that each item passed to m.prop.combine/m.prop.merge is a stream")
|
||||
return initDependency(createStream(), streams, function() {
|
||||
return fn.apply(this, streams.concat([streams.filter(changed)]))
|
||||
})
|
||||
}
|
||||
|
||||
function initDependency(dep, streams, derive) {
|
||||
var state = dep._state
|
||||
state.derive = derive
|
||||
state.parents = streams.filter(notEnded)
|
||||
|
||||
registerDependency(dep, state.parents)
|
||||
updateDependency(dep, true)
|
||||
|
||||
return dep
|
||||
}
|
||||
function registerDependency(stream, parents) {
|
||||
for (var i = 0; i < parents.length; i++) {
|
||||
parents[i]._state.deps[stream._state.id] = stream
|
||||
registerDependency(stream, parents[i]._state.parents)
|
||||
}
|
||||
}
|
||||
function unregisterStream(stream) {
|
||||
for (var i = 0; i < stream._state.parents.length; i++) {
|
||||
var parent = stream._state.parents[i]
|
||||
delete parent._state.deps[stream._state.id]
|
||||
}
|
||||
for (var id in stream._state.deps) {
|
||||
var dependent = stream._state.deps[id]
|
||||
var index = dependent._state.parents.indexOf(stream)
|
||||
if (index > -1) dependent._state.parents.splice(index, 1)
|
||||
}
|
||||
stream._state.state = 2 //ended
|
||||
stream._state.deps = {}
|
||||
}
|
||||
|
||||
function map(fn) {return combine(function(stream) {return fn(stream())}, [this])}
|
||||
function ap(stream) {return combine(function(s1, s2) {return s1()(s2())}, [stream, this])}
|
||||
function valueOf() {return this._state.value}
|
||||
function toJSON() {return this._state.value != null && typeof this._state.value.toJSON === "function" ? this._state.value.toJSON() : this._state.value}
|
||||
|
||||
function valid(stream) {return stream._state }
|
||||
function active(stream) {return stream._state.state === 1}
|
||||
function changed(stream) {return stream._state.changed}
|
||||
function notEnded(stream) {return stream._state.state !== 2}
|
||||
|
||||
function merge(streams) {
|
||||
return combine(function() {
|
||||
return streams.map(function(s) {return s()})
|
||||
}, streams)
|
||||
}
|
||||
createStream["fantasy-land/of"] = createStream
|
||||
createStream.merge = merge
|
||||
createStream.combine = combine
|
||||
createStream.HALT = HALT
|
||||
|
||||
module.exports = createStream
|
||||
Loading…
Add table
Add a link
Reference in a new issue