text: (function(root, factory) {
      if (typeof module === "object" && module.exports) {
          // Node, or CommonJS-Like environments
          module.exports = function() {
              return factory();
          };
      } else if (typeof define === "function" && define.amd) {
          // AMD. Register as an anonymous module.
          define([], function() {
              return factory(root);
          });
      } else {
          // Browser globals
          root.gnosis = factory(root);
      }
  }(this, function(global, undefined) {
      var depthNodes = ["[object Object]", "[object Array]"];
      var exclusion = [
          "__gnosis__",
          "__defineGetter__",
          "__defineSetter__",
          "__lookupGetter__",
          "__lookupSetter__",
          "__proto__",
          "constructor",
          "isPrototypeOf",
          "hasOwnProperty",
          "propertyIsEnumerable",
          "valueOf",
          "toString",
          "toLocaleString"
      ];
      var dontwalk = [];
  
      function setValFromPath(root, path, val, setFn) {
          var idx = 1;
          var segments = path.split(".");
          var len = segments.length;
          var lastIdx = len - 1;
          var target = root;
          while (idx < len) {
              if (idx !== lastIdx) {
                  target = target[segments[idx]];
              } else {
                  if (!setFn) {
                      target[segments[idx]] = val;
                  } else {
                      setFn(target[segments[idx]], val);
                  }
              }
              idx += 1;
          }
      };
  
      function _getPrototypeOf(obj, dontwalk) {
          var proto = Object.getPrototypeOf(obj);
          return dontwalk.indexOf(proto) !== -1 ? undefined : proto;
      }
  
      function buildMeta(obj, path, options, level, accum, cb, root, instance) {
          instance = instance || obj;
          if (obj) {
              (options.nonEnumerable ? Object.getOwnPropertyNames(obj) : Object.keys(obj)).forEach(function(key) {
                  if (exclusion.indexOf(key) === -1) {
                      var thisPath = path + "." + key;
                      try {
                          var desc = Object.getOwnPropertyDescriptor(obj, key);
                          var type = Object.prototype.toString.call(obj[key]);
                          var meta;
                          if (!accum.hasOwnProperty(thisPath) || accum[thisPath].type !== type) {
                              meta = accum[thisPath] = {
                                  source: obj,
                                  name: key,
                                  descriptor: desc,
                                  path: thisPath,
                                  level: level,
                                  type: type
                              };
                              cb(instance, key, obj[key], meta, root);
                              if (depthNodes.indexOf(type) !== -1) {
                                  buildMeta(obj[key], thisPath, options, level, accum, cb, root);
                              }
                          }
                      } catch (e) {
                          console.log(e);
                      }
                  }
              });
          }
          if (obj && options.walkPrototype && (proto = _getPrototypeOf(obj, options.dontwalk || dontwalk))) {
              buildMeta(proto, path, options, level + 1, accum, cb, root, obj);
          }
      }
  
      function traverse(obj, cb, path, options, level, meta) {
          path = path || "{ROOT}";
          options = options || {};
          level = level || 0;
          meta = meta || {};
          buildMeta(obj, path, options, level, meta, cb, obj);
          if (options.trackState && !obj.__gnosis__) {
              Object.defineProperty(obj, "__gnosis__", {
                  enumerable: false,
                  writeable: true,
                  value: {
                      meta: meta
                  }
              });
              obj.__gnosis__.args = Array.prototype.slice.call(arguments, 0);
          }
          return meta;
      }
  
      function traverseDiff(obj) {
          var g = obj.__gnosis__;
          if (g && g.args) {
              return traverse(g.args[0], g.args[1], g.args[2], g.args[3], g.args[4], g.meta)
          } else {
              throw new Error("Cannot perform a diff traversal on an object that does not have __gnosis__ args and meta.");
          }
      }
  
      return {
          dontwalk: dontwalk,
          depthNodes: depthNodes,
          exclusion: exclusion,
          setValFromPath: setValFromPath,
          traverse: traverse,
          traverseDiff: traverseDiff
      };
  }));