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

Statements: 98.86% (87 / 88)      Branches: 93.88% (46 / 49)      Functions: 100% (9 / 9)      Lines: 98.67% (74 / 75)      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 1411   1 1 1   1   631633     631629 290 351   290       631339 631339   631338 631338     631338     631338   631338 598913 598913 598913   562432   562432 617733 617733     617521     617504 1151113   1150130 1038 1038   1038             617504 617504     617504 617504 617482     617482       616499     616475 533631       562432 160341 215642     160320   402091         1 40 561 561 561 561 561 561 561 561 561 561   561 561     40 1122     40 40   40     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, callbacks, opts) {
  // falsy node
  if (!parent) return;
 
  // array of nodes
  if (_.isArray(parent)) {
    _.each(parent, function (node) {
      traverse(node, callbacks, opts);
    });
    return;
  }
 
  // unknown node type to traverse
  var keys = t.VISITOR_KEYS[parent.type];
  if (!keys) return;
 
  opts = opts || {};
  if (_.isArray(opts)) opts = { blacklist: opts };
 
  // blacklist these node types from being traversed
  var blacklistTypes = opts.blacklist || [];
 
  // normalise callbacks
  if (_.isFunction(callbacks)) callbacks = { enter: callbacks };
 
  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 (blacklistTypes.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 opts2 = { scope: opts.scope, blacklist: opts.blacklist };
      if (t.isScope(node)) opts2.scope = new Scope(node, opts.scope);
 
      // enter
      Eif (callbacks.enter) {
        var result = callbacks.enter(node, parent, opts2.scope);
        maybeReplace(result);
 
        // stop iteration
        if (result === false) return;
      }
 
      // traverse node
      traverse(node, callbacks, opts2);
 
      // exit
      if (callbacks.exit) {
        maybeReplace(callbacks.exit(node, parent, opts2.scope));
      }
    };
 
    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._scope;
    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, 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, function (node) {
    if (node.type === type) {
      has = true;
      return false;
    }
  }, { blacklist: blacklistTypes });
 
  return has;
};