'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) } }