diff options
Diffstat (limited to 'node_modules/asynckit/lib')
| -rw-r--r-- | node_modules/asynckit/lib/abort.js | 29 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/async.js | 34 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/defer.js | 26 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/iterate.js | 75 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/readable_asynckit.js | 91 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/readable_parallel.js | 25 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/readable_serial.js | 25 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/readable_serial_ordered.js | 29 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/state.js | 37 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/streamify.js | 141 | ||||
| -rw-r--r-- | node_modules/asynckit/lib/terminator.js | 29 | 
11 files changed, 541 insertions, 0 deletions
diff --git a/node_modules/asynckit/lib/abort.js b/node_modules/asynckit/lib/abort.js new file mode 100644 index 0000000..114367e --- /dev/null +++ b/node_modules/asynckit/lib/abort.js @@ -0,0 +1,29 @@ +// API +module.exports = abort; + +/** + * Aborts leftover active jobs + * + * @param {object} state - current state object + */ +function abort(state) +{ +  Object.keys(state.jobs).forEach(clean.bind(state)); + +  // reset leftover jobs +  state.jobs = {}; +} + +/** + * Cleans up leftover job by invoking abort function for the provided job id + * + * @this  state + * @param {string|number} key - job id to abort + */ +function clean(key) +{ +  if (typeof this.jobs[key] == 'function') +  { +    this.jobs[key](); +  } +} diff --git a/node_modules/asynckit/lib/async.js b/node_modules/asynckit/lib/async.js new file mode 100644 index 0000000..7f1288a --- /dev/null +++ b/node_modules/asynckit/lib/async.js @@ -0,0 +1,34 @@ +var defer = require('./defer.js'); + +// API +module.exports = async; + +/** + * Runs provided callback asynchronously + * even if callback itself is not + * + * @param   {function} callback - callback to invoke + * @returns {function} - augmented callback + */ +function async(callback) +{ +  var isAsync = false; + +  // check if async happened +  defer(function() { isAsync = true; }); + +  return function async_callback(err, result) +  { +    if (isAsync) +    { +      callback(err, result); +    } +    else +    { +      defer(function nextTick_callback() +      { +        callback(err, result); +      }); +    } +  }; +} diff --git a/node_modules/asynckit/lib/defer.js b/node_modules/asynckit/lib/defer.js new file mode 100644 index 0000000..b67110c --- /dev/null +++ b/node_modules/asynckit/lib/defer.js @@ -0,0 +1,26 @@ +module.exports = defer; + +/** + * Runs provided function on next iteration of the event loop + * + * @param {function} fn - function to run + */ +function defer(fn) +{ +  var nextTick = typeof setImmediate == 'function' +    ? setImmediate +    : ( +      typeof process == 'object' && typeof process.nextTick == 'function' +      ? process.nextTick +      : null +    ); + +  if (nextTick) +  { +    nextTick(fn); +  } +  else +  { +    setTimeout(fn, 0); +  } +} diff --git a/node_modules/asynckit/lib/iterate.js b/node_modules/asynckit/lib/iterate.js new file mode 100644 index 0000000..5d2839a --- /dev/null +++ b/node_modules/asynckit/lib/iterate.js @@ -0,0 +1,75 @@ +var async = require('./async.js') +  , abort = require('./abort.js') +  ; + +// API +module.exports = iterate; + +/** + * Iterates over each job object + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {object} state - current job status + * @param {function} callback - invoked when all elements processed + */ +function iterate(list, iterator, state, callback) +{ +  // store current index +  var key = state['keyedList'] ? state['keyedList'][state.index] : state.index; + +  state.jobs[key] = runJob(iterator, key, list[key], function(error, output) +  { +    // don't repeat yourself +    // skip secondary callbacks +    if (!(key in state.jobs)) +    { +      return; +    } + +    // clean up jobs +    delete state.jobs[key]; + +    if (error) +    { +      // don't process rest of the results +      // stop still active jobs +      // and reset the list +      abort(state); +    } +    else +    { +      state.results[key] = output; +    } + +    // return salvaged results +    callback(error, state.results); +  }); +} + +/** + * Runs iterator over provided job element + * + * @param   {function} iterator - iterator to invoke + * @param   {string|number} key - key/index of the element in the list of jobs + * @param   {mixed} item - job description + * @param   {function} callback - invoked after iterator is done with the job + * @returns {function|mixed} - job abort function or something else + */ +function runJob(iterator, key, item, callback) +{ +  var aborter; + +  // allow shortcut if iterator expects only two arguments +  if (iterator.length == 2) +  { +    aborter = iterator(item, async(callback)); +  } +  // otherwise go with full three arguments +  else +  { +    aborter = iterator(item, key, async(callback)); +  } + +  return aborter; +} diff --git a/node_modules/asynckit/lib/readable_asynckit.js b/node_modules/asynckit/lib/readable_asynckit.js new file mode 100644 index 0000000..78ad240 --- /dev/null +++ b/node_modules/asynckit/lib/readable_asynckit.js @@ -0,0 +1,91 @@ +var streamify = require('./streamify.js') +  , defer     = require('./defer.js') +  ; + +// API +module.exports = ReadableAsyncKit; + +/** + * Base constructor for all streams + * used to hold properties/methods + */ +function ReadableAsyncKit() +{ +  ReadableAsyncKit.super_.apply(this, arguments); + +  // list of active jobs +  this.jobs = {}; + +  // add stream methods +  this.destroy = destroy; +  this._start  = _start; +  this._read   = _read; +} + +/** + * Destroys readable stream, + * by aborting outstanding jobs + * + * @returns {void} + */ +function destroy() +{ +  if (this.destroyed) +  { +    return; +  } + +  this.destroyed = true; + +  if (typeof this.terminator == 'function') +  { +    this.terminator(); +  } +} + +/** + * Starts provided jobs in async manner + * + * @private + */ +function _start() +{ +  // first argument – runner function +  var runner = arguments[0] +    // take away first argument +    , args   = Array.prototype.slice.call(arguments, 1) +      // second argument - input data +    , input  = args[0] +      // last argument - result callback +    , endCb  = streamify.callback.call(this, args[args.length - 1]) +    ; + +  args[args.length - 1] = endCb; +  // third argument - iterator +  args[1] = streamify.iterator.call(this, args[1]); + +  // allow time for proper setup +  defer(function() +  { +    if (!this.destroyed) +    { +      this.terminator = runner.apply(null, args); +    } +    else +    { +      endCb(null, Array.isArray(input) ? [] : {}); +    } +  }.bind(this)); +} + + +/** + * Implement _read to comply with Readable streams + * Doesn't really make sense for flowing object mode + * + * @private + */ +function _read() +{ + +} diff --git a/node_modules/asynckit/lib/readable_parallel.js b/node_modules/asynckit/lib/readable_parallel.js new file mode 100644 index 0000000..5d2929f --- /dev/null +++ b/node_modules/asynckit/lib/readable_parallel.js @@ -0,0 +1,25 @@ +var parallel = require('../parallel.js'); + +// API +module.exports = ReadableParallel; + +/** + * Streaming wrapper to `asynckit.parallel` + * + * @param   {array|object} list - array or object (named list) to iterate over + * @param   {function} iterator - iterator to run + * @param   {function} callback - invoked when all elements processed + * @returns {stream.Readable#} + */ +function ReadableParallel(list, iterator, callback) +{ +  if (!(this instanceof ReadableParallel)) +  { +    return new ReadableParallel(list, iterator, callback); +  } + +  // turn on object mode +  ReadableParallel.super_.call(this, {objectMode: true}); + +  this._start(parallel, list, iterator, callback); +} diff --git a/node_modules/asynckit/lib/readable_serial.js b/node_modules/asynckit/lib/readable_serial.js new file mode 100644 index 0000000..7822698 --- /dev/null +++ b/node_modules/asynckit/lib/readable_serial.js @@ -0,0 +1,25 @@ +var serial = require('../serial.js'); + +// API +module.exports = ReadableSerial; + +/** + * Streaming wrapper to `asynckit.serial` + * + * @param   {array|object} list - array or object (named list) to iterate over + * @param   {function} iterator - iterator to run + * @param   {function} callback - invoked when all elements processed + * @returns {stream.Readable#} + */ +function ReadableSerial(list, iterator, callback) +{ +  if (!(this instanceof ReadableSerial)) +  { +    return new ReadableSerial(list, iterator, callback); +  } + +  // turn on object mode +  ReadableSerial.super_.call(this, {objectMode: true}); + +  this._start(serial, list, iterator, callback); +} diff --git a/node_modules/asynckit/lib/readable_serial_ordered.js b/node_modules/asynckit/lib/readable_serial_ordered.js new file mode 100644 index 0000000..3de89c4 --- /dev/null +++ b/node_modules/asynckit/lib/readable_serial_ordered.js @@ -0,0 +1,29 @@ +var serialOrdered = require('../serialOrdered.js'); + +// API +module.exports = ReadableSerialOrdered; +// expose sort helpers +module.exports.ascending  = serialOrdered.ascending; +module.exports.descending = serialOrdered.descending; + +/** + * Streaming wrapper to `asynckit.serialOrdered` + * + * @param   {array|object} list - array or object (named list) to iterate over + * @param   {function} iterator - iterator to run + * @param   {function} sortMethod - custom sort function + * @param   {function} callback - invoked when all elements processed + * @returns {stream.Readable#} + */ +function ReadableSerialOrdered(list, iterator, sortMethod, callback) +{ +  if (!(this instanceof ReadableSerialOrdered)) +  { +    return new ReadableSerialOrdered(list, iterator, sortMethod, callback); +  } + +  // turn on object mode +  ReadableSerialOrdered.super_.call(this, {objectMode: true}); + +  this._start(serialOrdered, list, iterator, sortMethod, callback); +} diff --git a/node_modules/asynckit/lib/state.js b/node_modules/asynckit/lib/state.js new file mode 100644 index 0000000..cbea7ad --- /dev/null +++ b/node_modules/asynckit/lib/state.js @@ -0,0 +1,37 @@ +// API +module.exports = state; + +/** + * Creates initial state object + * for iteration over list + * + * @param   {array|object} list - list to iterate over + * @param   {function|null} sortMethod - function to use for keys sort, + *                                     or `null` to keep them as is + * @returns {object} - initial state object + */ +function state(list, sortMethod) +{ +  var isNamedList = !Array.isArray(list) +    , initState = +    { +      index    : 0, +      keyedList: isNamedList || sortMethod ? Object.keys(list) : null, +      jobs     : {}, +      results  : isNamedList ? {} : [], +      size     : isNamedList ? Object.keys(list).length : list.length +    } +    ; + +  if (sortMethod) +  { +    // sort array keys based on it's values +    // sort object's keys just on own merit +    initState.keyedList.sort(isNamedList ? sortMethod : function(a, b) +    { +      return sortMethod(list[a], list[b]); +    }); +  } + +  return initState; +} diff --git a/node_modules/asynckit/lib/streamify.js b/node_modules/asynckit/lib/streamify.js new file mode 100644 index 0000000..f56a1c9 --- /dev/null +++ b/node_modules/asynckit/lib/streamify.js @@ -0,0 +1,141 @@ +var async = require('./async.js'); + +// API +module.exports = { +  iterator: wrapIterator, +  callback: wrapCallback +}; + +/** + * Wraps iterators with long signature + * + * @this    ReadableAsyncKit# + * @param   {function} iterator - function to wrap + * @returns {function} - wrapped function + */ +function wrapIterator(iterator) +{ +  var stream = this; + +  return function(item, key, cb) +  { +    var aborter +      , wrappedCb = async(wrapIteratorCallback.call(stream, cb, key)) +      ; + +    stream.jobs[key] = wrappedCb; + +    // it's either shortcut (item, cb) +    if (iterator.length == 2) +    { +      aborter = iterator(item, wrappedCb); +    } +    // or long format (item, key, cb) +    else +    { +      aborter = iterator(item, key, wrappedCb); +    } + +    return aborter; +  }; +} + +/** + * Wraps provided callback function + * allowing to execute snitch function before + * real callback + * + * @this    ReadableAsyncKit# + * @param   {function} callback - function to wrap + * @returns {function} - wrapped function + */ +function wrapCallback(callback) +{ +  var stream = this; + +  var wrapped = function(error, result) +  { +    return finisher.call(stream, error, result, callback); +  }; + +  return wrapped; +} + +/** + * Wraps provided iterator callback function + * makes sure snitch only called once, + * but passes secondary calls to the original callback + * + * @this    ReadableAsyncKit# + * @param   {function} callback - callback to wrap + * @param   {number|string} key - iteration key + * @returns {function} wrapped callback + */ +function wrapIteratorCallback(callback, key) +{ +  var stream = this; + +  return function(error, output) +  { +    // don't repeat yourself +    if (!(key in stream.jobs)) +    { +      callback(error, output); +      return; +    } + +    // clean up jobs +    delete stream.jobs[key]; + +    return streamer.call(stream, error, {key: key, value: output}, callback); +  }; +} + +/** + * Stream wrapper for iterator callback + * + * @this  ReadableAsyncKit# + * @param {mixed} error - error response + * @param {mixed} output - iterator output + * @param {function} callback - callback that expects iterator results + */ +function streamer(error, output, callback) +{ +  if (error && !this.error) +  { +    this.error = error; +    this.pause(); +    this.emit('error', error); +    // send back value only, as expected +    callback(error, output && output.value); +    return; +  } + +  // stream stuff +  this.push(output); + +  // back to original track +  // send back value only, as expected +  callback(error, output && output.value); +} + +/** + * Stream wrapper for finishing callback + * + * @this  ReadableAsyncKit# + * @param {mixed} error - error response + * @param {mixed} output - iterator output + * @param {function} callback - callback that expects final results + */ +function finisher(error, output, callback) +{ +  // signal end of the stream +  // only for successfully finished streams +  if (!error) +  { +    this.push(null); +  } + +  // back to original track +  callback(error, output); +} diff --git a/node_modules/asynckit/lib/terminator.js b/node_modules/asynckit/lib/terminator.js new file mode 100644 index 0000000..d6eb992 --- /dev/null +++ b/node_modules/asynckit/lib/terminator.js @@ -0,0 +1,29 @@ +var abort = require('./abort.js') +  , async = require('./async.js') +  ; + +// API +module.exports = terminator; + +/** + * Terminates jobs in the attached state context + * + * @this  AsyncKitState# + * @param {function} callback - final callback to invoke after termination + */ +function terminator(callback) +{ +  if (!Object.keys(this.jobs).length) +  { +    return; +  } + +  // fast forward iteration index +  this.index = this.size; + +  // abort jobs +  abort(this); + +  // send back results we have so far +  async(callback)(null, this.results); +}  | 
