text: /**
   * @depend ../../sinon.js
   */
  /**
   * Sinon core utilities. For internal use only.
   *
   * @author Christian Johansen (christian@cjohansen.no)
   * @license BSD
   *
   * Copyright (c) 2010-2013 Christian Johansen
   */
  "use strict";
  
  (function (sinon) {
      var div = typeof document != "undefined" && document.createElement("div");
      var hasOwn = Object.prototype.hasOwnProperty;
  
      function isDOMNode(obj) {
          var success = false;
  
          try {
              obj.appendChild(div);
              success = div.parentNode == obj;
          } catch (e) {
              return false;
          } finally {
              try {
                  obj.removeChild(div);
              } catch (e) {
                  // Remove failed, not much we can do about that
              }
          }
  
          return success;
      }
  
      function isElement(obj) {
          return div && obj && obj.nodeType === 1 && isDOMNode(obj);
      }
  
      function isFunction(obj) {
          return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
      }
  
      function isReallyNaN(val) {
          return typeof val === "number" && isNaN(val);
      }
  
      function mirrorProperties(target, source) {
          for (var prop in source) {
              if (!hasOwn.call(target, prop)) {
                  target[prop] = source[prop];
              }
          }
      }
  
      function isRestorable(obj) {
          return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
      }
  
      // Cheap way to detect if we have ES5 support.
      var hasES5Support = "keys" in Object;
  
      function makeApi(sinon) {
          sinon.wrapMethod = function wrapMethod(object, property, method) {
              if (!object) {
                  throw new TypeError("Should wrap property of object");
              }
  
              if (typeof method != "function" && typeof method != "object") {
                  throw new TypeError("Method wrapper should be a function or a property descriptor");
              }
  
              function checkWrappedMethod(wrappedMethod) {
                  if (!isFunction(wrappedMethod)) {
                      error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
                                          property + " as function");
                  } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
                      error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
                  } else if (wrappedMethod.calledBefore) {
                      var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
                      error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
                  }
  
                  if (error) {
                      if (wrappedMethod && wrappedMethod.stackTrace) {
                          error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
                      }
                      throw error;
                  }
              }
  
              var error, wrappedMethod;
  
              // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
              // when using hasOwn.call on objects from other frames.
              var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
  
              if (hasES5Support) {
                  var methodDesc = (typeof method == "function") ? {value: method} : method,
                      wrappedMethodDesc = sinon.getPropertyDescriptor(object, property),
                      i;
  
                  if (!wrappedMethodDesc) {
                      error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
                                          property + " as function");
                  } else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
                      error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
                  }
                  if (error) {
                      if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
                          error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
                      }
                      throw error;
                  }
  
                  var types = sinon.objectKeys(methodDesc);
                  for (i = 0; i < types.length; i++) {
                      wrappedMethod = wrappedMethodDesc[types[i]];
                      checkWrappedMethod(wrappedMethod);
                  }
  
                  mirrorProperties(methodDesc, wrappedMethodDesc);
                  for (i = 0; i < types.length; i++) {
                      mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
                  }
                  Object.defineProperty(object, property, methodDesc);
              } else {
                  wrappedMethod = object[property];
                  checkWrappedMethod(wrappedMethod);
                  object[property] = method;
                  method.displayName = property;
              }
  
              method.displayName = property;
  
              // Set up a stack trace which can be used later to find what line of
              // code the original method was created on.
              method.stackTrace = (new Error("Stack Trace for original")).stack;
  
              method.restore = function () {
                  // For prototype properties try to reset by delete first.
                  // If this fails (ex: localStorage on mobile safari) then force a reset
                  // via direct assignment.
                  if (!owned) {
                      // In some cases `delete` may throw an error
                      try {
                          delete object[property];
                      } catch (e) {}
                      // For native code functions `delete` fails without throwing an error
                      // on Chrome < 43, PhantomJS, etc.
                  } else if (hasES5Support) {
                      Object.defineProperty(object, property, wrappedMethodDesc);
                  }
  
                  // Use strict equality comparison to check failures then force a reset
                  // via direct assignment.
                  if (object[property] === method) {
                      object[property] = wrappedMethod;
                  }
              };
  
              method.restore.sinon = true;
  
              if (!hasES5Support) {
                  mirrorProperties(method, wrappedMethod);
              }
  
              return method;
          };
  
          sinon.create = function create(proto) {
              var F = function () {};
              F.prototype = proto;
              return new F();
          };
  
          sinon.deepEqual = function deepEqual(a, b) {
              if (sinon.match && sinon.match.isMatcher(a)) {
                  return a.test(b);
              }
  
              if (typeof a != "object" || typeof b != "object") {
                  if (isReallyNaN(a) && isReallyNaN(b)) {
                      return true;
                  } else {
                      return a === b;
                  }
              }
  
              if (isElement(a) || isElement(b)) {
                  return a === b;
              }
  
              if (a === b) {
                  return true;
              }
  
              if ((a === null && b !== null) || (a !== null && b === null)) {
                  return false;
              }
  
              if (a instanceof RegExp && b instanceof RegExp) {
                  return (a.source === b.source) && (a.global === b.global) &&
                      (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
              }
  
              var aString = Object.prototype.toString.call(a);
              if (aString != Object.prototype.toString.call(b)) {
                  return false;
              }
  
              if (aString == "[object Date]") {
                  return a.valueOf() === b.valueOf();
              }
  
              var prop, aLength = 0, bLength = 0;
  
              if (aString == "[object Array]" && a.length !== b.length) {
                  return false;
              }
  
              for (prop in a) {
                  aLength += 1;
  
                  if (!(prop in b)) {
                      return false;
                  }
  
                  if (!deepEqual(a[prop], b[prop])) {
                      return false;
                  }
              }
  
              for (prop in b) {
                  bLength += 1;
              }
  
              return aLength == bLength;
          };
  
          sinon.functionName = function functionName(func) {
              var name = func.displayName || func.name;
  
              // Use function decomposition as a last resort to get function
              // name. Does not rely on function decomposition to work - if it
              // doesn't debugging will be slightly less informative
              // (i.e. toString will say 'spy' rather than 'myFunc').
              if (!name) {
                  var matches = func.toString().match(/function ([^\s\(]+)/);
                  name = matches && matches[1];
              }
  
              return name;
          };
  
          sinon.functionToString = function toString() {
              if (this.getCall && this.callCount) {
                  var thisValue, prop, i = this.callCount;
  
                  while (i--) {
                      thisValue = this.getCall(i).thisValue;
  
                      for (prop in thisValue) {
                          if (thisValue[prop] === this) {
                              return prop;
                          }
                      }
                  }
              }
  
              return this.displayName || "sinon fake";
          };
  
          sinon.objectKeys = function objectKeys(obj) {
              if (obj !== Object(obj)) {
                  throw new TypeError("sinon.objectKeys called on a non-object");
              }
  
              var keys = [];
              var key;
              for (key in obj) {
                  if (hasOwn.call(obj, key)) {
                      keys.push(key);
                  }
              }
  
              return keys;
          };
  
          sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) {
              var proto = object, descriptor;
              while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
                  proto = Object.getPrototypeOf(proto);
              }
              return descriptor;
          }
  
          sinon.getConfig = function (custom) {
              var config = {};
              custom = custom || {};
              var defaults = sinon.defaultConfig;
  
              for (var prop in defaults) {
                  if (defaults.hasOwnProperty(prop)) {
                      config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
                  }
              }
  
              return config;
          };
  
          sinon.defaultConfig = {
              injectIntoThis: true,
              injectInto: null,
              properties: ["spy", "stub", "mock", "clock", "server", "requests"],
              useFakeTimers: true,
              useFakeServer: true
          };
  
          sinon.timesInWords = function timesInWords(count) {
              return count == 1 && "once" ||
                  count == 2 && "twice" ||
                  count == 3 && "thrice" ||
                  (count || 0) + " times";
          };
  
          sinon.calledInOrder = function (spies) {
              for (var i = 1, l = spies.length; i < l; i++) {
                  if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
                      return false;
                  }
              }
  
              return true;
          };
  
          sinon.orderByFirstCall = function (spies) {
              return spies.sort(function (a, b) {
                  // uuid, won't ever be equal
                  var aCall = a.getCall(0);
                  var bCall = b.getCall(0);
                  var aId = aCall && aCall.callId || -1;
                  var bId = bCall && bCall.callId || -1;
  
                  return aId < bId ? -1 : 1;
              });
          };
  
          sinon.createStubInstance = function (constructor) {
              if (typeof constructor !== "function") {
                  throw new TypeError("The constructor should be a function.");
              }
              return sinon.stub(sinon.create(constructor.prototype));
          };
  
          sinon.restore = function (object) {
              if (object !== null && typeof object === "object") {
                  for (var prop in object) {
                      if (isRestorable(object[prop])) {
                          object[prop].restore();
                      }
                  }
              } else if (isRestorable(object)) {
                  object.restore();
              }
          };
  
          return sinon;
      }
  
      var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
      var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
  
      function loadDependencies(require, exports) {
          makeApi(exports);
      }
  
      if (isAMD) {
          define(loadDependencies);
      } else if (isNode) {
          loadDependencies(require, module.exports);
      } else if (!sinon) {
          return;
      } else {
          makeApi(sinon);
      }
  }(typeof sinon == "object" && sinon || null));
  