| 2017 | // Internal: Determines whether the native `JSON.stringify` and `parse` |
| 2018 | // implementations are spec-compliant. Based on work by Ken Snyder. |
| 2019 | function has(name) { |
| 2020 | if (has[name] !== undef) { |
| 2021 | // Return cached feature test result. |
| 2022 | return has[name]; |
| 2023 | } |
| 2024 | var isSupported; |
| 2025 | if (name == "bug-string-char-index") { |
| 2026 | // IE <= 7 doesn't support accessing string characters using square |
| 2027 | // bracket notation. IE 8 only supports this for primitives. |
| 2028 | isSupported = "a"[0] != "a"; |
| 2029 | } else if (name == "json") { |
| 2030 | // Indicates whether both `JSON.stringify` and `JSON.parse` are |
| 2031 | // supported. |
| 2032 | isSupported = has("json-stringify") && has("json-parse"); |
| 2033 | } else { |
| 2034 | var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'; |
| 2035 | // Test `JSON.stringify`. |
| 2036 | if (name == "json-stringify") { |
| 2037 | var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended; |
| 2038 | if (stringifySupported) { |
| 2039 | // A test function object with a custom `toJSON` method. |
| 2040 | (value = function () { |
| 2041 | return 1; |
| 2042 | }).toJSON = value; |
| 2043 | try { |
| 2044 | stringifySupported = |
| 2045 | // Firefox 3.1b1 and b2 serialize string, number, and boolean |
| 2046 | // primitives as object literals. |
| 2047 | stringify(0) === "0" && |
| 2048 | // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object |
| 2049 | // literals. |
| 2050 | stringify(new Number()) === "0" && |
| 2051 | stringify(new String()) == '""' && |
| 2052 | // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or |
| 2053 | // does not define a canonical JSON representation (this applies to |
| 2054 | // objects with `toJSON` properties as well, *unless* they are nested |
| 2055 | // within an object or array). |
| 2056 | stringify(getClass) === undef && |
| 2057 | // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and |
| 2058 | // FF 3.1b3 pass this test. |
| 2059 | stringify(undef) === undef && |
| 2060 | // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s, |
| 2061 | // respectively, if the value is omitted entirely. |
| 2062 | stringify() === undef && |
| 2063 | // FF 3.1b1, 2 throw an error if the given value is not a number, |
| 2064 | // string, array, object, Boolean, or `null` literal. This applies to |
| 2065 | // objects with custom `toJSON` methods as well, unless they are nested |
| 2066 | // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON` |
| 2067 | // methods entirely. |
| 2068 | stringify(value) === "1" && |
| 2069 | stringify([value]) == "[1]" && |
| 2070 | // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of |
| 2071 | // `"[null]"`. |
| 2072 | stringify([undef]) == "[null]" && |
| 2073 | // YUI 3.0.0b1 fails to serialize `null` literals. |
| 2074 | stringify(null) == "null" && |
| 2075 | // FF 3.1b1, 2 halts serialization if an array contains a function: |
| 2076 | // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3 |