Code coverage report for 6to5/traverse/index.js

Statements: 98.89% (89 / 90)      Branches: 91.84% (45 / 49)      Functions: 100% (11 / 11)      Lines: 98.73% (78 / 79)      Ignored: none     

All files » 6to5/traverse/ » index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 1541   1 1 1   1   659667     659663 344 411   344       659319 659319   659318   659318 625183 625183 625183   585607   585607 645118 645118     644906     644889 1199700   1198697 1157 1157   1157           644889 644889   644889   18       6         644889 644889     644889 644889 644867   644867 6 6       644867       643843     643819 554833       585607 167097 226608     167076   418510         1 39 616 616 616 616 616 616 616 616 616   616 616     39 1232     39 39   39     1 20   20     20     19   18     191 3 3         18    
module.exports = traverse;
 
var Scope = require("./scope");
var t     = require("../types");
var _     = require("lodash");
 
function traverse(parent, opts, scope) {
  // falsy node
  if (!parent) return;
 
  // array of nodes
  if (_.isArray(parent)) {
    _.each(parent, function (node) {
      traverse(node, opts, scope);
    });
    return;
  }
 
  // unknown node type to traverse
  var keys = t.VISITOR_KEYS[parent.type];
  if (!keys) return;
 
  opts = opts || {};
 
  for (var i in keys) {
    var key = keys[i];
    var nodes = parent[key];
    if (!nodes) continue;
 
    var updated = false;
 
    var handle = function (obj, key) {
      var node = obj[key];
      if (!node) return;
 
      // type is blacklisted
      if (opts.blacklist && opts.blacklist.indexOf(node.type) > -1) return;
 
      // replace node
      var maybeReplace = function (result) {
        if (result === false) return;
 
        if (result != null) {
          updated = true;
          node = obj[key] = result;
 
          Iif (_.isArray(result) && _.contains(t.STATEMENT_OR_BLOCK_KEYS, key) && !t.isBlockStatement(obj)) {
            t.ensureBlock(obj, key);
          }
        }
      };
 
      var stopped = false;
      var removed = false;
 
      var context = {
        stop: function () {
          stopped = true;
        },
 
        remove: function () {
          stopped = removed = true;
        }
      };
 
      //
      var ourScope = scope;
      if (t.isScope(node)) ourScope = new Scope(node, scope);
 
      // enter
      Eif (opts.enter) {
        var result = opts.enter.call(context, node, parent, ourScope);
        maybeReplace(result);
 
        if (removed) {
          delete obj[key];
          updated = true;
        }
 
        // stop iteration
        if (stopped || result === false) return;
      }
 
      // traverse node
      traverse(node, opts, ourScope);
 
      // exit
      if (opts.exit) {
        maybeReplace(opts.exit.call(context, node, parent, ourScope));
      }
    };
 
    if (_.isArray(nodes)) {
      for (i in nodes) {
        handle(nodes, i);
      }
 
      if (updated) parent[key] = _.flatten(parent[key]);
    } else {
      handle(parent, key);
    }
  }
}
 
traverse.removeProperties = function (tree) {
  var clear = function (node) {
    delete node._declarations;
    delete node.extendedRange;
    delete node._scopeInfo;
    delete node.tokens;
    delete node.range;
    delete node.start;
    delete node.end;
    delete node.loc;
    delete node.raw;
 
    clearComments(node.trailingComments);
    clearComments(node.leadingComments);
  };
 
  var clearComments = function (comments) {
    _.each(comments, clear);
  };
 
  clear(tree);
  traverse(tree, { enter: clear });
 
  return tree;
};
 
traverse.hasType = function (tree, type, blacklistTypes) {
  blacklistTypes = [].concat(blacklistTypes || []);
 
  var has = false;
 
  // the node we're searching in is blacklisted
  if (_.contains(blacklistTypes, tree.type)) return false;
 
  // the type we're looking for is the same as the passed node
  if (tree.type === type) return true;
 
  traverse(tree, {
    blacklist: blacklistTypes,
    enter: function (node) {
      if (node.type === type) {
        has = true;
        return false;
      }
    }
  });
 
  return has;
};