jasmine-where.js
function where(fn) {

    if (typeof fn != 'function') {
      throw new Error('where(param) expected param should be a function');
    }
    
    var fnBody = fn.toString().replace(/\s*function[^\(]*[\(][^\)]*[\)][^\{]*{/,'')
                              .replace(/[\}]$/, '');
    var values = parseFnBody(fnBody);
    var labels = values[0];
    
    /**
     * {labels} array is toString'd so the values became param symbols in the new Function.
     * {fnBody} is what's left of the original function, mainly the expectation.
     */
    var fnTest = new Function(labels.toString(), fnBody);
    var failedCount = 0;
    var trace = '\n [' + labels.join(PAD) + '] : ';
    
    /*
     * 1.x.x - jasmine.getEnv().currentSpec
     * 2.x.x - .currentSpec is no longer exposed (leaking state) so use a shim for it with 
     *          the v2 .result property
     */

    var currentSpec = jasmine.getEnv().currentSpec || { result : {} };
    var result = /* jasmine 2.x.x. */ currentSpec.result || 
                 /* jasmine 1.x.x. */ currentSpec.results_;

    var item, message;
        
    for (var i = 1; i < values.length; ++i) {
    
      message = MESSAGE;
      
      fnTest.apply(currentSpec, values[i]);

      // TODO - extract method, perhaps...
      
      // collect any failed expectations 
      if (result.failedExpectations && result.failedExpectations.length) {
      
        /*
         * jasmine 2.x.x.
         */
         
        if (failedCount < result.failedExpectations.length) {
          failedCount += 1;
          item = result.failedExpectations[failedCount - 1];
          message = item.message;
          item.message = trace + '\n [' + values[i].join(PAD) + '] (' + message + ')';
        }
        
      } else if (result.items_) {
      
        /*
         * jasmine 1.x.x.
         */
        
        item = result.items_[result.items_.length - 1];
        
        if (item && !item.passed_) {
          failedCount += 1;
          message = item.message;
          item.message = trace + '\n [' + values[i].join(PAD) + '] (' + message + ')';
        }
      }
      
    }    
    
    // use these in further assertions 
    return values;
  }
function where(fn) {

    if (typeof fn != 'function') {
      throw new Error('where(param) expected param should be a function');
    }
    
    var fnBody = fn.toString().replace(/\s*function[^\(]*[\(][^\)]*[\)][^\{]*{/,'')
                              .replace(/[\}]$/, '');
    var values = parseFnBody(fnBody);
    var labels = values[0];
    
    /**
     * {labels} array is toString'd so the values became param symbols in the new Function.
     * {fnBody} is what's left of the original function, mainly the expectation.
     */
    var fnTest = new Function(labels.toString(), fnBody);
    var failedCount = 0;
    var trace = '\n [' + labels.join(PAD) + '] : ';
    
    /*
     * 1.x.x - jasmine.getEnv().currentSpec
     * 2.x.x - .currentSpec is no longer exposed (leaking state) so use a shim for it with 
     *          the v2 .result property
     */

    var currentSpec = jasmine.getEnv().currentSpec || { result : {} };
    var result = /* jasmine 2.x.x. */ currentSpec.result || 
                 /* jasmine 1.x.x. */ currentSpec.results_;

    var item, message;
        
    for (var i = 1; i < values.length; ++i) {
    
      message = MESSAGE;
      
      fnTest.apply(currentSpec, values[i]);

      // TODO - extract method, perhaps...
      
      // collect any failed expectations 
      if (result.failedExpectations && result.failedExpectations.length) {
      
        /*
         * jasmine 2.x.x.
         */
         
        if (failedCount < result.failedExpectations.length) {
          failedCount += 1;
          item = result.failedExpectations[failedCount - 1];
          message = item.message;
          item.message = trace + '\n [' + values[i].join(PAD) + '] (' + message + ')';
        }
        
      } else if (result.items_) {
      
        /*
         * jasmine 1.x.x.
         */
        
        item = result.items_[result.items_.length - 1];
        
        if (item && !item.passed_) {
          failedCount += 1;
          message = item.message;
          item.message = trace + '\n [' + values[i].join(PAD) + '] (' + message + ')';
        }
      }
      
    }    
    
    // use these in further assertions 
    return values;
  }
////////////////////////////////////////////////////////////////////////////////////// main api method defined on the jazz environment in imitation of the jasmine lib src.  where() accepts only a function with a commented data-table and an expectation.  parses the function into data array, passing each array row into a new Function() that contains the original function body's expectation statements.  entire data-table with pass/fail messages is passed to the jasmine report only if an expectation fails.  returns the data table values array for further use in other expectations.  //////////////////////////////////////////////////////////////////////////////////////