parent
9b38e41fd6
commit
b17b00e9eb
13 changed files with 7 additions and 2248 deletions
|
|
@ -3,8 +3,5 @@ coverage/
|
|||
docs/lib/
|
||||
examples/
|
||||
/mithril.js
|
||||
/mithril.mjs
|
||||
/mithril.min.js
|
||||
/mithril.min.mjs
|
||||
/stream/stream.mjs
|
||||
node_modules/
|
||||
|
|
|
|||
2
.gitattributes
vendored
2
.gitattributes
vendored
|
|
@ -1,7 +1,5 @@
|
|||
* text=auto
|
||||
/mithril.js binary
|
||||
/mithril.min.js binary
|
||||
/mithril.mjs binary
|
||||
/mithril.min.mjs binary
|
||||
/package-lock.json binary
|
||||
/yarn.lock binary
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ before_script:
|
|||
- npm run build-browser
|
||||
# Pass -save so it'll update the readme as well
|
||||
- npm run build-min -- -save
|
||||
# must run after build-min in order to generate min.mjs
|
||||
- npm run build-esm
|
||||
|
||||
# Run tests, lint, and then check for perf regressions
|
||||
script:
|
||||
|
|
@ -85,8 +83,6 @@ deploy:
|
|||
file:
|
||||
- "mithril.js"
|
||||
- "mithril.min.js"
|
||||
- "mithril.mjs"
|
||||
- "mithril.min.mjs"
|
||||
skip_cleanup: true
|
||||
draft: true
|
||||
on:
|
||||
|
|
|
|||
|
|
@ -77,6 +77,10 @@
|
|||
- request: don't modify params, call `extract`/`serialize`/`deserialize` with correct `this` value ([#2288](https://github.com/MithrilJS/mithril.js/pull/2288))
|
||||
- render: simplify component removal ([#2214](https://github.com/MithrilJS/mithril.js/pull/2214))
|
||||
- render: remove some redundancy within the component initialization code ([#2213](https://github.com/MithrilJS/mithril.js/pull/2213))
|
||||
- API: `mithril` loads `mithril/index.js`, not the bundle, so users of `mithril/hyperscript`, `mithril/render`, and similar see the same Mithril instance as those just using `mithril` itself.
|
||||
- `https://unpkg.com/mithril` is configured to receive the *minified* bundle, not the development bundle.
|
||||
- The raw bundle itself remains accessible at `mithril.js`, and is *not* browser-wrapped.
|
||||
- Note: this *will* increase overhead with bundlers like Webpack, Rollup, and Browserify.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
67
esm.js
67
esm.js
|
|
@ -1,67 +0,0 @@
|
|||
"use strict"
|
||||
|
||||
/*
|
||||
|
||||
This script will create esm compatible scripts
|
||||
from the already compiled versions of:
|
||||
|
||||
- mithril.js > mithril.mjs
|
||||
- mithril.min.js > mithril.min.mjs
|
||||
- /stream/stream.js > stream.mjs
|
||||
|
||||
*/
|
||||
|
||||
var fs = require("fs")
|
||||
|
||||
var namedExports = [
|
||||
"m",
|
||||
"trust",
|
||||
"fragment",
|
||||
"mount",
|
||||
"route",
|
||||
"render",
|
||||
"redraw",
|
||||
"request",
|
||||
"jsonp",
|
||||
"parseQueryString",
|
||||
"buildQueryString",
|
||||
"version",
|
||||
"vnode",
|
||||
"PromisePolyfill"
|
||||
]
|
||||
|
||||
var mithril = fs.readFileSync("mithril.js", "utf8")
|
||||
fs.writeFileSync("mithril.mjs",
|
||||
mithril.slice(
|
||||
mithril.indexOf("\"use strict\"") + 13,
|
||||
mithril.lastIndexOf("if (typeof module")
|
||||
)
|
||||
+ "\nexport default m"
|
||||
// The exports are declared with prefixed underscores to avoid overwriting previously
|
||||
// declared variables with the same name
|
||||
+ "\nvar " + namedExports.map(function(n) { return "_" + n + " = m." + n }).join(",")
|
||||
+ "\nexport {" + namedExports.map(function(n) { return "_" + n + " as " + n }).join(",") + "}"
|
||||
)
|
||||
|
||||
var mithrilMin = fs.readFileSync("mithril.min.js", "utf8")
|
||||
var mName = mithrilMin.match(/window\.m=([a-z])}/)[1]
|
||||
fs.writeFileSync("mithril.min.mjs",
|
||||
mithrilMin.slice(
|
||||
12,
|
||||
mithrilMin.lastIndexOf("\"undefined\"!==typeof module")
|
||||
)
|
||||
+ "export default " + mName + ";"
|
||||
// The exports are declared with prefixed underscores to avoid overwriting previously
|
||||
// declared variables with the same name
|
||||
+ "var " + namedExports.map(function(n) { return "_" + n + "=m." + n }).join(",") + ";"
|
||||
+ "export {" + namedExports.map(function(n) { return "_" + n + " as " + n }).join(",") + "};"
|
||||
)
|
||||
|
||||
var stream = fs.readFileSync("stream/stream.js", "utf8")
|
||||
fs.writeFileSync("stream/stream.mjs",
|
||||
stream.slice(
|
||||
stream.indexOf("\"use strict\"") + 13,
|
||||
stream.lastIndexOf("if (typeof module")
|
||||
)
|
||||
+ "\nexport default Stream"
|
||||
)
|
||||
File diff suppressed because one or more lines are too long
1584
mithril.mjs
1584
mithril.mjs
File diff suppressed because it is too large
Load diff
19
ospec/esm.js
19
ospec/esm.js
|
|
@ -1,19 +0,0 @@
|
|||
"use strict"
|
||||
|
||||
/*
|
||||
|
||||
This script will create an esm compatible script
|
||||
from the already compiled version of:
|
||||
|
||||
- ospec.js > ospec.mjs
|
||||
|
||||
*/
|
||||
|
||||
var fs = require("fs")
|
||||
|
||||
var ospec = fs.readFileSync("ospec.js", "utf8")
|
||||
fs.writeFileSync("ospec.mjs",
|
||||
"export default "
|
||||
+ ospec.slice(ospec.indexOf("})") + 2)
|
||||
+ "()"
|
||||
)
|
||||
386
ospec/ospec.mjs
386
ospec/ospec.mjs
|
|
@ -1,386 +0,0 @@
|
|||
export default (function init(name) {
|
||||
var spec = {}, subjects = [], results, only = [], ctx = spec, start, stack = 0, nextTickish, hasProcess = typeof process === "object", hasOwn = ({}).hasOwnProperty
|
||||
var ospecFileName = getStackName(ensureStackTrace(new Error), /[\/\\](.*?):\d+:\d+/), timeoutStackName
|
||||
var globalTimeout = noTimeoutRightNow
|
||||
var currentTestError = null
|
||||
if (name != null) spec[name] = ctx = {}
|
||||
|
||||
try {throw new Error} catch (e) {
|
||||
var ospecFileName = e.stack && (/[\/\\](.*?):\d+:\d+/).test(e.stack) ? e.stack.match(/[\/\\](.*?):\d+:\d+/)[1] : null
|
||||
}
|
||||
function o(subject, predicate) {
|
||||
if (predicate === undefined) {
|
||||
if (!isRunning()) throw new Error("Assertions should not occur outside test definitions")
|
||||
return new Assert(subject)
|
||||
} else {
|
||||
if (isRunning()) throw new Error("Test definitions and hooks shouldn't be nested. To group tests use `o.spec()`")
|
||||
subject = String(subject)
|
||||
if (subject.charCodeAt(0) === 1) throw new Error("test names starting with '\\x01' are reserved for internal use")
|
||||
ctx[unique(subject)] = new Task(predicate, ensureStackTrace(new Error))
|
||||
}
|
||||
}
|
||||
o.before = hook("\x01before")
|
||||
o.after = hook("\x01after")
|
||||
o.beforeEach = hook("\x01beforeEach")
|
||||
o.afterEach = hook("\x01afterEach")
|
||||
o.specTimeout = function (t) {
|
||||
if (isRunning()) throw new Error("o.specTimeout() can only be called before o.run()")
|
||||
if (hasOwn.call(ctx, "\x01specTimeout")) throw new Error("A default timeout has already been defined in this context")
|
||||
if (typeof t !== "number") throw new Error("o.specTimeout() expects a number as argument")
|
||||
ctx["\x01specTimeout"] = t
|
||||
}
|
||||
o.new = init
|
||||
o.spec = function(subject, predicate) {
|
||||
var parent = ctx
|
||||
ctx = ctx[unique(subject)] = {}
|
||||
predicate()
|
||||
ctx = parent
|
||||
}
|
||||
o.only = function(subject, predicate, silent) {
|
||||
if (!silent) console.log(
|
||||
highlight("/!\\ WARNING /!\\ o.only() mode") + "\n" + o.cleanStackTrace(ensureStackTrace(new Error)) + "\n",
|
||||
cStyle("red"), ""
|
||||
)
|
||||
only.push(predicate)
|
||||
o(subject, predicate)
|
||||
}
|
||||
o.spy = function(fn) {
|
||||
var spy = function() {
|
||||
spy.this = this
|
||||
spy.args = [].slice.call(arguments)
|
||||
spy.calls.push({this: this, args: spy.args})
|
||||
spy.callCount++
|
||||
|
||||
if (fn) return fn.apply(this, arguments)
|
||||
}
|
||||
if (fn)
|
||||
Object.defineProperties(spy, {
|
||||
length: {value: fn.length},
|
||||
name: {value: fn.name}
|
||||
})
|
||||
spy.args = []
|
||||
spy.calls = []
|
||||
spy.callCount = 0
|
||||
return spy
|
||||
}
|
||||
o.cleanStackTrace = function(error) {
|
||||
// For IE 10+ in quirks mode, and IE 9- in any mode, errors don't have a stack
|
||||
if (error.stack == null) return ""
|
||||
var i = 0, header = error.message ? error.name + ": " + error.message : error.name, stack
|
||||
// some environments add the name and message to the stack trace
|
||||
if (error.stack.indexOf(header) === 0) {
|
||||
stack = error.stack.slice(header.length).split(/\r?\n/)
|
||||
stack.shift() // drop the initial empty string
|
||||
} else {
|
||||
stack = error.stack.split(/\r?\n/)
|
||||
}
|
||||
if (ospecFileName == null) return stack.join("\n")
|
||||
// skip ospec-related entries on the stack
|
||||
while (stack[i] != null && stack[i].indexOf(ospecFileName) !== -1) i++
|
||||
// now we're in user code (or past the stack end)
|
||||
return stack[i]
|
||||
}
|
||||
o.timeout = function(n) {
|
||||
globalTimeout(n)
|
||||
}
|
||||
o.run = function(reporter) {
|
||||
results = []
|
||||
start = new Date
|
||||
test(spec, [], [], new Task(function() {
|
||||
setTimeout(function () {
|
||||
timeoutStackName = getStackName({stack: o.cleanStackTrace(ensureStackTrace(new Error))}, /([\w \.]+?:\d+:\d+)/)
|
||||
if (typeof reporter === "function") reporter(results)
|
||||
else {
|
||||
var errCount = o.report(results)
|
||||
if (hasProcess && errCount !== 0) process.exit(1) // eslint-disable-line no-process-exit
|
||||
}
|
||||
})
|
||||
}, null), 200 /*default timeout delay*/)
|
||||
|
||||
function test(spec, pre, post, finalize, defaultDelay) {
|
||||
if (hasOwn.call(spec, "\x01specTimeout")) defaultDelay = spec["\x01specTimeout"]
|
||||
pre = [].concat(pre, spec["\x01beforeEach"] || [])
|
||||
post = [].concat(spec["\x01afterEach"] || [], post)
|
||||
series([].concat(spec["\x01before"] || [], Object.keys(spec).reduce(function(tasks, key) {
|
||||
if (key.charCodeAt(0) !== 1 && (only.length === 0 || only.indexOf(spec[key].fn) !== -1 || !(spec[key] instanceof Task))) {
|
||||
tasks.push(new Task(function(done) {
|
||||
o.timeout(Infinity)
|
||||
subjects.push(key)
|
||||
var pop = new Task(function pop() {subjects.pop(), done()}, null)
|
||||
if (spec[key] instanceof Task) series([].concat(pre, spec[key], post, pop), defaultDelay)
|
||||
else test(spec[key], pre, post, pop, defaultDelay)
|
||||
}, null))
|
||||
}
|
||||
return tasks
|
||||
}, []), spec["\x01after"] || [], finalize), defaultDelay)
|
||||
}
|
||||
|
||||
function series(tasks, defaultDelay) {
|
||||
var cursor = 0
|
||||
next()
|
||||
|
||||
function next() {
|
||||
if (cursor === tasks.length) return
|
||||
|
||||
var task = tasks[cursor++]
|
||||
var fn = task.fn
|
||||
currentTestError = task.err
|
||||
var timeout = 0, delay = defaultDelay, s = new Date
|
||||
var current = cursor
|
||||
var arg
|
||||
|
||||
globalTimeout = setDelay
|
||||
|
||||
var isDone = false
|
||||
// public API, may only be called once from use code (or after returned Promise resolution)
|
||||
function done(err) {
|
||||
if (!isDone) isDone = true
|
||||
else throw new Error("`" + arg + "()` should only be called once")
|
||||
if (timeout === undefined) console.warn("# elapsed: " + Math.round(new Date - s) + "ms, expected under " + delay + "ms\n" + o.cleanStackTrace(task.err))
|
||||
finalizeAsync(err)
|
||||
}
|
||||
// for internal use only
|
||||
function finalizeAsync(err) {
|
||||
if (err == null) {
|
||||
if (task.err != null) succeed(new Assert)
|
||||
} else {
|
||||
if (err instanceof Error) fail(new Assert, err.message, err)
|
||||
else fail(new Assert, String(err), null)
|
||||
}
|
||||
if (timeout !== undefined) timeout = clearTimeout(timeout)
|
||||
if (current === cursor) next()
|
||||
}
|
||||
function startTimer() {
|
||||
timeout = setTimeout(function() {
|
||||
timeout = undefined
|
||||
finalizeAsync("async test timed out after " + delay + "ms")
|
||||
}, Math.min(delay, 2147483647))
|
||||
}
|
||||
function setDelay (t) {
|
||||
if (typeof t !== "number") throw new Error("timeout() and o.timeout() expect a number as argument")
|
||||
delay = t
|
||||
}
|
||||
if (fn.length > 0) {
|
||||
var body = fn.toString()
|
||||
arg = (body.match(/^(.+?)(?:\s|\/\*[\s\S]*?\*\/|\/\/.*?\n)*=>/) || body.match(/\((?:\s|\/\*[\s\S]*?\*\/|\/\/.*?\n)*(.+?)(?:\s|\/\*[\s\S]*?\*\/|\/\/.*?\n)*[,\)]/) || []).pop()
|
||||
if (body.indexOf(arg) === body.lastIndexOf(arg)) {
|
||||
var e = new Error
|
||||
e.stack = "`" + arg + "()` should be called at least once\n" + o.cleanStackTrace(task.err)
|
||||
throw e
|
||||
}
|
||||
try {
|
||||
fn(done, setDelay)
|
||||
}
|
||||
catch (e) {
|
||||
if (task.err != null) finalizeAsync(e)
|
||||
// The errors of internal tasks (which don't have an Err) are ospec bugs and must be rethrown.
|
||||
else throw e
|
||||
}
|
||||
if (timeout === 0) {
|
||||
startTimer()
|
||||
}
|
||||
} else {
|
||||
try{
|
||||
var p = fn()
|
||||
if (p && p.then) {
|
||||
startTimer()
|
||||
p.then(function() { done() }, done)
|
||||
} else {
|
||||
nextTickish(next)
|
||||
}
|
||||
} catch (e) {
|
||||
if (task.err != null) finalizeAsync(e)
|
||||
// The errors of internal tasks (which don't have an Err) are ospec bugs and must be rethrown.
|
||||
else throw e
|
||||
}
|
||||
}
|
||||
globalTimeout = noTimeoutRightNow
|
||||
}
|
||||
}
|
||||
}
|
||||
function unique(subject) {
|
||||
if (hasOwn.call(ctx, subject)) {
|
||||
console.warn("A test or a spec named `" + subject + "` was already defined")
|
||||
while (hasOwn.call(ctx, subject)) subject += "*"
|
||||
}
|
||||
return subject
|
||||
}
|
||||
function hook(name) {
|
||||
return function(predicate) {
|
||||
if (ctx[name]) throw new Error("This hook should be defined outside of a loop or inside a nested test group:\n" + predicate)
|
||||
ctx[name] = new Task(predicate, ensureStackTrace(new Error))
|
||||
}
|
||||
}
|
||||
|
||||
define("equals", "should equal", function(a, b) {return a === b})
|
||||
define("notEquals", "should not equal", function(a, b) {return a !== b})
|
||||
define("deepEquals", "should deep equal", deepEqual)
|
||||
define("notDeepEquals", "should not deep equal", function(a, b) {return !deepEqual(a, b)})
|
||||
define("throws", "should throw a", throws)
|
||||
define("notThrows", "should not throw a", function(a, b) {return !throws(a, b)})
|
||||
|
||||
function isArguments(a) {
|
||||
if ("callee" in a) {
|
||||
for (var i in a) if (i === "callee") return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
function deepEqual(a, b) {
|
||||
if (a === b) return true
|
||||
if (a === null ^ b === null || a === undefined ^ b === undefined) return false // eslint-disable-line no-bitwise
|
||||
if (typeof a === "object" && typeof b === "object") {
|
||||
var aIsArgs = isArguments(a), bIsArgs = isArguments(b)
|
||||
if (a.constructor === Object && b.constructor === Object && !aIsArgs && !bIsArgs) {
|
||||
for (var i in a) {
|
||||
if ((!(i in b)) || !deepEqual(a[i], b[i])) return false
|
||||
}
|
||||
for (var i in b) {
|
||||
if (!(i in a)) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a.length === b.length && (a instanceof Array && b instanceof Array || aIsArgs && bIsArgs)) {
|
||||
var aKeys = Object.getOwnPropertyNames(a), bKeys = Object.getOwnPropertyNames(b)
|
||||
if (aKeys.length !== bKeys.length) return false
|
||||
for (var i = 0; i < aKeys.length; i++) {
|
||||
if (!hasOwn.call(b, aKeys[i]) || !deepEqual(a[aKeys[i]], b[aKeys[i]])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime()
|
||||
if (typeof Buffer === "function" && a instanceof Buffer && b instanceof Buffer) {
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a.valueOf() === b.valueOf()) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
function throws(a, b){
|
||||
try{
|
||||
a()
|
||||
}catch(e){
|
||||
if(typeof b === "string"){
|
||||
return (e.message === b)
|
||||
}else{
|
||||
return (e instanceof b)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function isRunning() {return results != null}
|
||||
function Assert(value) {
|
||||
this.value = value
|
||||
this.i = results.length
|
||||
results.push({pass: null, context: "", message: "Incomplete assertion in the test definition starting at...", error: currentTestError, testError: currentTestError})
|
||||
}
|
||||
function Task(fn, err) {
|
||||
this.fn = fn
|
||||
this.err = err
|
||||
}
|
||||
function define(name, verb, compare) {
|
||||
Assert.prototype[name] = function assert(value) {
|
||||
var self = this
|
||||
var message = serialize(self.value) + "\n " + verb + "\n" + serialize(value)
|
||||
if (compare(self.value, value)){
|
||||
succeed(self, message)
|
||||
return function(message) {
|
||||
if (!self.pass) self.message = message + "\n\n" + self.message
|
||||
}
|
||||
}else fail(self, message)
|
||||
}
|
||||
}
|
||||
function succeed(assertion, message) {
|
||||
results[assertion.i].pass = true
|
||||
results[assertion.i].context = subjects.join(" > ")
|
||||
results[assertion.i].message = message
|
||||
}
|
||||
function fail(assertion, message, error) {
|
||||
results[assertion.i].pass = false
|
||||
results[assertion.i].context = subjects.join(" > ")
|
||||
results[assertion.i].message = message
|
||||
results[assertion.i].error = error != null ? error : ensureStackTrace(new Error)
|
||||
}
|
||||
function serialize(value) {
|
||||
if (hasProcess) return require("util").inspect(value) // eslint-disable-line global-require
|
||||
if (value === null || (typeof value === "object" && !(value instanceof Array)) || typeof value === "number") return String(value)
|
||||
else if (typeof value === "function") return value.name || "<anonymous function>"
|
||||
try {return JSON.stringify(value)} catch (e) {return String(value)}
|
||||
}
|
||||
function noTimeoutRightNow() {
|
||||
throw new Error("o.timeout must be called snchronously from within a test definition or a hook")
|
||||
}
|
||||
var colorCodes = {
|
||||
red: "31m",
|
||||
red2: "31;1m",
|
||||
green: "32;1m"
|
||||
}
|
||||
function highlight(message, color) {
|
||||
var code = colorCodes[color] || colorCodes.red;
|
||||
return hasProcess ? (process.stdout.isTTY ? "\x1b[" + code + message + "\x1b[0m" : message) : "%c" + message + "%c "
|
||||
}
|
||||
function cStyle(color, bold) {
|
||||
return hasProcess||!color ? "" : "color:"+color+(bold ? ";font-weight:bold" : "")
|
||||
}
|
||||
function ensureStackTrace(error) {
|
||||
// mandatory to get a stack in IE 10 and 11 (and maybe other envs?)
|
||||
if (error.stack === undefined) try { throw error } catch(e) {return e}
|
||||
else return error
|
||||
}
|
||||
function getStackName(e, exp) {
|
||||
return e.stack && exp.test(e.stack) ? e.stack.match(exp)[1] : null
|
||||
}
|
||||
|
||||
o.report = function (results) {
|
||||
var errCount = 0
|
||||
for (var i = 0, r; r = results[i]; i++) {
|
||||
if (r.pass == null) {
|
||||
r.testError.stack = r.message + "\n" + o.cleanStackTrace(r.testError)
|
||||
r.testError.message = r.message
|
||||
throw r.testError
|
||||
}
|
||||
if (!r.pass) {
|
||||
var stackTrace = o.cleanStackTrace(r.error)
|
||||
var couldHaveABetterStackTrace = !stackTrace || timeoutStackName != null && stackTrace.indexOf(timeoutStackName) !== -1
|
||||
if (couldHaveABetterStackTrace) stackTrace = r.testError != null ? o.cleanStackTrace(r.testError) : r.error.stack || ""
|
||||
console.error(
|
||||
(hasProcess ? "\n" : "") +
|
||||
highlight(r.context + ":", "red2") + "\n" +
|
||||
highlight(r.message, "red") +
|
||||
(stackTrace ? "\n" + stackTrace + "\n" : ""),
|
||||
|
||||
cStyle("black", true), "", // reset to default
|
||||
cStyle("red"), cStyle("black")
|
||||
)
|
||||
errCount++
|
||||
}
|
||||
}
|
||||
var pl = results.length === 1 ? "" : "s"
|
||||
var resultSummary = (errCount === 0) ?
|
||||
highlight((pl ? "All " : "The ") + results.length + " assertion" + pl + " passed", "green"):
|
||||
highlight(errCount + " out of " + results.length + " assertion" + pl + " failed", "red2")
|
||||
var runningTime = " in " + Math.round(Date.now() - start) + "ms"
|
||||
|
||||
console.log(
|
||||
(hasProcess ? "––––––\n" : "") +
|
||||
(name ? name + ": " : "") + resultSummary + runningTime,
|
||||
cStyle((errCount === 0 ? "green" : "red"), true), ""
|
||||
)
|
||||
return errCount
|
||||
}
|
||||
|
||||
if (hasProcess) {
|
||||
nextTickish = process.nextTick
|
||||
} else {
|
||||
nextTickish = function fakeFastNextTick(next) {
|
||||
if (stack++ < 5000) next()
|
||||
else setTimeout(next, stack = 0)
|
||||
}
|
||||
}
|
||||
|
||||
return o
|
||||
})
|
||||
()
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
"version": "3.1.0",
|
||||
"description": "Noiseless testing framework",
|
||||
"main": "ospec.js",
|
||||
"module": "ospec.mjs",
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
|
|
@ -13,9 +12,6 @@
|
|||
"bin": {
|
||||
"ospec": "./bin/ospec"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublishOnly": "node esm.js"
|
||||
},
|
||||
"repository": "MithrilJS/mithril.js",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
|
|
|
|||
|
|
@ -4,15 +4,13 @@
|
|||
"description": "A framework for building brilliant applications",
|
||||
"author": "Leo Horie",
|
||||
"license": "MIT",
|
||||
"main": "mithril.js",
|
||||
"module": "mithril.mjs",
|
||||
"unpkg": "mithril.min.js",
|
||||
"repository": "MithrilJS/mithril.js",
|
||||
"scripts": {
|
||||
"dev": "node bundler/cli browser.js -output mithril.js -watch",
|
||||
"build": "npm run build-browser & npm run build-min && npm run build-esm",
|
||||
"build": "npm run build-browser & npm run build-min",
|
||||
"build-browser": "node bundler/cli browser.js -output mithril.js",
|
||||
"build-min": "node bundler/cli browser.js -output mithril.min.js -minify",
|
||||
"build-esm": "node esm.js",
|
||||
"precommit": "lint-staged",
|
||||
"lintdocs": "node docs/lint",
|
||||
"gendocs": "node docs/generate",
|
||||
|
|
@ -24,7 +22,7 @@
|
|||
"cover": "istanbul cover --print both ospec/bin/ospec",
|
||||
"release": "npm version -m 'v%s'",
|
||||
"preversion": "npm run test",
|
||||
"version": "npm run build && git add mithril.js mithril.min.js mithril.mjs mithril.min.mjs stream/stream.mjs",
|
||||
"version": "npm run build && git add mithril.js mithril.min.js",
|
||||
"postversion": "git push --follow-tags"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"version": "2.0.0",
|
||||
"description": "Streaming data, mithril-style",
|
||||
"main": "stream.js",
|
||||
"module": "stream.mjs",
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,172 +0,0 @@
|
|||
/* eslint-enable */
|
||||
Stream.SKIP = {}
|
||||
Stream.lift = lift
|
||||
Stream.scan = scan
|
||||
Stream.merge = merge
|
||||
Stream.combine = combine
|
||||
Stream.scanMerge = scanMerge
|
||||
Stream["fantasy-land/of"] = Stream
|
||||
|
||||
var warnedHalt = false
|
||||
Object.defineProperty(Stream, "HALT", {
|
||||
get: function() {
|
||||
warnedHalt || console.log("HALT is deprecated and has been renamed to SKIP");
|
||||
warnedHalt = true
|
||||
return Stream.SKIP
|
||||
}
|
||||
})
|
||||
|
||||
function Stream(value) {
|
||||
var dependentStreams = []
|
||||
var dependentFns = []
|
||||
|
||||
function stream(v) {
|
||||
if (arguments.length && v !== Stream.SKIP) {
|
||||
value = v
|
||||
if (open(stream)) {
|
||||
stream.changing()
|
||||
stream.state = "active"
|
||||
dependentStreams.forEach(function(s, i) { s(dependentFns[i](value)) })
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
stream.constructor = Stream
|
||||
stream.state = arguments.length && value !== Stream.SKIP ? "active" : "pending"
|
||||
stream.parents = []
|
||||
|
||||
stream.changing = function() {
|
||||
open(stream) && (stream.state = "changing")
|
||||
dependentStreams.forEach(function(s) {
|
||||
s.changing()
|
||||
})
|
||||
}
|
||||
|
||||
stream.map = function(fn, ignoreInitial) {
|
||||
var target = stream.state === "active" && ignoreInitial !== Stream.SKIP
|
||||
? Stream(fn(value))
|
||||
: Stream()
|
||||
target.parents.push(stream)
|
||||
|
||||
dependentStreams.push(target)
|
||||
dependentFns.push(fn)
|
||||
return target
|
||||
}
|
||||
|
||||
var end
|
||||
function createEnd() {
|
||||
end = Stream()
|
||||
end.map(function(value) {
|
||||
if (value === true) {
|
||||
stream.parents.forEach(function (p) {p.unregisterChild(stream)})
|
||||
stream.state = "ended"
|
||||
stream.parents.length = dependentStreams.length = dependentFns.length = 0
|
||||
}
|
||||
return value
|
||||
})
|
||||
return end
|
||||
}
|
||||
|
||||
stream.toJSON = function() { return value != null && typeof value.toJSON === "function" ? value.toJSON() : value }
|
||||
|
||||
stream["fantasy-land/map"] = stream.map
|
||||
stream["fantasy-land/ap"] = function(x) { return combine(function(s1, s2) { return s1()(s2()) }, [x, stream]) }
|
||||
|
||||
stream.unregisterChild = function(child) {
|
||||
var childIndex = dependentStreams.indexOf(child)
|
||||
if (childIndex !== -1) {
|
||||
dependentStreams.splice(childIndex, 1)
|
||||
dependentFns.splice(childIndex, 1)
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(stream, "end", {
|
||||
get: function() { return end || createEnd() }
|
||||
})
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
function combine(fn, streams) {
|
||||
var ready = streams.every(function(s) {
|
||||
if (s.constructor !== Stream)
|
||||
throw new Error("Ensure that each item passed to stream.combine/stream.merge/lift is a stream")
|
||||
return s.state === "active"
|
||||
})
|
||||
var stream = ready
|
||||
? Stream(fn.apply(null, streams.concat([streams])))
|
||||
: Stream()
|
||||
|
||||
var changed = []
|
||||
|
||||
var mappers = streams.map(function(s) {
|
||||
return s.map(function(value) {
|
||||
changed.push(s)
|
||||
if (ready || streams.every(function(s) { return s.state !== "pending" })) {
|
||||
ready = true
|
||||
stream(fn.apply(null, streams.concat([changed])))
|
||||
changed = []
|
||||
}
|
||||
return value
|
||||
}, Stream.SKIP)
|
||||
})
|
||||
|
||||
var endStream = stream.end.map(function(value) {
|
||||
if (value === true) {
|
||||
mappers.forEach(function(mapper) { mapper.end(true) })
|
||||
endStream.end(true)
|
||||
}
|
||||
return undefined
|
||||
})
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
function merge(streams) {
|
||||
return combine(function() { return streams.map(function(s) { return s() }) }, streams)
|
||||
}
|
||||
|
||||
function scan(fn, acc, origin) {
|
||||
var stream = origin.map(function(v) {
|
||||
var next = fn(acc, v)
|
||||
if (next !== Stream.SKIP) acc = next
|
||||
return next
|
||||
})
|
||||
stream(acc)
|
||||
return stream
|
||||
}
|
||||
|
||||
function scanMerge(tuples, seed) {
|
||||
var streams = tuples.map(function(tuple) { return tuple[0] })
|
||||
|
||||
var stream = combine(function() {
|
||||
var changed = arguments[arguments.length - 1]
|
||||
streams.forEach(function(stream, i) {
|
||||
if (changed.indexOf(stream) > -1)
|
||||
seed = tuples[i][1](seed, stream())
|
||||
})
|
||||
|
||||
return seed
|
||||
}, streams)
|
||||
|
||||
stream(seed)
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
function lift() {
|
||||
var fn = arguments[0]
|
||||
var streams = Array.prototype.slice.call(arguments, 1)
|
||||
return merge(streams).map(function(streams) {
|
||||
return fn.apply(undefined, streams)
|
||||
})
|
||||
}
|
||||
|
||||
function open(s) {
|
||||
return s.state === "pending" || s.state === "active" || s.state === "changing"
|
||||
}
|
||||
|
||||
|
||||
export default Stream
|
||||
Loading…
Add table
Add a link
Reference in a new issue