Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base: e63e56059c
...
compare: af6b160401
Checking mergeability… Don't worry, you can still create the pull request.
  • 10 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
View
18 README.md
@@ -2,10 +2,10 @@
![JSON 3 Logo](http://bestiejs.github.com/json3/page/logo.png)
-**JSON 3** is a modern JSON implementation compatible with a variety of JavaScript platforms, including Internet Explorer 6, Opera 7, Safari 2, and Netscape 6. The current version is **3.1**.
+**JSON 3** is a modern JSON implementation compatible with a variety of JavaScript platforms, including Internet Explorer 6, Opera 7, Safari 2, and Netscape 6. The current version is **3.2**.
-- [Development Version](http://bestiejs.github.com/json3/lib/json3.js) *(8.2 KB; uncompressed with comments)*
-- [Production Version](http://bestiejs.github.com/json3/lib/json3.min.js) *(3.0 KB; compressed)*
+- [Development Version](http://bestiejs.github.com/json3/lib/json3.js) *(37 KB; uncompressed with comments)*
+- [Production Version](http://bestiejs.github.com/json3/lib/json3.min.js) *(3.4 KB; compressed)*
[JSON](http://json.org/) is a language-independent data interchange format based on a loose subset of the JavaScript grammar. Originally popularized by [Douglas Crockford](http://www.crockford.com/), the format was standardized in the [fifth edition](http://es5.github.com/) of the ECMAScript specification. The 5.1 edition, ratified in June 2011, incorporates several modifications to the grammar pertaining to the serialization of dates.
@@ -34,6 +34,8 @@ In contrast to JSON 2, JSON 3 **does not**...
**Several native `Date#toJSON()` implementations produce date time strings that do *not* conform to the grammar outlined in the spec**. For instance, all versions of Safari 4, as well as JSON 2, fail to serialize extended years correctly. Furthermore, JSON 2 and older implementations omit the milliseconds from the date-time string (optional in ES 5, but required in 5.1). Finally, in all versions of Safari 4 and 5, serializing an invalid date will produce the string `"Invalid Date"`, rather than `null`. Because these environments exhibit other serialization bugs, however, JSON 3 will override the native `stringify()` implementation.
+Portions of the date serialization code are adapted from the [`date-shim`](https://github.com/Yaffle/date-shim) project.
+
# Usage #
## Web Browsers
@@ -99,11 +101,13 @@ JSON 3 assumes that the following methods exist and function as described in the
- The `Number`, `String`, `Array`, `Object`, `Date`, `SyntaxError`, and `TypeError` constructors.
- `String.fromCharCode`
+- `Object#toString`
- `Function#call`
-- `String.prototype`: `indexOf`, `charAt`, `slice`.
-- `Object.prototype`: `toString`, `hasOwnProperty` (a fallback is provided for Safari 2).
-- `Date.prototype`: `getUTC{FullYear, Month, Date, Hours, Minutes, Seconds, Milliseconds}`.
-- `Array.prototype`: `push`, `pop`, `join`.
+- `Math.floor`
+- `Number#toString`
+- `String.prototype`: `indexOf`, `charCodeAt`, `charAt`, `slice`.
+- `Date.prototype`: `getUTC{Hours, Minutes, Seconds, Milliseconds}`, `valueOf`.
+- `Array.prototype`: `push`, `pop`, `join`, `splice`.
# Contribute #
View
2  build.js
@@ -91,7 +91,7 @@ fs.readFile("lib/json3.js", "utf8", function (exception, source) {
// Remove the leading `!` character from YUI-style comments.
results += comment.type == "comment1" ? "//" + comment.value + "\n" : ("/*" + comment.value.slice(comment.value.charAt(0) == "!" ? 1 : 0) + "*/");
});
- results += "\n" + compressor.uglify.gen_code(
+ results += "\n;" + compressor.uglify.gen_code(
// Enable unsafe transformations.
compressor.uglify.ast_squeeze_more(
compressor.uglify.ast_squeeze(
View
23 index.html
@@ -19,12 +19,12 @@
<p><img src="http://bestiejs.github.com/json3/page/logo.png" alt="JSON 3 Logo">
</p>
-<p><strong>JSON 3</strong> is a modern JSON implementation compatible with a variety of JavaScript platforms, including Internet Explorer 6, Opera 7, Safari 2, and Netscape 6. The current version is <strong>3.1</strong>.
+<p><strong>JSON 3</strong> is a modern JSON implementation compatible with a variety of JavaScript platforms, including Internet Explorer 6, Opera 7, Safari 2, and Netscape 6. The current version is <strong>3.2</strong>.
</p>
<ul>
-<li><a href="http://bestiejs.github.com/json3/lib/json3.js">Development Version</a> <em>(8.2 KB; uncompressed with comments)</em></li>
-<li><a href="http://bestiejs.github.com/json3/lib/json3.min.js">Production Version</a> <em>(3.0 KB; compressed)</em></li>
+<li><a href="http://bestiejs.github.com/json3/lib/json3.js">Development Version</a> <em>(37 KB; uncompressed with comments)</em></li>
+<li><a href="http://bestiejs.github.com/json3/lib/json3.min.js">Production Version</a> <em>(3.4 KB; compressed)</em></li>
</ul>
<p><a href="http://json.org/">JSON</a> is a language-independent data interchange format based on a loose subset of the JavaScript grammar. Originally popularized by <a href="http://www.crockford.com/">Douglas Crockford</a>, the format was standardized in the <a href="http://es5.github.com/">fifth edition</a> of the ECMAScript specification. The 5.1 edition, ratified in June 2011, incorporates several modifications to the grammar pertaining to the serialization of dates.
@@ -35,7 +35,7 @@
<p>The JSON 3 parser does <strong>not</strong> use <code>eval</code> or regular expressions. This provides security and performance benefits in obsolete and mobile environments, where the margin is particularly significant. Informal benchmarks have shown that JSON 3 is slower than Crockford&#39;s <a href="https://github.com/douglascrockford/JSON-js">recursive descent parser</a> and Mike Samuel&#39;s <a href="http://code.google.com/p/json-sans-eval/"><code>json-sans-eval</code></a>, but approximates the speed of the <code>eval</code>-based JSON 2 parser.
</p>
-<p>The project is <a href="https://github.com/bestiejs/json3">hosted on GitHub</a>, along with the <a href="http://bestiejs.github.com/json3/test/test_browser.html">unit tests</a>. It is part of the <a href="https://github.com/bestiejs">BestieJS</a> family, a collection of best-in-class JavaScript libraries that promote cross-platform support, specification precedents, unit testing, and plenty of documentation.
+<p>The project is <a href="http://git.io/json3">hosted on GitHub</a>, along with the <a href="http://bestiejs.github.com/json3/test/test_browser.html">unit tests</a>. It is part of the <a href="https://github.com/bestiejs">BestieJS</a> family, a collection of best-in-class JavaScript libraries that promote cross-platform support, specification precedents, unit testing, and plenty of documentation.
</p>
<h1><a name="section_2"></a>Changes from JSON 2</h1>
@@ -61,6 +61,9 @@
<p><strong>Several native <code>Date#toJSON()</code> implementations produce date time strings that do <em>not</em> conform to the grammar outlined in the spec</strong>. For instance, all versions of Safari 4, as well as JSON 2, fail to serialize extended years correctly. Furthermore, JSON 2 and older implementations omit the milliseconds from the date-time string (optional in ES 5, but required in 5.1). Finally, in all versions of Safari 4 and 5, serializing an invalid date will produce the string <code>&quot;Invalid Date&quot;</code>, rather than <code>null</code>. Because these environments exhibit other serialization bugs, however, JSON 3 will override the native <code>stringify()</code> implementation.
</p>
+<p>Portions of the date serialization code are adapted from the <a href="https://github.com/Yaffle/date-shim"><code>date-shim</code></a> project.
+
+</p>
<h1><a name="section_3"></a>Usage</h1>
<h2>Web Browsers</h2>
<pre><code>&lt;script src=&quot;http://bestiejs.github.com/json3/lib/json3.min.js&quot;&gt;&lt;/script&gt;
@@ -119,13 +122,15 @@
</p>
<ul>
-<li>The <code>Number</code>, <code>String</code>, <code>Array</code>, <code>Object</code>, <code>SyntaxError</code>, and <code>TypeError</code> constructors.</li>
+<li>The <code>Number</code>, <code>String</code>, <code>Array</code>, <code>Object</code>, <code>Date</code>, <code>SyntaxError</code>, and <code>TypeError</code> constructors.</li>
<li><code>String.fromCharCode</code></li>
+<li><code>Object#toString</code></li>
<li><code>Function#call</code></li>
-<li><code>String.prototype</code>: <code>indexOf</code>, <code>charAt</code>, <code>slice</code>.</li>
-<li><code>Object.prototype</code>: <code>toString</code>, <code>hasOwnProperty</code> (a fallback is provided for Safari 2).</li>
-<li><code>Date.prototype</code>: <code>getUTC{FullYear, Month, Date, Hours, Minutes, Seconds, Milliseconds}</code>.</li>
-<li><code>Array.prototype</code>: <code>push</code>, <code>pop</code>, <code>join</code>.</li>
+<li><code>Math.floor</code></li>
+<li><code>Number#toString</code></li>
+<li><code>String.prototype</code>: <code>indexOf</code>, <code>charCodeAt</code>, <code>charAt</code>, <code>slice</code>.</li>
+<li><code>Date.prototype</code>: <code>getUTC{Hours, Minutes, Seconds, Milliseconds}</code>, <code>valueOf</code>.</li>
+<li><code>Array.prototype</code>: <code>push</code>, <code>pop</code>, <code>join</code>, <code>splice</code>.</li>
</ul>
<h1><a name="section_5"></a>Contribute</h1>
<p>Check out a working copy of the JSON 3 source code with <a href="http://git-scm.com/">Git</a>:
View
208 lib/json3.js
@@ -1,4 +1,4 @@
-/*! JSON v3.1 | http://bestiejs.github.com/json3 | Copyright 2012, Kit Cambridge | http://kit.mit-license.org */
+/*! JSON v3.2 | http://bestiejs.github.com/json3 | Copyright 2012, Kit Cambridge | http://kit.mit-license.org */
;(function (root, Module) {
if (typeof define == "function" && define.amd) {
// Export JSON 3 for asynchronous module loaders.
@@ -9,14 +9,20 @@
}
})(this, function (exports) {
// Convenience aliases.
- var getClass = {}.toString, hasOwnProperty = {}.hasOwnProperty, forEach, stringifySupported, parseSupported;
+ var getClass = {}.toString, isPropertyOf = {}.hasOwnProperty, getUTCSupported = false, stringifySupported, parseSupported, forEach;
// Feature tests to determine whether the native `JSON.stringify` and `parse`
// implementations are spec-compliant. Based on work by Ken Snyder.
stringifySupported = typeof exports.stringify == "function";
parseSupported = typeof exports.parse == "function";
(function () {
- var serialized = '{"result":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}', toJSON, original, value;
+ var serialized = '{"result":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}', value = new Date(-3509827334573292), toJSON, original;
+ // The `Date#getUTC{FullYear, Month, Date}` methods return nonsensical
+ // results for certain dates in Opera >= 10.54.
+ getUTCSupported = typeof value.getUTCFullYear == "function" && value.getUTCFullYear() == -109252 &&
+ typeof value.getUTCMonth == "function" && value.getUTCMonth() === 0 &&
+ typeof value.getUTCDate == "function" && value.getUTCDate() == 1;
+ value = null;
// Test `JSON.stringify`.
if (stringifySupported) {
// An object with a custom `toJSON` method.
@@ -75,8 +81,8 @@
// Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
// four-digit years instead of six-digit years. Credits: @Yaffle.
case exports.stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"':
- // Safari <= 5.1.5 incorrectly serializes millisecond values < 1000.
- // Credits: @Yaffle.
+ // Safari <= 5.1.5 and Opera >= 10.54 incorrectly serialize
+ // millisecond values less than 1000. Credits: @Yaffle.
case exports.stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"':
stringifySupported = false;
}
@@ -113,13 +119,13 @@
}
})();
- // **hasOwnProperty** determines if a property is a direct property of the
- // given object. Delegates to the native `Object#hasOwnProperty` method if
+ // Internal: Determines if a property is a direct property of the given
+ // object. Delegates to the native `Object#hasOwnProperty` method if
// available.
- if (typeof hasOwnProperty != "function") {
- hasOwnProperty = (function () {
+ if (!isPropertyOf || getClass.call(isPropertyOf) != "[object Function]") {
+ isPropertyOf = (function () {
// Capture a reference to the top-level `Object` constructor.
- var hasOwnProperty, members = {}, constructor = members.constructor;
+ var isPropertyOf, members = {}, constructor = members.constructor;
if ((members.__proto__ = null, members.__proto__ = {
// The internal *proto* property cannot be set multiple times in recent
// versions of Mozilla Firefox and SeaMonkey.
@@ -127,7 +133,7 @@
}, members).toString != getClass) {
// Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
// supports the mutable *proto* property.
- hasOwnProperty = function hasOwnProperty(property) {
+ isPropertyOf = function isPropertyOf(property) {
// Capture and break the object's prototype chain (see section 8.6.2
// of the ES 5.1 spec). The parenthesized expression prevents an
// unsafe transformation by the Closure Compiler.
@@ -139,17 +145,17 @@
} else {
// Use the `constructor` property to simulate `Object#hasOwnProperty` in
// other environments.
- hasOwnProperty = function hasOwnProperty(property) {
+ isPropertyOf = function isPropertyOf(property) {
var parent = (this.constructor || constructor).prototype;
return property in this && !(property in parent && this[property] === parent[property]);
};
}
members = null;
- return hasOwnProperty;
+ return isPropertyOf;
})();
}
- // **forEach** normalizes the `for...in` iteration algorithm across
+ // Internal: Normalizes the `for...in` iteration algorithm across
// environments. Each enumerated key is yielded to a `callback` function.
forEach = (function () {
var members, property, forEach, size = 0;
@@ -166,7 +172,7 @@
members = new Properties();
for (property in members) {
// Ignore all other properties inherited from `Object.prototype`.
- if (hasOwnProperty.call(members, property)) {
+ if (isPropertyOf.call(members, property)) {
size += 1;
}
}
@@ -183,17 +189,12 @@
for (property in object) {
// Gecko <= 1.0 enumerates the `prototype` property of functions under
// certain conditions; IE does not.
- if (!(isFunction && property == "prototype") && hasOwnProperty.call(object, property)) {
+ if (!(isFunction && property == "prototype") && isPropertyOf.call(object, property)) {
callback(property);
}
}
// Manually invoke the callback for each non-enumerable property.
- for (length = members.length; length--;) {
- property = members[length];
- if (hasOwnProperty.call(object, property)) {
- callback(property);
- }
- }
+ for (length = members.length; property = members[--length]; isPropertyOf.call(object, property) && callback(property));
};
} else if (size == 2) {
// Safari <= 2.0.4 enumerates shadowed properties twice.
@@ -204,7 +205,7 @@
// Store each property name to prevent double enumeration. The
// `prototype` property of functions is not enumerated due to cross-
// environment inconsistencies.
- if (!(isFunction && property == "prototype") && !hasOwnProperty.call(members, property) && (members[property] = 1) && hasOwnProperty.call(object, property)) {
+ if (!(isFunction && property == "prototype") && !isPropertyOf.call(members, property) && (members[property] = 1) && isPropertyOf.call(object, property)) {
callback(property);
}
}
@@ -214,13 +215,13 @@
forEach = function forEach(object, callback) {
var isFunction = getClass.call(object) == "[object Function]", property, isConstructor;
for (property in object) {
- if (!(isFunction && property == "prototype") && hasOwnProperty.call(object, property) && !(isConstructor = property === "constructor")) {
+ if (!(isFunction && property == "prototype") && isPropertyOf.call(object, property) && !(isConstructor = property === "constructor")) {
callback(property);
}
}
// Manually invoke the callback for the `constructor` property due to
// cross-environment inconsistencies.
- if (isConstructor || hasOwnProperty.call(object, "constructor")) {
+ if (isConstructor || isPropertyOf.call(object, "constructor")) {
callback("constructor");
}
};
@@ -228,15 +229,15 @@
return forEach;
})();
- // Serializes a JavaScript `value` as a JSON string. The optional `filter`
- // argument may be either a function that alters how certain values in objects
- // and arrays are serialized, or an array of strings and numbers that filters
- // object properties for serialization. The optional `width` argument may be
- // either a string or number that specifies the indentation level of the
- // output.
- if (!stringifySupported) {
+ // Public: Serializes a JavaScript `value` as a JSON string. The optional
+ // `filter` argument may specify either a function that alters how object and
+ // array members are serialized, or an array of strings and numbers that
+ // indicates which properties should be serialized. The optional `width`
+ // argument may be either a string or number that specifies the indentation
+ // level of the output.
+ if (!stringifySupported || (stringifySupported && !getUTCSupported)) {
exports.stringify = (function () {
- // Maps control characters to their escaped equivalents.
+ // Internal: A map of control characters and their escaped equivalents.
var Escapes = {
"\\": "\\\\",
'"': '\\"',
@@ -245,21 +246,24 @@
"\n": "\\n",
"\r": "\\r",
"\t": "\\t"
- };
+ },
- // Converts `value` into a zero-padded string such that its length is at
- // least equal to `width`. The `width` must be <= 6.
+ // Internal: A mapping between the months of the year and the number of
+ // days between January 1st and the first of the respective month.
+ Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], floor = Math.floor;
+
+ // Internal: Converts `value` into a zero-padded string such that its
+ // length is at least equal to `width`. The `width` must be <= 6.
function toPaddedString(width, value) {
- // The `|| 0` expression is necessary to work around a bug in Opera 7
- // where `0 == -0`, but `String(-0) == "-0"`.
- value = "000000" + (value || 0);
- // Opera 7 doesn't support passing negative arguments to `String#slice`.
- return value.slice(value.length - width);
+ // The `|| 0` expression is necessary to work around a bug in
+ // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
+ return ("000000" + (value || 0)).slice(-width);
}
- // Double-quotes a string, replacing all ASCII control characters with their
- // escaped equivalents. This is an implementation of the `Quote(value)`
- // operation defined in ES 5.1 section 15.12.3.
+ // Internal: Double-quotes a string `value`, replacing all ASCII control
+ // characters (characters with code unit values between 0 and 31) with
+ // their escaped equivalents. This is an implementation of the
+ // `Quote(value)` operation defined in ES 5.1 section 15.12.3.
function quote(value) {
var result = '"', index = 0, symbol;
for (; symbol = value.charAt(index); index += 1) {
@@ -273,20 +277,38 @@
return result + '"';
}
- // Recursively serializes an object. Implements the `Str(key, holder)`,
- // `JO(value)`, and `JA(value)` operations.
+ // Internal: Calculates the number of days between the Unix epoch and the
+ // first day of the given month.
+ function getDay(year, month) {
+ return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
+ }
+
+ // Internal: Recursively serializes an object. Implements the
+ // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
function serialize(property, object, callback, properties, whitespace, indentation, stack) {
- var value = object[property], className, year, results, element, index, length, prefix, any;
+ var value = object[property], className, date, year, month, results, element, index, length, prefix, any;
if (typeof value == "object" && value) {
- if (getClass.call(value) == "[object Date]" && !hasOwnProperty.call(value, "toJSON")) {
+ if (getClass.call(value) == "[object Date]" && !isPropertyOf.call(value, "toJSON")) {
if (value > -1 / 0 && value < 1 / 0) {
// Dates are serialized according to the `Date#toJSON` method
- // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15 for
- // the ISO 8601 date time string format.
- year = value.getUTCFullYear();
+ // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
+ // for the ISO 8601 date time string format.
+ if (getUTCSupported) {
+ year = value.getUTCFullYear();
+ month = value.getUTCMonth();
+ date = value.getUTCDate();
+ } else {
+ // Manually compute the year, month, and date if the `getUTC*`
+ // methods are buggy. Adapted from @Yaffle's `date-shim`
+ // project.
+ date = floor(value / 864e5);
+ for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year += 1);
+ for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month += 1);
+ date = 1 + date - getDay(year, month);
+ }
// Serialize extended years correctly.
value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
- "-" + toPaddedString(2, value.getUTCMonth() + 1) + "-" + toPaddedString(2, value.getUTCDate()) +
+ "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
// Months, dates, hours, minutes, and seconds should have two
// digits; milliseconds should have three.
"T" + toPaddedString(2, value.getUTCHours()) + ":" + toPaddedString(2, value.getUTCMinutes()) + ":" + toPaddedString(2, value.getUTCSeconds()) +
@@ -366,49 +388,44 @@
}
}
- // `JSON.stringify`. See section 15.12.3 of the ES 5.1 spec.
+ // Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
function stringify(value, filter, width) {
- var whitespace = "", callback, properties, length, element;
+ var whitespace, callback, properties, length, element;
if (typeof filter == "function" || typeof filter == "object" && filter) {
if (getClass.call(filter) == "[object Function]") {
callback = filter;
} else if (getClass.call(filter) == "[object Array]") {
// Convert the property names array into a makeshift set.
properties = {};
- for (length = filter.length; length--;) {
- element = filter[length];
- if (element && (getClass.call(element) == "[object String]" || getClass.call(element) == "[object Number]")) {
- properties[element] = 1;
- }
- }
+ for (length = filter.length; length--; ((element = filter[length]) && (getClass.call(element) == "[object String]" || getClass.call(element) == "[object Number]")) && (properties[element] = 1));
}
}
- if (width != null && width !== "") {
+ if (width != null && width !== "" && width !== 0) {
if (getClass.call(width) == "[object Number]") {
// Convert the `width` to an integer and create a string containing
// `width` number of space characters.
if ((width -= width % 1) > 0) {
- for (whitespace = "", width > 10 && (width = 10); whitespace.length < width;) {
- whitespace += " ";
- }
+ for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
}
} else if (getClass.call(width) == "[object String]") {
whitespace = width.length <= 10 ? width : width.slice(0, 10);
}
}
- // Opera 7 ignores `""` and `"\0"` object properties, so the `$`
- // character is used as a placeholder value instead.
- return serialize("$", { "$": value }, callback, properties, whitespace, "", []);
+ // Opera <= 7.54u2 discards the values associated with empty string keys
+ // (`""`) only if they are used directly within an object member list
+ // (e.g., `!("" in { "": 1})`).
+ return serialize("", (element = {}, element[""] = value, element), callback, properties, whitespace, "", []);
}
return stringify;
})();
}
- // Parses a JSON source string.
+ // Public: Parses a JSON source string.
if (!parseSupported) {
exports.parse = (function () {
- // Maps escaped JSON control characters to their revived equivalents.
+ // Internal: A map of escaped control characters and their unescaped
+ // equivalents.
var Unescapes = {
"\\": "\\",
'"': '"',
@@ -420,16 +437,16 @@
"r": "\r"
}, fromCharCode = "".constructor.fromCharCode;
- // Internal: creates a new JSON parser instance. The `source` string is parsed
- // according to the grammar specified in section 15.12.1 of the ES 5.1 spec.
+ // Internal: creates a new JSON parser instance. The `source` string is
+ // parsed according to the grammar specified in ES 5.1 section 15.12.1.
function Parser(source) {
this.source = source;
this.index = 0;
}
- // Returns the next token, or `"$"` if the parser has reached the end of the
- // source string. A token may be a string, number, `null` literal, or Boolean
- // literal.
+ // Internal: Returns the next token, or `"$"` if the parser has reached
+ // the end of the source string. A token may be a string, number, `null`
+ // literal, or Boolean literal.
Parser.prototype.lex = lex;
function lex() {
for (var source = this.source, length = this.source.length, symbol, value, begin, position, sign; this.index < length;) {
@@ -452,14 +469,12 @@
case ",":
this.index += 1;
return symbol;
- // Parse a JSON string token at the current position. String tokens are
- // prefixed with the special `@` character to distinguish them from
- // punctuators.
+ // Parse a JSON string token at the current position. String tokens
+ // are prefixed with the sentinel `@` character to distinguish them
+ // from punctuators.
case '"':
- value = "@";
// Advance to the first character.
- this.index += 1;
- while (this.index < length) {
+ for (value = "@", this.index += 1; this.index < length;) {
symbol = source.charAt(this.index);
if (symbol < " ") {
// Unescaped ASCII control characters are not permitted.
@@ -510,7 +525,8 @@
// Parse numbers and literals.
default:
begin = this.index;
- // Advance the scanner's position past the sign, if one is specified.
+ // Advance the scanner's position past the sign, if one is
+ // specified.
if (symbol == "-") {
sign = true;
symbol = source.charAt(this.index += 1);
@@ -538,7 +554,8 @@
// Parse exponents.
symbol = source.charAt(this.index);
if (symbol == "e" || symbol == "E") {
- // Skip past the sign following the exponent, if one is specified.
+ // Skip past the sign following the exponent, if one is
+ // specified.
symbol = source.charAt(this.index += 1);
if (symbol == "+" || symbol == "-") {
this.index += 1;
@@ -571,12 +588,12 @@
throw SyntaxError("Unrecognized token.");
}
}
- // Return the sentinel `$` character if the parser has reached the end of
- // the source string.
+ // Return the sentinel `$` character if the parser has reached the end
+ // of the source string.
return "$";
}
- // Parses a JSON token.
+ // Internal: Parses a JSON token.
Parser.prototype.get = get;
function get(value) {
var results, any, key;
@@ -599,8 +616,9 @@
if (value == "]") {
break;
}
- // If the array literal contains elements, the current token should
- // be a comma separating the previous element from the next.
+ // If the array literal contains elements, the current token
+ // should be a comma separating the previous element from the
+ // next.
if (any) {
if (value == ",") {
value = this.lex();
@@ -627,8 +645,8 @@
if (value == "}") {
break;
}
- // If the object literal contains members, the current token should
- // be a comma separating the previous member from the next.
+ // If the object literal contains members, the current token
+ // should be a comma separator.
if (any) {
if (value == ",") {
value = this.lex();
@@ -658,9 +676,9 @@
return value;
}
- // Recursively traverses a parsed JSON object, invoking the callback function
- // for each value. This is an implementation of the `Walk(holder, name)`
- // operation defined in ES 5.1 section 15.12.2.
+ // Internal: Recursively traverses a parsed JSON object, invoking the
+ // `callback` function for each value. This is an implementation of the
+ // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
function walk(source, property, callback) {
var value = source[property], length, element;
if (typeof value == "object" && value) {
@@ -687,14 +705,14 @@
return callback.call(source, property, value);
}
- // `JSON.parse`. See section 15.12.2.
+ // Public: `JSON.parse`. See ES 5.1 section 15.12.2.
function parse(source, callback) {
- var parser = new Parser("" + source), value = parser.get(parser.lex());
+ var parser = new Parser("" + source), value = parser.get(parser.lex()), element;
// If a JSON string contains multiple tokens, it is invalid.
if (parser.lex() != "$") {
throw SyntaxError("Expected end-of-file.");
}
- return callback && getClass.call(callback) == "[object Function]" ? walk({ "$": value }, "$", callback) : value;
+ return callback && getClass.call(callback) == "[object Function]" ? walk((element = {}, element[""] = value, element), "", callback) : value;
}
return parse;
View
7 lib/json3.min.js
@@ -1,3 +1,4 @@
-/* JSON v3.1 | http://bestiejs.github.com/json3 | Copyright 2012, Kit Cambridge | http://kit.mit-license.org */
-(function(a,b){typeof define=="function"&&define.amd?define("json",["exports"],b):b(typeof exports=="object"&&exports||this.JSON||(this.JSON={}))})(this,function(a){var b={}.toString,c={}.hasOwnProperty,d,e,f;return e=typeof a.stringify=="function",f=typeof a.parse=="function",function(){var c='{"result":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}',d,g,h;if(e){d=function(){return 1},d.toJSON=d;try{switch(!1){case a.stringify(0)==="0":case a.stringify(new 0..constructor)==="0":case a.stringify(new"".constructor)=='""':case a.stringify(b)===void 0:case a.stringify(void 0)===void 0:case a.stringify()===void 0:case a.stringify(d)==="1":case a.stringify([d])=="[1]":case a.stringify([void 0])=="[null]":case a.stringify(null)=="null":case a.stringify([void 0,b,null])=="[null,null,null]":case a.stringify({result:[d,true,false,null,"\0\b\n\f\r "]})==c:case a.stringify(null,d)==="1":case a.stringify([1,2],null,1)=="[\n 1,\n 2\n]":case(d=new Date(-864e13)).getUTCFullYear()!=-271821||a.stringify(d)=='"-271821-04-20T00:00:00.000Z"':case(d=new Date(864e13)).getUTCFullYear()!=275760||a.stringify(d)=='"+275760-09-13T00:00:00.000Z"':e=!1}}catch(i){e=!1}}if(f)try{if(a.parse("0")===0&&!a.parse(!1)){h=a.parse(c);if(f=h.result.length==5&&h.result[0]==1){try{f=!a.parse('" "')}catch(i){}if(f)try{f=a.parse("+1")!=1&&a.parse("01")!=1}catch(i){}}}}catch(i){f=!1}}(),typeof c!="function"&&(c=function(){var a,c={},d=c.constructor;return(c.__proto__=null,c.__proto__={toString:1},c).toString!=b?a=function e(a){var b=this.__proto__,c=a in(this.__proto__=null,this);return this.__proto__=b,c}:a=function f(a){var b=(this.constructor||d).prototype;return a in this&&!(a in b&&this[a]===b[a])},c=null,a}()),d=function(){function g(){this.valueOf=0}var a,d,e,f=0;g.prototype.valueOf=0,a=new g;for(d in a)c.call(a,d)&&(f+=1);return a=null,f?f==2?e=function(d,e){var f={},g=b.call(d)=="[object Function]",h;for(h in d)(!g||h!="prototype")&&!c.call(f,h)&&(f[h]=1)&&c.call(d,h)&&e(h)}:e=function(d,e){var f=b.call(d)=="[object Function]",g,h;for(g in d)(!f||g!="prototype")&&c.call(d,g)&&!(h=g==="constructor")&&e(g);(h||c.call(d,"constructor"))&&e("constructor")}:(a=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"],e=function(e,f){var g=b.call(e)=="[object Function]",h,i;for(h in e)(!g||h!="prototype")&&c.call(e,h)&&f(h);for(i=a.length;i--;)h=a[i],c.call(e,h)&&f(h)}),e}(),e||(a.stringify=function(){function e(a,b){return b="000000"+(b||0),b.slice(b.length-a)}function f(b){var c='"',d=0,f;for(;f=b.charAt(d);d+=1)c+='\\"\b\f\n\r '.indexOf(f)>-1?a[f]:f<" "?"\\u00"+e(2,f.charCodeAt(0).toString(16)):f;return c+'"'}function g(a,h,i,j,k,l,m){var n=h[a],o,p,q,r,s,t,u,v;typeof n=="object"&&n&&(b.call(n)=="[object Date]"&&!c.call(n,"toJSON")?n>-1/0&&n<1/0?(p=n.getUTCFullYear(),n=(p<=0||p>=1e4?(p<0?"-":"+")+e(6,p<0?-p:p):e(4,p))+"-"+e(2,n.getUTCMonth()+1)+"-"+e(2,n.getUTCDate())+"T"+e(2,n.getUTCHours())+":"+e(2,n.getUTCMinutes())+":"+e(2,n.getUTCSeconds())+"."+e(3,n.getUTCMilliseconds())+"Z"):n=null:typeof n.toJSON=="function"&&(n=n.toJSON(a))),i&&(n=i.call(h,a,n));if(n===null)return"null";o=b.call(n);switch(o){case"[object Boolean]":return""+n;case"[object Number]":return n>-1/0&&n<1/0?""+n:"null";case"[object String]":return f(n)}if(typeof n=="object"){for(t=m.length;t--;)if(m[t]==n)throw TypeError("Cyclic structures cannot be serialized.");m.push(n),q=[],u=l,l+=k;if(o=="[object Array]"){for(s=0,t=n.length;s<t;v||(v=!0),s++)r=g(s,n,i,j,k,l,m),q.push(r===void 0?"null":r);return v?k?"[\n"+l+q.join(",\n"+l)+"\n"+u+"]":"["+q.join(",")+"]":"[]"}return d(j||n,function(a){var b=g(a,n,i,j,k,l,m);b!==void 0&&q.push(f(a)+":"+(k?" ":"")+b),v||(v=!0)}),v?k?"{\n"+l+q.join(",\n"+l)+"\n"+u+"}":"{"+q.join(",")+"}":"{}"}}function h(a,c,d){var e="",f,h,i,j;if(typeof c=="function"||typeof c=="object"&&c)if(b.call(c)=="[object Function]")f=c;else if(b.call(c)=="[object Array]"){h={};for(i=c.length;i--;)j=c[i],j&&(b.call(j)=="[object String]"||
-b.call(j)=="[object Number]")&&(h[j]=1)}if(d!=null&&d!=="")if(b.call(d)=="[object Number]"){if((d-=d%1)>0)for(e="",d>10&&(d=10);e.length<d;)e+=" "}else b.call(d)=="[object String]"&&(e=d.length<=10?d:d.slice(0,10));return g("$",{$:a},f,h,e,"",[])}var a={"\\":"\\\\",'"':'\\"',"\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r"," ":"\\t"};return h}()),f||(a.parse=function(){function e(a){this.source=a,this.index=0}function f(){for(var b=this.source,d=this.source.length,e,f,g,h,i;this.index<d;){e=b.charAt(this.index);switch(e){case" ":case"\r":case"\n":case" ":this.index+=1;break;case"{":case"}":case"[":case"]":case":":case",":return this.index+=1,e;case'"':f="@",this.index+=1;while(this.index<d){e=b.charAt(this.index);if(e<" ")throw SyntaxError("Unescaped control character in string.");if(e=="\\"){this.index+=1,e=b.charAt(this.index);if('\\"/btnfr'.indexOf(e)>-1)f+=a[e],this.index+=1;else{if(e!="u")throw SyntaxError("Invalid escape sequence in string.");g=this.index+=1;for(h=this.index+4;this.index<h;this.index+=1){e=b.charAt(this.index);if(!(e>="0"&&e<="9"||e>="a"&&e<="f"||e>="A"&&e<="F"))throw SyntaxError("Invalid Unicode escape sequence in string.")}f+=c("0x"+b.slice(g,this.index))}}else{if(e=='"')break;f+=e,this.index+=1}}if(b.charAt(this.index)=='"')return this.index+=1,f;throw SyntaxError("Unterminated string.");default:g=this.index,e=="-"&&(i=!0,e=b.charAt(this.index+=1));if(e>="0"&&e<="9"){if(e=="0"&&(e=b.charAt(this.index+1),e>="0"&&e<="9"))throw SyntaxError("Illegal octal literal.");i=!1;for(;this.index<d&&(e=b.charAt(this.index),e>="0"&&e<="9");this.index+=1);if(b.charAt(this.index)=="."){h=this.index+=1;for(;h<d&&(e=b.charAt(h),e>="0"&&e<="9");h+=1);if(h==this.index)throw SyntaxError("Illegal trailing decimal.");this.index=h}e=b.charAt(this.index);if(e=="e"||e=="E"){e=b.charAt(this.index+=1);if(e=="+"||e=="-")this.index+=1;for(h=this.index;h<d&&(e=b.charAt(h),e>="0"&&e<="9");h+=1);if(h==this.index)throw SyntaxError("Illegal empty exponent.");this.index=h}return+b.slice(g,this.index)}if(i)throw SyntaxError("Unexpected `-`.");if(e=="t"&&b.slice(this.index,this.index+4)=="true")return this.index+=4,!0;if(e=="f"&&b.slice(this.index,this.index+5)=="false")return this.index+=5,!1;if(e=="n"&&b.slice(this.index,this.index+4)=="null")return this.index+=4,null;throw SyntaxError("Unrecognized token.")}}return"$"}function g(a){var b,c,d;if(a=="$")throw SyntaxError("Unexpected end-of-file.");if(typeof a=="string"){if(a.charAt(0)=="@")return a.slice(1);switch(a){case"[":b=[];for(;;c||(c=!0)){a=this.lex();if(a=="]")break;if(c){if(a!=",")throw SyntaxError("A comma (`,`) must separate the previous array element from the next.");a=this.lex();if(a=="]")throw SyntaxError("Unexpected trailing `,` in array literal.")}if(a==",")throw SyntaxError("Unexpected `,` in array literal.");b.push(this.get(a))}return b;case"{":b={};for(;;c||(c=!0)){a=this.lex();if(a=="}")break;if(c){if(a!=",")throw SyntaxError("A comma (`,`) must separate the previous object member from the next.");a=this.lex();if(a=="}")throw SyntaxError("Unexpected trailing `,`. in object literal.")}if(a==",")throw SyntaxError("Unexpected `,` in object literal.");if(typeof a!="string"||a.charAt(0)!="@")throw SyntaxError("Object property names must be double-quoted strings.");if(this.lex()!=":")throw SyntaxError("A single colon (`:`) must separate each object property name from the value.");b[a.slice(1)]=this.get(this.lex())}return b}throw SyntaxError("Expected `[` or `{`.")}return a}function h(a,c,e){var f=a[c],g,i;if(typeof f=="object"&&f)if(b.call(f)=="[object Array]")for(g=f.length;g--;)i=h(f,g,e),i===void 0?f.splice(g,1):f[g]=i;else d(f,function(a){var b=h(f,a,e);b===void 0?delete f[a]:f[a]=b});return e.call(a,c,f)}function i(a,c){var d=new e(""+a),f=d.get(d.lex());if(d.lex()!="$")throw SyntaxError("Expected end-of-file.");return c&&b.call(c)=="[object Function]"?h({$:f},"$",c):f}var a={"\\":"\\",'"':'"',"/":"/",b:"\b",t:" ",n:"\n",f:"\f",r:"\r"},c="".constructor.fromCharCode;return e.prototype.lex=f,e.prototype.get=g,i}()),a})
+/* JSON v3.2 | http://bestiejs.github.com/json3 | Copyright 2012, Kit Cambridge | http://kit.mit-license.org */
+;(function(a,b){typeof define=="function"&&define.amd?define("json",["exports"],b):b(typeof exports=="object"&&exports||this.JSON||(this.JSON={}))})(this,function(a){var b={}.toString,c={}.hasOwnProperty,d=!1,e,f,g;e=typeof a.stringify=="function",f=typeof a.parse=="function",function(){var c='{"result":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}',g=new Date(-0xc782b5b800cec),h,i;d=typeof g.getUTCFullYear=="function"&&g.getUTCFullYear()==-109252&&typeof g.getUTCMonth=="function"&&g.getUTCMonth()===0&&typeof g.getUTCDate=="function"&&g.getUTCDate()==1,g=null;if(e){h=function(){return 1},h.toJSON=h;try{switch(!1){case a.stringify(0)==="0":case a.stringify(new 0..constructor)==="0":case a.stringify(new"".constructor)=='""':case a.stringify(b)===void 0:case a.stringify(void 0)===void 0:case a.stringify()===void 0:case a.stringify(h)==="1":case a.stringify([h])=="[1]":case a.stringify([void 0])=="[null]":case a.stringify(null)=="null":case a.stringify([void 0,b,null])=="[null,null,null]":case a.stringify({result:[h,true,false,null,"\0\b\n\f\r "]})==c:case a.stringify(null,h)==="1":case a.stringify([1,2],null,1)=="[\n 1,\n 2\n]":case(h=new Date(-864e13)).getUTCFullYear()!=-271821||a.stringify(h)=='"-271821-04-20T00:00:00.000Z"':case(h=new Date(864e13)).getUTCFullYear()!=275760||a.stringify(h)=='"+275760-09-13T00:00:00.000Z"':case a.stringify(new Date(-621987552e5))=='"-000001-01-01T00:00:00.000Z"':case a.stringify(new Date(-1))=='"1969-12-31T23:59:59.999Z"':e=!1}}catch(j){e=!1}}if(f)try{if(a.parse("0")===0&&!a.parse(!1)){g=a.parse(c);if(f=g.result.length==5&&g.result[0]==1){try{f=!a.parse('" "')}catch(j){}if(f)try{f=a.parse("+1")!=1&&a.parse("01")!=1}catch(j){}}}}catch(j){f=!1}}();if(!c||b.call(c)!="[object Function]")c=function(){var a,c={},d=c.constructor;return(c.__proto__=null,c.__proto__={toString:1},c).toString!=b?a=function(b){var c=this.__proto__,d=b in(this.__proto__=null,this);return this.__proto__=c,d}:a=function(b){var c=(this.constructor||d).prototype;return b in this&&!(b in c&&this[b]===c[b])},c=null,a}();g=function(){function g(){this.valueOf=0}var a,d,e,f=0;g.prototype.valueOf=0,a=new g;for(d in a)c.call(a,d)&&(f+=1);return a=null,f?f==2?e=function(d,e){var f={},g=b.call(d)=="[object Function]",h;for(h in d)(!g||h!="prototype")&&!c.call(f,h)&&(f[h]=1)&&c.call(d,h)&&e(h)}:e=function(d,e){var f=b.call(d)=="[object Function]",g,h;for(g in d)(!f||g!="prototype")&&c.call(d,g)&&!(h=g==="constructor")&&e(g);(h||c.call(d,"constructor"))&&e("constructor")}:(a=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"],e=function(e,f){var g=b.call(e)=="[object Function]",h,i;for(h in e)(!g||h!="prototype")&&c.call(e,h)&&f(h);for(i=a.length;h=a[--i];c.call(e,h)&&f(h));}),e}();if(!e||e&&!d)a.stringify=function(){function h(a,b){return("000000"+(b||0)).slice(-a)}function i(b){var c='"',d=0,e;for(;e=b.charAt(d);d+=1)c+='\\"\b\f\n\r '.indexOf(e)>-1?a[e]:e<" "?"\\u00"+h(2,e.charCodeAt(0).toString(16)):e;return c+'"'}function j(a,b){return e[b]+365*(a-1970)+f((a-1969+(b=+(b>1)))/4)-f((a-1901+b)/100)+f((a-1601+b)/400)}function k(a,e,l,m,n,o,p){var q=e[a],r,s,t,u,v,w,x,y,z,A;if(typeof q=="object"&&q)if(b.call(q)=="[object Date]"&&!c.call(q,"toJSON"))if(q>-1/0&&q<1/0){if(d)t=q.getUTCFullYear(),u=q.getUTCMonth(),s=q.getUTCDate();else{s=f(q/864e5);for(t=f(s/365.2425)+1970-1;j(t+1,0)<=s;t+=1);for(u=f((s-j(t,0))/30.42);j(t,u+1)<=s;u+=1);s=1+s-j(t,u)}q=(t<=0||t>=1e4?(t<0?"-":"+")+h(6,t<0?-t:t):h(4,t))+"-"+h(2,u+1)+"-"+h(2,s)+"T"+h(2,q.getUTCHours())+":"+h(2,q.getUTCMinutes())+":"+h(2,q.getUTCSeconds())+"."+h(3,q.getUTCMilliseconds())+"Z"}else q=null;else typeof q.toJSON=="function"&&(q=q.toJSON(a));l&&(q=l.call(e,a,q));if(q===null)return"null";r=b.call(q);switch(r){case"[object Boolean]":return""+q;case"[object Number]":return q>-1/0&&q<1/0?""+q:"null";case"[object String]":return i(q)}if(typeof q=="object"){for(y=p.length;y--;)if(p[y]==q)throw TypeError("Cyclic structures cannot be serialized."
+);p.push(q),v=[],z=o,o+=n;if(r=="[object Array]"){for(x=0,y=q.length;x<y;A||(A=!0),x++)w=k(x,q,l,m,n,o,p),v.push(w===void 0?"null":w);return A?n?"[\n"+o+v.join(",\n"+o)+"\n"+z+"]":"["+v.join(",")+"]":"[]"}return g(m||q,function(a){var b=k(a,q,l,m,n,o,p);b!==void 0&&v.push(i(a)+":"+(n?" ":"")+b),A||(A=!0)}),A?n?"{\n"+o+v.join(",\n"+o)+"\n"+z+"}":"{"+v.join(",")+"}":"{}"}}function l(a,c,d){var e,f,g,h,i;if(typeof c=="function"||typeof c=="object"&&c)if(b.call(c)=="[object Function]")f=c;else if(b.call(c)=="[object Array]"){g={};for(h=c.length;h--;(i=c[h])&&(b.call(i)=="[object String]"||b.call(i)=="[object Number]")&&(g[i]=1));}if(d!=null&&d!==""&&d!==0)if(b.call(d)=="[object Number]"){if((d-=d%1)>0)for(e="",d>10&&(d=10);e.length<d;e+=" ");}else b.call(d)=="[object String]"&&(e=d.length<=10?d:d.slice(0,10));return k("",(i={},i[""]=a,i),f,g,e,"",[])}var a={"\\":"\\\\",'"':'\\"',"\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r"," ":"\\t"},e=[0,31,59,90,120,151,181,212,243,273,304,334],f=Math.floor;return l}();return f||(a.parse=function(){function d(a){this.source=a,this.index=0}function e(){for(var b=this.source,d=this.source.length,e,f,g,h,i;this.index<d;){e=b.charAt(this.index);switch(e){case" ":case"\r":case"\n":case" ":this.index+=1;break;case"{":case"}":case"[":case"]":case":":case",":return this.index+=1,e;case'"':for(f="@",this.index+=1;this.index<d;){e=b.charAt(this.index);if(e<" ")throw SyntaxError("Unescaped control character in string.");if(e=="\\"){this.index+=1,e=b.charAt(this.index);if('\\"/btnfr'.indexOf(e)>-1)f+=a[e],this.index+=1;else{if(e!="u")throw SyntaxError("Invalid escape sequence in string.");g=this.index+=1;for(h=this.index+4;this.index<h;this.index+=1){e=b.charAt(this.index);if(!(e>="0"&&e<="9"||e>="a"&&e<="f"||e>="A"&&e<="F"))throw SyntaxError("Invalid Unicode escape sequence in string.")}f+=c("0x"+b.slice(g,this.index))}}else{if(e=='"')break;f+=e,this.index+=1}}if(b.charAt(this.index)=='"')return this.index+=1,f;throw SyntaxError("Unterminated string.");default:g=this.index,e=="-"&&(i=!0,e=b.charAt(this.index+=1));if(e>="0"&&e<="9"){if(e=="0"&&(e=b.charAt(this.index+1),e>="0"&&e<="9"))throw SyntaxError("Illegal octal literal.");i=!1;for(;this.index<d&&(e=b.charAt(this.index),e>="0"&&e<="9");this.index+=1);if(b.charAt(this.index)=="."){h=this.index+=1;for(;h<d&&(e=b.charAt(h),e>="0"&&e<="9");h+=1);if(h==this.index)throw SyntaxError("Illegal trailing decimal.");this.index=h}e=b.charAt(this.index);if(e=="e"||e=="E"){e=b.charAt(this.index+=1);if(e=="+"||e=="-")this.index+=1;for(h=this.index;h<d&&(e=b.charAt(h),e>="0"&&e<="9");h+=1);if(h==this.index)throw SyntaxError("Illegal empty exponent.");this.index=h}return+b.slice(g,this.index)}if(i)throw SyntaxError("Unexpected `-`.");if(e=="t"&&b.slice(this.index,this.index+4)=="true")return this.index+=4,!0;if(e=="f"&&b.slice(this.index,this.index+5)=="false")return this.index+=5,!1;if(e=="n"&&b.slice(this.index,this.index+4)=="null")return this.index+=4,null;throw SyntaxError("Unrecognized token.")}}return"$"}function f(a){var b,c,d;if(a=="$")throw SyntaxError("Unexpected end-of-file.");if(typeof a=="string"){if(a.charAt(0)=="@")return a.slice(1);switch(a){case"[":b=[];for(;;c||(c=!0)){a=this.lex();if(a=="]")break;if(c){if(a!=",")throw SyntaxError("A comma (`,`) must separate the previous array element from the next.");a=this.lex();if(a=="]")throw SyntaxError("Unexpected trailing `,` in array literal.")}if(a==",")throw SyntaxError("Unexpected `,` in array literal.");b.push(this.get(a))}return b;case"{":b={};for(;;c||(c=!0)){a=this.lex();if(a=="}")break;if(c){if(a!=",")throw SyntaxError("A comma (`,`) must separate the previous object member from the next.");a=this.lex();if(a=="}")throw SyntaxError("Unexpected trailing `,`. in object literal.")}if(a==",")throw SyntaxError("Unexpected `,` in object literal.");if(typeof a!="string"||a.charAt(0)!="@")throw SyntaxError("Object property names must be double-quoted strings.");if(this.lex()!=":")throw SyntaxError("A single colon (`:`) must separate each object property name from the value.");b[a.slice(1)]=this.get(this.lex
+())}return b}throw SyntaxError("Expected `[` or `{`.")}return a}function h(a,c,d){var e=a[c],f,i;if(typeof e=="object"&&e)if(b.call(e)=="[object Array]")for(f=e.length;f--;)i=h(e,f,d),i===void 0?e.splice(f,1):e[f]=i;else g(e,function(a){var b=h(e,a,d);b===void 0?delete e[a]:e[a]=b});return d.call(a,c,e)}function i(a,c){var e=new d(""+a),f=e.get(e.lex()),g;if(e.lex()!="$")throw SyntaxError("Expected end-of-file.");return c&&b.call(c)=="[object Function]"?h((g={},g[""]=f,g),"",c):f}var a={"\\":"\\",'"':'"',"/":"/",b:"\b",t:" ",n:"\n",f:"\f",r:"\r"},c="".constructor.fromCharCode;return d.prototype.lex=e,d.prototype.get=f,i}()),a})
View
2  package.json
@@ -1,6 +1,6 @@
{
"name": "json3",
- "version": "3.1.0",
+ "version": "3.2.0",
"description": "A modern JSON implementation compatible with nearly all JavaScript platforms.",
"homepage": "http://bestiejs.github.com/json3",
"main": "./lib/json3",
View
10 test/test_json3.js
@@ -217,7 +217,7 @@
});
testSuite.addTest("`stringify`", function () {
- var expected = 23, value, pattern;
+ var expected = 24, value, pattern;
// Special values.
this.serializes("null", null, "`null` is represented literally");
@@ -258,13 +258,7 @@
this.serializes('"1969-12-31T23:59:59.999Z"', new Date(-1), "Millisecond values < 1000 should be serialized correctly");
this.serializes('"-000001-01-01T00:00:00.000Z"', new Date(-621987552e5), "Years prior to 0 should be serialized as extended years");
this.serializes('"+010000-01-01T00:00:00.000Z"', new Date(2534023008e5), "Years after 9999 should be serialized as extended years");
-
- value = new Date(-3509827334573292);
- if (value.getUTCFullYear() == -109252) {
- // This test will fail in Opera >= 10.53. See issue #4.
- expected += 1;
- this.serializes('"-109252-01-01T10:37:06.708Z"', value, "Opera <= 9.64 should correctly serialize a date with a year of `-109252`");
- }
+ this.serializes('"-109252-01-01T10:37:06.708Z"', new Date(-3509827334573292), "Issue #4: Opera > 9.64 should correctly serialize a date with a year of `-109252`");
// Safari 2 restricts date time values to the range `[(-2 ** 31),
// (2 ** 31) - 1]`, which respectively correspond to the minimum and

No commit comments for this range

Something went wrong with that request. Please try again.