8 // Can be sync or async; return a promise, receive a completion handler, return
9 // new values and errors.
10 function wrap(fn, callback) {
16 var params = slice.call(arguments, 0)
17 var callback = fn.length > params.length
25 result = fn.apply(null, params)
27 // Well, this is quite the pickle.
28 // `fn` received a callback and invoked it (thus continuing the pipeline),
29 // but later also threw an error.
30 // We’re not about to restart the pipeline again, so the only thing left
31 // to do is to throw the thing instead.
32 if (callback && invoked) {
40 if (result && typeof result.then === 'function') {
41 result.then(then, done)
42 } else if (result instanceof Error) {
50 // Invoke `next`, only once.
55 callback.apply(null, arguments)
59 // Invoke `done` with one value.
60 // Tracks if an error is passed, too.
61 function then(value) {