spotlight.js
function crawl(callback, callbackArg, options) {
      options || (options = {});

      if (callback == 'custom') {
        var isCustom = true;
      } else {
        isCustom = false;
        callback = filters[callback];
      }
      var data,
          index,
          pool,
          pooled,
          queue,
          separator,
          roots = defaultRoots.slice(),
          object = options.object,
          path = options.path,
          result = [];

      // Resolve object roots.
      if (object) {
        // Resolve `undefined` path.
        if (path == null) {
          path = _.result(_.find(roots, { 'object': object }), 'path') || '<object>';
        }
        roots = [{ 'object': object, 'path': path }];
      }
      // Crawl all root objects.
      while ((data = roots.pop())) {
        index = 0;
        object = data.object;
        path = data.path;
        data = { 'object': object, 'path': path, 'pool': [object] };
        queue = [];

        // A non-recursive solution to avoid call stack limits.
        // See http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4
        // for more details.
        do {
          object = data.object;
          path = data.path;
          separator = path ? '.' : '';

          forOwn(object, function(value, key) {
            // IE may throw errors coercing properties like `window.external` or `window.navigator`.
            try {
              // Inspect objects.
              if (_.isPlainObject(value)) {
                // Clone current pool per prop on the current `object` to avoid
                // sibling properties from polluting each others object pools.
                pool = data.pool.slice();

                // Check if already pooled (prevents infinite loops when handling circular references).
                pooled = _.find(pool, function(data) {
                  return value == data.object;
                });
                // Add to the "call" queue.
                if (!pooled) {
                  pool.push({ 'object': value, 'path': path + separator + key, 'pool': pool });
                  queue.push(_.last(pool));
                }
              }
              // If filter passed, log it.
              if (
                isCustom
                  ? callbackArg.call(data, value, key, object)
                  : callback(callbackArg, key, object)
              ) {
                value = [
                  path + separator + key + ' -> (' +
                  (pooled ? '<' + pooled.path + '>' : getKindOf(value).toLowerCase()) + ')',
                  value
                ];
                result.push(value);
                log('text', value[0], value[1]);
              }
            } catch(e) {}
          });
        } while ((data = queue[index++]));
      }
      return result;
    }
function crawl(callback, callbackArg, options) {
      options || (options = {});

      if (callback == 'custom') {
        var isCustom = true;
      } else {
        isCustom = false;
        callback = filters[callback];
      }
      var data,
          index,
          pool,
          pooled,
          queue,
          separator,
          roots = defaultRoots.slice(),
          object = options.object,
          path = options.path,
          result = [];

      // Resolve object roots.
      if (object) {
        // Resolve `undefined` path.
        if (path == null) {
          path = _.result(_.find(roots, { 'object': object }), 'path') || '<object>';
        }
        roots = [{ 'object': object, 'path': path }];
      }
      // Crawl all root objects.
      while ((data = roots.pop())) {
        index = 0;
        object = data.object;
        path = data.path;
        data = { 'object': object, 'path': path, 'pool': [object] };
        queue = [];

        // A non-recursive solution to avoid call stack limits.
        // See http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4
        // for more details.
        do {
          object = data.object;
          path = data.path;
          separator = path ? '.' : '';

          forOwn(object, function(value, key) {
            // IE may throw errors coercing properties like `window.external` or `window.navigator`.
            try {
              // Inspect objects.
              if (_.isPlainObject(value)) {
                // Clone current pool per prop on the current `object` to avoid
                // sibling properties from polluting each others object pools.
                pool = data.pool.slice();

                // Check if already pooled (prevents infinite loops when handling circular references).
                pooled = _.find(pool, function(data) {
                  return value == data.object;
                });
                // Add to the "call" queue.
                if (!pooled) {
                  pool.push({ 'object': value, 'path': path + separator + key, 'pool': pool });
                  queue.push(_.last(pool));
                }
              }
              // If filter passed, log it.
              if (
                isCustom
                  ? callbackArg.call(data, value, key, object)
                  : callback(callbackArg, key, object)
              ) {
                value = [
                  path + separator + key + ' -> (' +
                  (pooled ? '<' + pooled.path + '>' : getKindOf(value).toLowerCase()) + ')',
                  value
                ];
                result.push(value);
                log('text', value[0], value[1]);
              }
            } catch(e) {}
          });
        } while ((data = queue[index++]));
      }
      return result;
    }
function crawl ( callback , callbackArg , options ) { options || ( options = { } ) ; if ( callback == 'custom' ) { var isCustom = true ; } else { isCustom = false ; callback = filters [ callback ] ; } var data , index , pool , pooled , queue , separator , roots = defaultRoots . slice ( ) , object = options . object , path = options . path , result = [ ] ; // Resolve object roots. if ( object ) { // Resolve `undefined` path. if ( path == null ) { path = _ . result ( _ . find ( roots , { 'object' : object } ) , 'path' ) || '<object>' ; } roots = [ { 'object' : object , 'path' : path } ] ; } // Crawl all root objects. while ( ( data = roots . pop ( ) ) ) { index = 0 ; object = data . object ; path = data . path ; data = { 'object' : object , 'path' : path , 'pool' : [ object ] } ; queue = [ ] ; // A non-recursive solution to avoid call stack limits. // See http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4 // for more details. do { object = data . object ; path = data . path ; separator = path ? '.' : '' ; forOwn ( object , function ( value , key ) { // IE may throw errors coercing properties like `window.external` or `window.navigator`. try { // Inspect objects. if ( _ . isPlainObject ( value ) ) { // Clone current pool per prop on the current `object` to avoid // sibling properties from polluting each others object pools. pool = data . pool . slice ( ) ; // Check if already pooled (prevents infinite loops when handling circular references). pooled = _ . find ( pool , function ( data ) { return value == data . object ; } ) ; // Add to the "call" queue. if ( ! pooled ) { pool . push ( { 'object' : value , 'path' : path + separator + key , 'pool' : pool } ) ; queue . push ( _ . last ( pool ) ) ; } } // If filter passed, log it. if ( isCustom ? callbackArg . call ( data , value , key , object ) : callback ( callbackArg , key , object ) ) { value = [ path + separator + key + ' -> (' + ( pooled ? '<' + pooled . path + '>' : getKindOf ( value ) . toLowerCase ( ) ) + ')' , value ] ; result . push ( value ) ; log ( 'text' , value [ 0 ] , value [ 1 ] ) ; } } catch ( e ) { } } ) ; } while ( ( data = queue [ index ++ ] ) ) ; } return result ; }
Crawls environment objects logging all properties that pass the callback filter.

@private
@param {Function|string} callback A function executed per object encountered.
@param {*} callbackArg An argument passed to the callback.
@param {Object} [options={}] The options object.
@returns {Array} An array of arguments passed to each `console.log()` call.
Crawls environment objects logging all properties that pass the callback filter .