define("gallery/expect/0.2.0/expect-debug", [], function(require, exports, module) {
    (function(global, module) {
        if ("undefined" == typeof module) {
            var module = {
                exports: {}
            }, exports = module.exports;
        }
        /**
   * Exports.
   */
        module.exports = expect;
        expect.Assertion = Assertion;
        /**
   * Exports version.
   */
        expect.version = "0.1.2";
        /**
   * Possible assertion flags.
   */
        var flags = {
            not: [ "to", "be", "have", "include", "only" ],
            to: [ "be", "have", "include", "only", "not" ],
            only: [ "have" ],
            have: [ "own" ],
            be: [ "an" ]
        };
        function expect(obj) {
            return new Assertion(obj);
        }
        /**
   * Constructor
   *
   * @api private
   */
        function Assertion(obj, flag, parent) {
            this.obj = obj;
            this.flags = {};
            if (undefined != parent) {
                this.flags[flag] = true;
                for (var i in parent.flags) {
                    if (parent.flags.hasOwnProperty(i)) {
                        this.flags[i] = true;
                    }
                }
            }
            var $flags = flag ? flags[flag] : keys(flags), self = this;
            if ($flags) {
                for (var i = 0, l = $flags.length; i < l; i++) {
                    // avoid recursion
                    if (this.flags[$flags[i]]) continue;
                    var name = $flags[i], assertion = new Assertion(this.obj, name, this);
                    if ("function" == typeof Assertion.prototype[name]) {
                        // clone the function, make sure we dont touch the prot reference
                        var old = this[name];
                        this[name] = function() {
                            return old.apply(self, arguments);
                        };
                        for (var fn in Assertion.prototype) {
                            if (Assertion.prototype.hasOwnProperty(fn) && fn != name) {
                                this[name][fn] = bind(assertion[fn], assertion);
                            }
                        }
                    } else {
                        this[name] = assertion;
                    }
                }
            }
        }
        /**
   * Performs an assertion
   *
   * @api private
   */
        Assertion.prototype.assert = function(truth, msg, error) {
            var msg = this.flags.not ? error : msg, ok = this.flags.not ? !truth : truth;
            if (!ok) {
                throw new Error(msg.call(this));
            }
            this.and = new Assertion(this.obj);
        };
        /**
   * Check if the value is truthy
   *
   * @api public
   */
        Assertion.prototype.ok = function() {
            this.assert(!!this.obj, function() {
                return "expected " + i(this.obj) + " to be truthy";
            }, function() {
                return "expected " + i(this.obj) + " to be falsy";
            });
        };
        /**
   * Assert that the function throws.
   *
   * @param {Function|RegExp} callback, or regexp to match error string against
   * @api public
   */
        Assertion.prototype.throwError = Assertion.prototype.throwException = function(fn) {
            expect(this.obj).to.be.a("function");
            var thrown = false, not = this.flags.not;
            try {
                this.obj();
            } catch (e) {
                if ("function" == typeof fn) {
                    fn(e);
                } else if ("object" == typeof fn) {
                    var subject = "string" == typeof e ? e : e.message;
                    if (not) {
                        expect(subject).to.not.match(fn);
                    } else {
                        expect(subject).to.match(fn);
                    }
                }
                thrown = true;
            }
            if ("object" == typeof fn && not) {
                // in the presence of a matcher, ensure the `not` only applies to
                // the matching.
                this.flags.not = false;
            }
            var name = this.obj.name || "fn";
            this.assert(thrown, function() {
                return "expected " + name + " to throw an exception";
            }, function() {
                return "expected " + name + " not to throw an exception";
            });
        };
        /**
   * Checks if the array is empty.
   *
   * @api public
   */
        Assertion.prototype.empty = function() {
            var expectation;
            if ("object" == typeof this.obj && null !== this.obj && !isArray(this.obj)) {
                if ("number" == typeof this.obj.length) {
                    expectation = !this.obj.length;
                } else {
                    expectation = !keys(this.obj).length;
                }
            } else {
                if ("string" != typeof this.obj) {
                    expect(this.obj).to.be.an("object");
                }
                expect(this.obj).to.have.property("length");
                expectation = !this.obj.length;
            }
            this.assert(expectation, function() {
                return "expected " + i(this.obj) + " to be empty";
            }, function() {
                return "expected " + i(this.obj) + " to not be empty";
            });
            return this;
        };
        /**
   * Checks if the obj exactly equals another.
   *
   * @api public
   */
        Assertion.prototype.be = Assertion.prototype.equal = function(obj) {
            this.assert(obj === this.obj, function() {
                return "expected " + i(this.obj) + " to equal " + i(obj);
            }, function() {
                return "expected " + i(this.obj) + " to not equal " + i(obj);
            });
            return this;
        };
        /**
   * Checks if the obj sortof equals another.
   *
   * @api public
   */
        Assertion.prototype.eql = function(obj) {
            this.assert(expect.eql(obj, this.obj), function() {
                return "expected " + i(this.obj) + " to sort of equal " + i(obj);
            }, function() {
                return "expected " + i(this.obj) + " to sort of not equal " + i(obj);
            });
            return this;
        };
        /**
   * Assert within start to finish (inclusive).
   *
   * @param {Number} start
   * @param {Number} finish
   * @api public
   */
        Assertion.prototype.within = function(start, finish) {
            var range = start + ".." + finish;
            this.assert(this.obj >= start && this.obj <= finish, function() {
                return "expected " + i(this.obj) + " to be within " + range;
            }, function() {
                return "expected " + i(this.obj) + " to not be within " + range;
            });
            return this;
        };
        /**
   * Assert typeof / instance of
   *
   * @api public
   */
        Assertion.prototype.a = Assertion.prototype.an = function(type) {
            if ("string" == typeof type) {
                // proper english in error msg
                var n = /^[aeiou]/.test(type) ? "n" : "";
                // typeof with support for 'array'
                this.assert("array" == type ? isArray(this.obj) : "object" == type ? "object" == typeof this.obj && null !== this.obj : type == typeof this.obj, function() {
                    return "expected " + i(this.obj) + " to be a" + n + " " + type;
                }, function() {
                    return "expected " + i(this.obj) + " not to be a" + n + " " + type;
                });
            } else {
                // instanceof
                var name = type.name || "supplied constructor";
                this.assert(this.obj instanceof type, function() {
                    return "expected " + i(this.obj) + " to be an instance of " + name;
                }, function() {
                    return "expected " + i(this.obj) + " not to be an instance of " + name;
                });
            }
            return this;
        };
        /**
   * Assert numeric value above _n_.
   *
   * @param {Number} n
   * @api public
   */
        Assertion.prototype.greaterThan = Assertion.prototype.above = function(n) {
            this.assert(this.obj > n, function() {
                return "expected " + i(this.obj) + " to be above " + n;
            }, function() {
                return "expected " + i(this.obj) + " to be below " + n;
            });
            return this;
        };
        /**
   * Assert numeric value below _n_.
   *
   * @param {Number} n
   * @api public
   */
        Assertion.prototype.lessThan = Assertion.prototype.below = function(n) {
            this.assert(this.obj < n, function() {
                return "expected " + i(this.obj) + " to be below " + n;
            }, function() {
                return "expected " + i(this.obj) + " to be above " + n;
            });
            return this;
        };
        /**
   * Assert string value matches _regexp_.
   *
   * @param {RegExp} regexp
   * @api public
   */
        Assertion.prototype.match = function(regexp) {
            this.assert(regexp.exec(this.obj), function() {
                return "expected " + i(this.obj) + " to match " + regexp;
            }, function() {
                return "expected " + i(this.obj) + " not to match " + regexp;
            });
            return this;
        };
        /**
   * Assert property "length" exists and has value of _n_.
   *
   * @param {Number} n
   * @api public
   */
        Assertion.prototype.length = function(n) {
            expect(this.obj).to.have.property("length");
            var len = this.obj.length;
            this.assert(n == len, function() {
                return "expected " + i(this.obj) + " to have a length of " + n + " but got " + len;
            }, function() {
                return "expected " + i(this.obj) + " to not have a length of " + len;
            });
            return this;
        };
        /**
   * Assert property _name_ exists, with optional _val_.
   *
   * @param {String} name
   * @param {Mixed} val
   * @api public
   */
        Assertion.prototype.property = function(name, val) {
            if (this.flags.own) {
                this.assert(Object.prototype.hasOwnProperty.call(this.obj, name), function() {
                    return "expected " + i(this.obj) + " to have own property " + i(name);
                }, function() {
                    return "expected " + i(this.obj) + " to not have own property " + i(name);
                });
                return this;
            }
            if (this.flags.not && undefined !== val) {
                if (undefined === this.obj[name]) {
                    throw new Error(i(this.obj) + " has no property " + i(name));
                }
            } else {
                var hasProp;
                try {
                    hasProp = name in this.obj;
                } catch (e) {
                    hasProp = undefined !== this.obj[name];
                }
                this.assert(hasProp, function() {
                    return "expected " + i(this.obj) + " to have a property " + i(name);
                }, function() {
                    return "expected " + i(this.obj) + " to not have a property " + i(name);
                });
            }
            if (undefined !== val) {
                this.assert(val === this.obj[name], function() {
                    return "expected " + i(this.obj) + " to have a property " + i(name) + " of " + i(val) + ", but got " + i(this.obj[name]);
                }, function() {
                    return "expected " + i(this.obj) + " to not have a property " + i(name) + " of " + i(val);
                });
            }
            this.obj = this.obj[name];
            return this;
        };
        /**
   * Assert that the array contains _obj_ or string contains _obj_.
   *
   * @param {Mixed} obj|string
   * @api public
   */
        Assertion.prototype.string = Assertion.prototype.contain = function(obj) {
            if ("string" == typeof this.obj) {
                this.assert(~this.obj.indexOf(obj), function() {
                    return "expected " + i(this.obj) + " to contain " + i(obj);
                }, function() {
                    return "expected " + i(this.obj) + " to not contain " + i(obj);
                });
            } else {
                this.assert(~indexOf(this.obj, obj), function() {
                    return "expected " + i(this.obj) + " to contain " + i(obj);
                }, function() {
                    return "expected " + i(this.obj) + " to not contain " + i(obj);
                });
            }
            return this;
        };
        /**
   * Assert exact keys or inclusion of keys by using
   * the `.own` modifier.
   *
   * @param {Array|String ...} keys
   * @api public
   */
        Assertion.prototype.key = Assertion.prototype.keys = function($keys) {
            var str, ok = true;
            $keys = isArray($keys) ? $keys : Array.prototype.slice.call(arguments);
            if (!$keys.length) throw new Error("keys required");
            var actual = keys(this.obj), len = $keys.length;
            // Inclusion
            ok = every($keys, function(key) {
                return ~indexOf(actual, key);
            });
            // Strict
            if (!this.flags.not && this.flags.only) {
                ok = ok && $keys.length == actual.length;
            }
            // Key string
            if (len > 1) {
                $keys = map($keys, function(key) {
                    return i(key);
                });
                var last = $keys.pop();
                str = $keys.join(", ") + ", and " + last;
            } else {
                str = i($keys[0]);
            }
            // Form
            str = (len > 1 ? "keys " : "key ") + str;
            // Have / include
            str = (!this.flags.only ? "include " : "only have ") + str;
            // Assertion
            this.assert(ok, function() {
                return "expected " + i(this.obj) + " to " + str;
            }, function() {
                return "expected " + i(this.obj) + " to not " + str;
            });
            return this;
        };
        /**
   * Assert a failure.
   *
   * @param {String ...} custom message
   * @api public
   */
        Assertion.prototype.fail = function(msg) {
            msg = msg || "explicit failure";
            this.assert(false, msg, msg);
            return this;
        };
        /**
   * Function bind implementation.
   */
        function bind(fn, scope) {
            return function() {
                return fn.apply(scope, arguments);
            };
        }
        /**
   * Array every compatibility
   *
   * @see bit.ly/5Fq1N2
   * @api public
   */
        function every(arr, fn, thisObj) {
            var scope = thisObj || global;
            for (var i = 0, j = arr.length; i < j; ++i) {
                if (!fn.call(scope, arr[i], i, arr)) {
                    return false;
                }
            }
            return true;
        }
        /**
   * Array indexOf compatibility.
   *
   * @see bit.ly/a5Dxa2
   * @api public
   */
        function indexOf(arr, o, i) {
            if (Array.prototype.indexOf) {
                return Array.prototype.indexOf.call(arr, o, i);
            }
            if (arr.length === undefined) {
                return -1;
            }
            for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0; i < j && arr[i] !== o; i++) ;
            return j <= i ? -1 : i;
        }
        // https://gist.github.com/1044128/
        var getOuterHTML = function(element) {
            if ("outerHTML" in element) return element.outerHTML;
            var ns = "http://www.w3.org/1999/xhtml";
            var container = document.createElementNS(ns, "_");
            var elemProto = (window.HTMLElement || window.Element).prototype;
            var xmlSerializer = new XMLSerializer();
            var html;
            if (document.xmlVersion) {
                return xmlSerializer.serializeToString(element);
            } else {
                container.appendChild(element.cloneNode(false));
                html = container.innerHTML.replace("><", ">" + element.innerHTML + "<");
                container.innerHTML = "";
                return html;
            }
        };
        // Returns true if object is a DOM element.
        var isDOMElement = function(object) {
            if (typeof HTMLElement === "object") {
                return object instanceof HTMLElement;
            } else {
                return object && typeof object === "object" && object.nodeType === 1 && typeof object.nodeName === "string";
            }
        };
        /**
   * Inspects an object.
   *
   * @see taken from node.js `util` module (copyright Joyent, MIT license)
   * @api private
   */
        function i(obj, showHidden, depth) {
            var seen = [];
            function stylize(str) {
                return str;
            }
            function format(value, recurseTimes) {
                // Provide a hook for user-specified inspect functions.
                // Check that value is an object with an inspect function on it
                if (value && typeof value.inspect === "function" && // Filter out the util module, it's inspect function is special
                value !== exports && // Also filter out any prototype objects using the circular check.
                !(value.constructor && value.constructor.prototype === value)) {
                    return value.inspect(recurseTimes);
                }
                // Primitive types cannot have properties
                switch (typeof value) {
                  case "undefined":
                    return stylize("undefined", "undefined");

                  case "string":
                    var simple = "'" + json.stringify(value).replace(/^"|"$/g, "").replace(/'/g, "\\'").replace(/\\"/g, '"') + "'";
                    return stylize(simple, "string");

                  case "number":
                    return stylize("" + value, "number");

                  case "boolean":
                    return stylize("" + value, "boolean");
                }
                // For some reason typeof null is "object", so special case here.
                if (value === null) {
                    return stylize("null", "null");
                }
                if (isDOMElement(value)) {
                    return getOuterHTML(value);
                }
                // Look up the keys of the object.
                var visible_keys = keys(value);
                var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys;
                // Functions without properties can be shortcutted.
                if (typeof value === "function" && $keys.length === 0) {
                    if (isRegExp(value)) {
                        return stylize("" + value, "regexp");
                    } else {
                        var name = value.name ? ": " + value.name : "";
                        return stylize("[Function" + name + "]", "special");
                    }
                }
                // Dates without properties can be shortcutted
                if (isDate(value) && $keys.length === 0) {
                    return stylize(value.toUTCString(), "date");
                }
                var base, type, braces;
                // Determine the object type
                if (isArray(value)) {
                    type = "Array";
                    braces = [ "[", "]" ];
                } else {
                    type = "Object";
                    braces = [ "{", "}" ];
                }
                // Make functions say that they are functions
                if (typeof value === "function") {
                    var n = value.name ? ": " + value.name : "";
                    base = isRegExp(value) ? " " + value : " [Function" + n + "]";
                } else {
                    base = "";
                }
                // Make dates with properties first say the date
                if (isDate(value)) {
                    base = " " + value.toUTCString();
                }
                if ($keys.length === 0) {
                    return braces[0] + base + braces[1];
                }
                if (recurseTimes < 0) {
                    if (isRegExp(value)) {
                        return stylize("" + value, "regexp");
                    } else {
                        return stylize("[Object]", "special");
                    }
                }
                seen.push(value);
                var output = map($keys, function(key) {
                    var name, str;
                    if (value.__lookupGetter__) {
                        if (value.__lookupGetter__(key)) {
                            if (value.__lookupSetter__(key)) {
                                str = stylize("[Getter/Setter]", "special");
                            } else {
                                str = stylize("[Getter]", "special");
                            }
                        } else {
                            if (value.__lookupSetter__(key)) {
                                str = stylize("[Setter]", "special");
                            }
                        }
                    }
                    if (indexOf(visible_keys, key) < 0) {
                        name = "[" + key + "]";
                    }
                    if (!str) {
                        if (indexOf(seen, value[key]) < 0) {
                            if (recurseTimes === null) {
                                str = format(value[key]);
                            } else {
                                str = format(value[key], recurseTimes - 1);
                            }
                            if (str.indexOf("\n") > -1) {
                                if (isArray(value)) {
                                    str = map(str.split("\n"), function(line) {
                                        return "  " + line;
                                    }).join("\n").substr(2);
                                } else {
                                    str = "\n" + map(str.split("\n"), function(line) {
                                        return "   " + line;
                                    }).join("\n");
                                }
                            }
                        } else {
                            str = stylize("[Circular]", "special");
                        }
                    }
                    if (typeof name === "undefined") {
                        if (type === "Array" && key.match(/^\d+$/)) {
                            return str;
                        }
                        name = json.stringify("" + key);
                        if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
                            name = name.substr(1, name.length - 2);
                            name = stylize(name, "name");
                        } else {
                            name = name.replace(/'/g, "\\'").replace(/\\"/g, '"').replace(/(^"|"$)/g, "'");
                            name = stylize(name, "string");
                        }
                    }
                    return name + ": " + str;
                });
                seen.pop();
                var numLinesEst = 0;
                var length = reduce(output, function(prev, cur) {
                    numLinesEst++;
                    if (indexOf(cur, "\n") >= 0) numLinesEst++;
                    return prev + cur.length + 1;
                }, 0);
                if (length > 50) {
                    output = braces[0] + (base === "" ? "" : base + "\n ") + " " + output.join(",\n  ") + " " + braces[1];
                } else {
                    output = braces[0] + base + " " + output.join(", ") + " " + braces[1];
                }
                return output;
            }
            return format(obj, typeof depth === "undefined" ? 2 : depth);
        }
        function isArray(ar) {
            return Object.prototype.toString.call(ar) == "[object Array]";
        }
        function isRegExp(re) {
            var s;
            try {
                s = "" + re;
            } catch (e) {
                return false;
            }
            return re instanceof RegExp || // easy case
            // duck-type for context-switching evalcx case
            typeof re === "function" && re.constructor.name === "RegExp" && re.compile && re.test && re.exec && s.match(/^\/.*\/[gim]{0,3}$/);
        }
        function isDate(d) {
            if (d instanceof Date) return true;
            return false;
        }
        function keys(obj) {
            if (Object.keys) {
                return Object.keys(obj);
            }
            var keys = [];
            for (var i in obj) {
                if (Object.prototype.hasOwnProperty.call(obj, i)) {
                    keys.push(i);
                }
            }
            return keys;
        }
        function map(arr, mapper, that) {
            if (Array.prototype.map) {
                return Array.prototype.map.call(arr, mapper, that);
            }
            var other = new Array(arr.length);
            for (var i = 0, n = arr.length; i < n; i++) if (i in arr) other[i] = mapper.call(that, arr[i], i, arr);
            return other;
        }
        function reduce(arr, fun) {
            if (Array.prototype.reduce) {
                return Array.prototype.reduce.apply(arr, Array.prototype.slice.call(arguments, 1));
            }
            var len = +this.length;
            if (typeof fun !== "function") throw new TypeError();
            // no value to return if no initial value and an empty array
            if (len === 0 && arguments.length === 1) throw new TypeError();
            var i = 0;
            if (arguments.length >= 2) {
                var rv = arguments[1];
            } else {
                do {
                    if (i in this) {
                        rv = this[i++];
                        break;
                    }
                    // if array contains no values, no initial value to return
                    if (++i >= len) throw new TypeError();
                } while (true);
            }
            for (;i < len; i++) {
                if (i in this) rv = fun.call(null, rv, this[i], i, this);
            }
            return rv;
        }
        /**
   * Asserts deep equality
   *
   * @see taken from node.js `assert` module (copyright Joyent, MIT license)
   * @api private
   */
        expect.eql = function eql(actual, expected) {
            // 7.1. All identical values are equivalent, as determined by ===.
            if (actual === expected) {
                return true;
            } else if ("undefined" != typeof Buffer && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
                if (actual.length != expected.length) return false;
                for (var i = 0; i < actual.length; i++) {
                    if (actual[i] !== expected[i]) return false;
                }
                return true;
            } else if (actual instanceof Date && expected instanceof Date) {
                return actual.getTime() === expected.getTime();
            } else if (typeof actual != "object" && typeof expected != "object") {
                return actual == expected;
            } else {
                return objEquiv(actual, expected);
            }
        };
        function isUndefinedOrNull(value) {
            return value === null || value === undefined;
        }
        function isArguments(object) {
            return Object.prototype.toString.call(object) == "[object Arguments]";
        }
        function objEquiv(a, b) {
            if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) return false;
            // an identical "prototype" property.
            if (a.prototype !== b.prototype) return false;
            //~~~I've managed to break Object.keys through screwy arguments passing.
            //   Converting to array solves the problem.
            if (isArguments(a)) {
                if (!isArguments(b)) {
                    return false;
                }
                a = pSlice.call(a);
                b = pSlice.call(b);
                return expect.eql(a, b);
            }
            try {
                var ka = keys(a), kb = keys(b), key, i;
            } catch (e) {
                //happens when one is a string literal and the other isn't
                return false;
            }
            // having the same number of owned properties (keys incorporates hasOwnProperty)
            if (ka.length != kb.length) return false;
            //the same set of keys (although not necessarily the same order),
            ka.sort();
            kb.sort();
            //~~~cheap key test
            for (i = ka.length - 1; i >= 0; i--) {
                if (ka[i] != kb[i]) return false;
            }
            //equivalent values for every corresponding key, and
            //~~~possibly expensive deep test
            for (i = ka.length - 1; i >= 0; i--) {
                key = ka[i];
                if (!expect.eql(a[key], b[key])) return false;
            }
            return true;
        }
        var json = function() {
            "use strict";
            if ("object" == typeof JSON && JSON.parse && JSON.stringify) {
                return {
                    parse: nativeJSON.parse,
                    stringify: nativeJSON.stringify
                };
            }
            var JSON = {};
            function f(n) {
                // Format integers to have at least two digits.
                return n < 10 ? "0" + n : n;
            }
            function date(d, key) {
                return isFinite(d.valueOf()) ? d.getUTCFullYear() + "-" + f(d.getUTCMonth() + 1) + "-" + f(d.getUTCDate()) + "T" + f(d.getUTCHours()) + ":" + f(d.getUTCMinutes()) + ":" + f(d.getUTCSeconds()) + "Z" : null;
            }
            var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = {
                // table of character substitutions
                "\b": "\\b",
                "	": "\\t",
                "\n": "\\n",
                "\f": "\\f",
                "\r": "\\r",
                '"': '\\"',
                "\\": "\\\\"
            }, rep;
            function quote(string) {
                // If the string contains no control characters, no quote characters, and no
                // backslash characters, then we can safely slap some quotes around it.
                // Otherwise we must also replace the offending characters with safe escape
                // sequences.
                escapable.lastIndex = 0;
                return escapable.test(string) ? '"' + string.replace(escapable, function(a) {
                    var c = meta[a];
                    return typeof c === "string" ? c : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
                }) + '"' : '"' + string + '"';
            }
            function str(key, holder) {
                // Produce a string from holder[key].
                var i, // The loop counter.
                k, // The member key.
                v, // The member value.
                length, mind = gap, partial, value = holder[key];
                // If the value has a toJSON method, call it to obtain a replacement value.
                if (value instanceof Date) {
                    value = date(key);
                }
                // If we were called with a replacer function, then call the replacer to
                // obtain a replacement value.
                if (typeof rep === "function") {
                    value = rep.call(holder, key, value);
                }
                // What happens next depends on the value's type.
                switch (typeof value) {
                  case "string":
                    return quote(value);

                  case "number":
                    // JSON numbers must be finite. Encode non-finite numbers as null.
                    return isFinite(value) ? String(value) : "null";

                  case "boolean":
                  case "null":
                    // If the value is a boolean or null, convert it to a string. Note:
                    // typeof null does not produce 'null'. The case is included here in
                    // the remote chance that this gets fixed someday.
                    return String(value);

                  // If the type is 'object', we might be dealing with an object or an array or
                    // null.
                    case "object":
                    // Due to a specification blunder in ECMAScript, typeof null is 'object',
                    // so watch out for that case.
                    if (!value) {
                        return "null";
                    }
                    // Make an array to hold the partial results of stringifying this object value.
                    gap += indent;
                    partial = [];
                    // Is the value an array?
                    if (Object.prototype.toString.apply(value) === "[object Array]") {
                        // The value is an array. Stringify every element. Use null as a placeholder
                        // for non-JSON values.
                        length = value.length;
                        for (i = 0; i < length; i += 1) {
                            partial[i] = str(i, value) || "null";
                        }
                        // Join all of the elements together, separated with commas, and wrap them in
                        // brackets.
                        v = partial.length === 0 ? "[]" : gap ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" : "[" + partial.join(",") + "]";
                        gap = mind;
                        return v;
                    }
                    // If the replacer is an array, use it to select the members to be stringified.
                    if (rep && typeof rep === "object") {
                        length = rep.length;
                        for (i = 0; i < length; i += 1) {
                            if (typeof rep[i] === "string") {
                                k = rep[i];
                                v = str(k, value);
                                if (v) {
                                    partial.push(quote(k) + (gap ? ": " : ":") + v);
                                }
                            }
                        }
                    } else {
                        // Otherwise, iterate through all of the keys in the object.
                        for (k in value) {
                            if (Object.prototype.hasOwnProperty.call(value, k)) {
                                v = str(k, value);
                                if (v) {
                                    partial.push(quote(k) + (gap ? ": " : ":") + v);
                                }
                            }
                        }
                    }
                    // Join all of the member texts together, separated with commas,
                    // and wrap them in braces.
                    v = partial.length === 0 ? "{}" : gap ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" : "{" + partial.join(",") + "}";
                    gap = mind;
                    return v;
                }
            }
            // If the JSON object does not yet have a stringify method, give it one.
            JSON.stringify = function(value, replacer, space) {
                // The stringify method takes a value and an optional replacer, and an optional
                // space parameter, and returns a JSON text. The replacer can be a function
                // that can replace values, or an array of strings that will select the keys.
                // A default replacer method can be provided. Use of the space parameter can
                // produce text that is more easily readable.
                var i;
                gap = "";
                indent = "";
                // If the space parameter is a number, make an indent string containing that
                // many spaces.
                if (typeof space === "number") {
                    for (i = 0; i < space; i += 1) {
                        indent += " ";
                    }
                } else if (typeof space === "string") {
                    indent = space;
                }
                // If there is a replacer, it must be a function or an array.
                // Otherwise, throw an error.
                rep = replacer;
                if (replacer && typeof replacer !== "function" && (typeof replacer !== "object" || typeof replacer.length !== "number")) {
                    throw new Error("JSON.stringify");
                }
                // Make a fake root object containing our value under the key of ''.
                // Return the result of stringifying the value.
                return str("", {
                    "": value
                });
            };
            // If the JSON object does not yet have a parse method, give it one.
            JSON.parse = function(text, reviver) {
                // The parse method takes a text and an optional reviver function, and returns
                // a JavaScript value if the text is a valid JSON text.
                var j;
                function walk(holder, key) {
                    // The walk method is used to recursively walk the resulting structure so
                    // that modifications can be made.
                    var k, v, value = holder[key];
                    if (value && typeof value === "object") {
                        for (k in value) {
                            if (Object.prototype.hasOwnProperty.call(value, k)) {
                                v = walk(value, k);
                                if (v !== undefined) {
                                    value[k] = v;
                                } else {
                                    delete value[k];
                                }
                            }
                        }
                    }
                    return reviver.call(holder, key, value);
                }
                // Parsing happens in four stages. In the first stage, we replace certain
                // Unicode characters with escape sequences. JavaScript handles many characters
                // incorrectly, either silently deleting them, or treating them as line endings.
                text = String(text);
                cx.lastIndex = 0;
                if (cx.test(text)) {
                    text = text.replace(cx, function(a) {
                        return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
                    });
                }
                // In the second stage, we run the text against regular expressions that look
                // for non-JSON patterns. We are especially concerned with '()' and 'new'
                // because they can cause invocation, and '=' because it can cause mutation.
                // But just to be safe, we want to reject all unexpected forms.
                // We split the second stage into 4 regexp operations in order to work around
                // crippling inefficiencies in IE's and Safari's regexp engines. First we
                // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
                // replace all simple value tokens with ']' characters. Third, we delete all
                // open brackets that follow a colon or comma or that begin the text. Finally,
                // we look to see that the remaining characters are only whitespace or ']' or
                // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
                if (/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]").replace(/(?:^|:|,)(?:\s*\[)+/g, ""))) {
                    // In the third stage we use the eval function to compile the text into a
                    // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
                    // in JavaScript: it can begin a block or an object literal. We wrap the text
                    // in parens to eliminate the ambiguity.
                    j = eval("(" + text + ")");
                    // In the optional fourth stage, we recursively walk the new structure, passing
                    // each name/value pair to a reviver function for possible transformation.
                    return typeof reviver === "function" ? walk({
                        "": j
                    }, "") : j;
                }
                // If the text is not JSON parseable, then a SyntaxError is thrown.
                throw new SyntaxError("JSON.parse");
            };
            return JSON;
        }();
        if ("undefined" != typeof window) {
            window.expect = module.exports;
        }
    })(this, "undefined" != typeof module ? module : {}, "undefined" != typeof exports ? exports : {});
});