docs: function(storeName, query, each, cb) {
      if (arguments.length === 3) {
        cb = each;
        each = null;
      }
      if (arguments.length === 2) {
        cb = query;
        query = null;
        each = null;
      }
  
      var result = [];
      var transaction = this.transaction(storeName, MODE.READ_ONLY, result, cb);
      var store = this.store(storeName, transaction, cb);
      var target = store;
      var request;
      try {
        // Change the target of the cursor, if defined
        if (query !== null && query.index) {
          target = store.index(query.index);
        }
        // Set a limit, if defined
        if (query !== null && query.limit) {
          var limit = query.limit;
        }
        if (query === null) {
          // Retrieve all records from object store
          request = target.openCursor();
        } else {
          request = target.openCursor(query.range, query.direction);
        }
      } catch(err) {
        if (isFunction(cb)) return cb(err);
      }
      request.onsuccess = function(event) {
        var cursor = event.target.result;
        if (cursor) {
          // Execute specified operation on each value
          if (isFunction(each)) {
            result.push(each(cursor.value));
          // Gather all results according to query
          } else {
            result.push(cursor.value);
          }
          // Limit the number of results
          if (limit) {
            limit--;
            if (limit === 0) {
              return;
            }
          }
          try {
            cursor.continue();
          } catch (err) {
            if (isFunction(cb)) return cb(err);
          }
        } else {
          // No more matching records
        }
      };
      request.onerror = function(event) {
        if (isFunction(cb)) return cb(event.target.error);
      };
    }