| /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ |
| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| //----------------------------------------------------------------------------- |
| var BUGNUMBER = 450369; |
| var summary = 'Crash with JIT and json2.js'; |
| var actual = 'No Crash'; |
| var expect = 'No Crash'; |
| |
| jit(true); |
| |
| /* |
| json2.js |
| 2007-11-06 |
| |
| Public Domain |
| |
| See http://www.JSON.org/js.html |
| |
| This file creates a global JSON object containing two methods: |
| |
| JSON.stringify(value, whitelist) |
| value any JavaScript value, usually an object or array. |
| |
| whitelist an optional that determines how object values are |
| stringified. |
| |
| This method produces a JSON text from a JavaScript value. |
| There are three possible ways to stringify an object, depending |
| on the optional whitelist parameter. |
| |
| If an object has a toJSON method, then the toJSON() method will be |
| called. The value returned from the toJSON method will be |
| stringified. |
| |
| Otherwise, if the optional whitelist parameter is an array, then |
| the elements of the array will be used to select members of the |
| object for stringification. |
| |
| Otherwise, if there is no whitelist parameter, then all of the |
| members of the object will be stringified. |
| |
| Values that do not have JSON representaions, such as undefined or |
| functions, will not be serialized. Such values in objects will be |
| dropped, in arrays will be replaced with null. JSON.stringify() |
| returns undefined. Dates will be stringified as quoted ISO dates. |
| |
| Example: |
| |
| var text = JSON.stringify(['e', {pluribus: 'unum'}]); |
| // text is '["e",{"pluribus":"unum"}]' |
| |
| JSON.parse(text, filter) |
| This method parses a JSON text to produce an object or |
| array. It can throw a SyntaxError exception. |
| |
| The optional filter parameter is a function that can filter and |
| transform the results. It receives each of the keys and values, and |
| its return value is used instead of the original value. If it |
| returns what it received, then structure is not modified. If it |
| returns undefined then the member is deleted. |
| |
| Example: |
| |
| // Parse the text. If a key contains the string 'date' then |
| // convert the value to a date. |
| |
| myData = JSON.parse(text, function (key, value) { |
| return key.indexOf('date') >= 0 ? new Date(value) : value; |
| }); |
| |
| This is a reference implementation. You are free to copy, modify, or |
| redistribute. |
| |
| Use your own copy. It is extremely unwise to load third party |
| code into your pages. |
| */ |
| |
| /*jslint evil: true */ |
| /*extern JSON */ |
| |
| if (!this.emulatedJSON) { |
| |
| emulatedJSON = function () { |
| |
| function f(n) { // Format integers to have at least two digits. |
| return n < 10 ? '0' + n : n; |
| } |
| |
| Date.prototype.toJSON = function () { |
| |
| // Eventually, this method will be based on the date.toISOString method. |
| |
| return this.getUTCFullYear() + '-' + |
| f(this.getUTCMonth() + 1) + '-' + |
| f(this.getUTCDate()) + 'T' + |
| f(this.getUTCHours()) + ':' + |
| f(this.getUTCMinutes()) + ':' + |
| f(this.getUTCSeconds()) + 'Z'; |
| }; |
| |
| |
| var m = { // table of character substitutions |
| '\b': '\\b', |
| '\t': '\\t', |
| '\n': '\\n', |
| '\f': '\\f', |
| '\r': '\\r', |
| '"' : '\\"', |
| '\\': '\\\\' |
| }; |
| |
| function stringify(value, whitelist) { |
| var a, // The array holding the partial texts. |
| i, // The loop counter. |
| k, // The member key. |
| l, // Length. |
| r = /["\\\x00-\x1f\x7f-\x9f]/g, |
| v; // The member value. |
| |
| switch (typeof value) { |
| case '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 sequences. |
| |
| return r.test(value) ? |
| '"' + value.replace(r, function (a) { |
| var c = m[a]; |
| if (c) { |
| return c; |
| } |
| c = a.charCodeAt(); |
| return '\\u00' + Math.floor(c / 16).toString(16) + |
| (c % 16).toString(16); |
| }) + '"' : |
| '"' + value + '"'; |
| |
| case 'number': |
| |
| // JSON numbers must be finite. Encode non-finite numbers as null. |
| |
| return isFinite(value) ? String(value) : 'null'; |
| |
| case 'boolean': |
| case 'null': |
| return String(value); |
| |
| case 'object': |
| |
| // Due to a specification blunder in ECMAScript, |
| // typeof null is 'object', so watch out for that case. |
| |
| if (!value) { |
| return 'null'; |
| } |
| |
| // If the object has a toJSON method, call it, and stringify the result. |
| |
| if (typeof value.toJSON === 'function') { |
| return stringify(value.toJSON()); |
| } |
| a = []; |
| if (typeof value.length === 'number' && |
| !(value.propertyIsEnumerable('length'))) { |
| |
| // The object is an array. Stringify every element. Use null as a placeholder |
| // for non-JSON values. |
| |
| l = value.length; |
| for (i = 0; i < l; i += 1) { |
| a.push(stringify(value[i], whitelist) || 'null'); |
| } |
| |
| // Join all of the elements together and wrap them in brackets. |
| |
| return '[' + a.join(',') + ']'; |
| } |
| if (whitelist) { |
| |
| // If a whitelist (array of keys) is provided, use it to select the components |
| // of the object. |
| |
| l = whitelist.length; |
| for (i = 0; i < l; i += 1) { |
| k = whitelist[i]; |
| if (typeof k === 'string') { |
| v = stringify(value[k], whitelist); |
| if (v) { |
| a.push(stringify(k) + ':' + v); |
| } |
| } |
| } |
| } else { |
| |
| // Otherwise, iterate through all of the keys in the object. |
| |
| for (k in value) { |
| if (typeof k === 'string') { |
| v = stringify(value[k], whitelist); |
| if (v) { |
| a.push(stringify(k) + ':' + v); |
| } |
| } |
| } |
| } |
| |
| // Join all of the member texts together and wrap them in braces. |
| |
| return '{' + a.join(',') + '}'; |
| } |
| return undefined; |
| } |
| |
| return { |
| stringify: stringify, |
| parse: function (text, filter) { |
| var j; |
| |
| function walk(k, v) { |
| var i, n; |
| if (v && typeof v === 'object') { |
| for (i in v) { |
| if (Object.prototype.hasOwnProperty.apply(v, [i])) { |
| n = walk(i, v[i]); |
| if (n !== undefined) { |
| v[i] = n; |
| } |
| } |
| } |
| } |
| return filter(k, v); |
| } |
| |
| |
| // Parsing happens in three stages. In the first 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 first stage into 4 regexp operations in order to work around |
| // crippling inefficiencies in IE's and Safari's regexp engines. First we |
| // replace all 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(/\\./g, '@'). |
| replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']'). |
| replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { |
| |
| // In the second 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 third stage, we recursively walk the new structure, passing |
| // each name/value pair to a filter function for possible transformation. |
| |
| return typeof filter === 'function' ? walk('', j) : j; |
| } |
| |
| // If the text is not JSON parseable, then a SyntaxError is thrown. |
| |
| throw new SyntaxError('parseJSON'); |
| } |
| }; |
| }(); |
| } |
| |
| |
| //----------------------------------------------------------------------------- |
| test(); |
| //----------------------------------------------------------------------------- |
| |
| jit(false); |
| |
| function test() |
| { |
| enterFunc ('test'); |
| printBugNumber(BUGNUMBER); |
| printStatus (summary); |
| |
| |
| var testPairs = [ |
| ["{}", {}], |
| ["[]", []], |
| ['{"foo":"bar"}', {"foo":"bar"}], |
| ['{"null":null}', {"null":null}], |
| ['{"five":5}', {"five":5}], |
| ] |
| |
| var a = []; |
| for (var i=0; i < testPairs.length; i++) { |
| var pair = testPairs[i]; |
| var s = emulatedJSON.stringify(pair[1]) |
| a[i] = s; |
| } |
| print(a.join("\n")); |
| |
| reportCompare(expect, actual, summary); |
| |
| exitFunc ('test'); |
| } |
| |