blob: cf568c07adfa34cff504c0a9cdce500797669151 [file] [log] [blame]
'use strict'
var slice = [].slice
module.exports = wrap
// Wrap `fn`.
// Can be sync or async; return a promise, receive a completion handler, return
// new values and errors.
function wrap(fn, callback) {
var invoked
return wrapped
function wrapped() {
var params = slice.call(arguments, 0)
var callback = fn.length > params.length
var result
if (callback) {
params.push(done)
}
try {
result = fn.apply(null, params)
} catch (error) {
// Well, this is quite the pickle.
// `fn` received a callback and invoked it (thus continuing the pipeline),
// but later also threw an error.
// We’re not about to restart the pipeline again, so the only thing left
// to do is to throw the thing instead.
if (callback && invoked) {
throw error
}
return done(error)
}
if (!callback) {
if (result && typeof result.then === 'function') {
result.then(then, done)
} else if (result instanceof Error) {
done(result)
} else {
then(result)
}
}
}
// Invoke `next`, only once.
function done() {
if (!invoked) {
invoked = true
callback.apply(null, arguments)
}
}
// Invoke `done` with one value.
// Tracks if an error is passed, too.
function then(value) {
done(null, value)
}
}