1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
* License, v. 2.0. If a copy of the MPL was not distributed with this
4
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
//-----------------------------------------------------------------------------
7
var BUGNUMBER = 450369;
8
var summary = 'Crash with JIT and json2.js';
9
var actual = 'No Crash';
10
var expect = 'No Crash';
20
See http://www.JSON.org/js.html
22
This file creates a global JSON object containing two methods:
24
JSON.stringify(value, whitelist)
25
value any JavaScript value, usually an object or array.
27
whitelist an optional that determines how object values are
30
This method produces a JSON text from a JavaScript value.
31
There are three possible ways to stringify an object, depending
32
on the optional whitelist parameter.
34
If an object has a toJSON method, then the toJSON() method will be
35
called. The value returned from the toJSON method will be
38
Otherwise, if the optional whitelist parameter is an array, then
39
the elements of the array will be used to select members of the
40
object for stringification.
42
Otherwise, if there is no whitelist parameter, then all of the
43
members of the object will be stringified.
45
Values that do not have JSON representaions, such as undefined or
46
functions, will not be serialized. Such values in objects will be
47
dropped, in arrays will be replaced with null. JSON.stringify()
48
returns undefined. Dates will be stringified as quoted ISO dates.
52
var text = JSON.stringify(['e', {pluribus: 'unum'}]);
53
// text is '["e",{"pluribus":"unum"}]'
55
JSON.parse(text, filter)
56
This method parses a JSON text to produce an object or
57
array. It can throw a SyntaxError exception.
59
The optional filter parameter is a function that can filter and
60
transform the results. It receives each of the keys and values, and
61
its return value is used instead of the original value. If it
62
returns what it received, then structure is not modified. If it
63
returns undefined then the member is deleted.
67
// Parse the text. If a key contains the string 'date' then
68
// convert the value to a date.
70
myData = JSON.parse(text, function (key, value) {
71
return key.indexOf('date') >= 0 ? new Date(value) : value;
74
This is a reference implementation. You are free to copy, modify, or
77
Use your own copy. It is extremely unwise to load third party
81
/*jslint evil: true */
84
if (!this.emulatedJSON) {
86
emulatedJSON = function () {
88
function f(n) { // Format integers to have at least two digits.
89
return n < 10 ? '0' + n : n;
92
Date.prototype.toJSON = function () {
94
// Eventually, this method will be based on the date.toISOString method.
96
return this.getUTCFullYear() + '-' +
97
f(this.getUTCMonth() + 1) + '-' +
98
f(this.getUTCDate()) + 'T' +
99
f(this.getUTCHours()) + ':' +
100
f(this.getUTCMinutes()) + ':' +
101
f(this.getUTCSeconds()) + 'Z';
105
var m = { // table of character substitutions
115
function stringify(value, whitelist) {
116
var a, // The array holding the partial texts.
117
i, // The loop counter.
118
k, // The member key.
120
r = /["\\\x00-\x1f\x7f-\x9f]/g,
121
v; // The member value.
123
switch (typeof value) {
126
// If the string contains no control characters, no quote characters, and no
127
// backslash characters, then we can safely slap some quotes around it.
128
// Otherwise we must also replace the offending characters with safe sequences.
130
return r.test(value) ?
131
'"' + value.replace(r, function (a) {
137
return '\\u00' + Math.floor(c / 16).toString(16) +
138
(c % 16).toString(16);
144
// JSON numbers must be finite. Encode non-finite numbers as null.
146
return isFinite(value) ? String(value) : 'null';
150
return String(value);
154
// Due to a specification blunder in ECMAScript,
155
// typeof null is 'object', so watch out for that case.
161
// If the object has a toJSON method, call it, and stringify the result.
163
if (typeof value.toJSON === 'function') {
164
return stringify(value.toJSON());
167
if (typeof value.length === 'number' &&
168
!(value.propertyIsEnumerable('length'))) {
170
// The object is an array. Stringify every element. Use null as a placeholder
171
// for non-JSON values.
174
for (i = 0; i < l; i += 1) {
175
a.push(stringify(value[i], whitelist) || 'null');
178
// Join all of the elements together and wrap them in brackets.
180
return '[' + a.join(',') + ']';
184
// If a whitelist (array of keys) is provided, use it to select the components
187
l = whitelist.length;
188
for (i = 0; i < l; i += 1) {
190
if (typeof k === 'string') {
191
v = stringify(value[k], whitelist);
193
a.push(stringify(k) + ':' + v);
199
// Otherwise, iterate through all of the keys in the object.
202
if (typeof k === 'string') {
203
v = stringify(value[k], whitelist);
205
a.push(stringify(k) + ':' + v);
211
// Join all of the member texts together and wrap them in braces.
213
return '{' + a.join(',') + '}';
219
stringify: stringify,
220
parse: function (text, filter) {
223
function walk(k, v) {
225
if (v && typeof v === 'object') {
227
if (Object.prototype.hasOwnProperty.apply(v, [i])) {
229
if (n !== undefined) {
239
// Parsing happens in three stages. In the first stage, we run the text against
240
// regular expressions that look for non-JSON patterns. We are especially
241
// concerned with '()' and 'new' because they can cause invocation, and '='
242
// because it can cause mutation. But just to be safe, we want to reject all
245
// We split the first stage into 4 regexp operations in order to work around
246
// crippling inefficiencies in IE's and Safari's regexp engines. First we
247
// replace all backslash pairs with '@' (a non-JSON character). Second, we
248
// replace all simple value tokens with ']' characters. Third, we delete all
249
// open brackets that follow a colon or comma or that begin the text. Finally,
250
// we look to see that the remaining characters are only whitespace or ']' or
251
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
253
if (/^[\],:{}\s]*$/.test(text.replace(/\\./g, '@').
254
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']').
255
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
257
// In the second stage we use the eval function to compile the text into a
258
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
259
// in JavaScript: it can begin a block or an object literal. We wrap the text
260
// in parens to eliminate the ambiguity.
262
j = eval('(' + text + ')');
264
// In the optional third stage, we recursively walk the new structure, passing
265
// each name/value pair to a filter function for possible transformation.
267
return typeof filter === 'function' ? walk('', j) : j;
270
// If the text is not JSON parseable, then a SyntaxError is thrown.
272
throw new SyntaxError('parseJSON');
279
//-----------------------------------------------------------------------------
281
//-----------------------------------------------------------------------------
288
printBugNumber(BUGNUMBER);
289
printStatus (summary);
295
['{"foo":"bar"}', {"foo":"bar"}],
296
['{"null":null}', {"null":null}],
297
['{"five":5}', {"five":5}],
301
for (var i=0; i < testPairs.length; i++) {
302
var pair = testPairs[i];
303
var s = emulatedJSON.stringify(pair[1])
308
reportCompare(expect, actual, summary);