OLD | NEW |
(Empty) | |
| 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| 2 /* ***** BEGIN LICENSE BLOCK ***** |
| 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 4 * |
| 5 * The contents of this file are subject to the Mozilla Public License Version |
| 6 * 1.1 (the "License"); you may not use this file except in compliance with |
| 7 * the License. You may obtain a copy of the License at |
| 8 * http://www.mozilla.org/MPL/ |
| 9 * |
| 10 * Software distributed under the License is distributed on an "AS IS" basis, |
| 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 12 * for the specific language governing rights and limitations under the |
| 13 * License. |
| 14 * |
| 15 * The Original Code is JavaScript Engine testing utilities. |
| 16 * |
| 17 * The Initial Developer of the Original Code is |
| 18 * Mozilla Foundation. |
| 19 * Portions created by the Initial Developer are Copyright (C) 2008 |
| 20 * the Initial Developer. All Rights Reserved. |
| 21 * |
| 22 * Contributor(s): |
| 23 * |
| 24 * Alternatively, the contents of this file may be used under the terms of |
| 25 * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 27 * in which case the provisions of the GPL or the LGPL are applicable instead |
| 28 * of those above. If you wish to allow use of your version of this file only |
| 29 * under the terms of either the GPL or the LGPL, and not to allow others to |
| 30 * use your version of this file under the terms of the MPL, indicate your |
| 31 * decision by deleting the provisions above and replace them with the notice |
| 32 * and other provisions required by the GPL or the LGPL. If you do not delete |
| 33 * the provisions above, a recipient may use your version of this file under |
| 34 * the terms of any one of the MPL, the GPL or the LGPL. |
| 35 * |
| 36 * ***** END LICENSE BLOCK ***** */ |
| 37 |
| 38 var gTestfile = 'regress-450369.js'; |
| 39 //----------------------------------------------------------------------------- |
| 40 var BUGNUMBER = 450369; |
| 41 var summary = 'Crash with JIT and json2.js'; |
| 42 var actual = 'No Crash'; |
| 43 var expect = 'No Crash'; |
| 44 |
| 45 jit(true); |
| 46 |
| 47 /* |
| 48 json2.js |
| 49 2007-11-06 |
| 50 |
| 51 Public Domain |
| 52 |
| 53 See http://www.JSON.org/js.html |
| 54 |
| 55 This file creates a global JSON object containing two methods: |
| 56 |
| 57 JSON.stringify(value, whitelist) |
| 58 value any JavaScript value, usually an object or array. |
| 59 |
| 60 whitelist an optional that determines how object values are |
| 61 stringified. |
| 62 |
| 63 This method produces a JSON text from a JavaScript value. |
| 64 There are three possible ways to stringify an object, depending |
| 65 on the optional whitelist parameter. |
| 66 |
| 67 If an object has a toJSON method, then the toJSON() method will be |
| 68 called. The value returned from the toJSON method will be |
| 69 stringified. |
| 70 |
| 71 Otherwise, if the optional whitelist parameter is an array, then |
| 72 the elements of the array will be used to select members of the |
| 73 object for stringification. |
| 74 |
| 75 Otherwise, if there is no whitelist parameter, then all of the |
| 76 members of the object will be stringified. |
| 77 |
| 78 Values that do not have JSON representaions, such as undefined or |
| 79 functions, will not be serialized. Such values in objects will be |
| 80 dropped, in arrays will be replaced with null. JSON.stringify() |
| 81 returns undefined. Dates will be stringified as quoted ISO dates. |
| 82 |
| 83 Example: |
| 84 |
| 85 var text = JSON.stringify(['e', {pluribus: 'unum'}]); |
| 86 // text is '["e",{"pluribus":"unum"}]' |
| 87 |
| 88 JSON.parse(text, filter) |
| 89 This method parses a JSON text to produce an object or |
| 90 array. It can throw a SyntaxError exception. |
| 91 |
| 92 The optional filter parameter is a function that can filter and |
| 93 transform the results. It receives each of the keys and values, and |
| 94 its return value is used instead of the original value. If it |
| 95 returns what it received, then structure is not modified. If it |
| 96 returns undefined then the member is deleted. |
| 97 |
| 98 Example: |
| 99 |
| 100 // Parse the text. If a key contains the string 'date' then |
| 101 // convert the value to a date. |
| 102 |
| 103 myData = JSON.parse(text, function (key, value) { |
| 104 return key.indexOf('date') >= 0 ? new Date(value) : value; |
| 105 }); |
| 106 |
| 107 This is a reference implementation. You are free to copy, modify, or |
| 108 redistribute. |
| 109 |
| 110 Use your own copy. It is extremely unwise to load third party |
| 111 code into your pages. |
| 112 */ |
| 113 |
| 114 /*jslint evil: true */ |
| 115 /*extern JSON */ |
| 116 |
| 117 if (!this.emulatedJSON) { |
| 118 |
| 119 emulatedJSON = function () { |
| 120 |
| 121 function f(n) { // Format integers to have at least two digits. |
| 122 return n < 10 ? '0' + n : n; |
| 123 } |
| 124 |
| 125 Date.prototype.toJSON = function () { |
| 126 |
| 127 // Eventually, this method will be based on the date.toISOString method. |
| 128 |
| 129 return this.getUTCFullYear() + '-' + |
| 130 f(this.getUTCMonth() + 1) + '-' + |
| 131 f(this.getUTCDate()) + 'T' + |
| 132 f(this.getUTCHours()) + ':' + |
| 133 f(this.getUTCMinutes()) + ':' + |
| 134 f(this.getUTCSeconds()) + 'Z'; |
| 135 }; |
| 136 |
| 137 |
| 138 var m = { // table of character substitutions |
| 139 '\b': '\\b', |
| 140 '\t': '\\t', |
| 141 '\n': '\\n', |
| 142 '\f': '\\f', |
| 143 '\r': '\\r', |
| 144 '"' : '\\"', |
| 145 '\\': '\\\\' |
| 146 }; |
| 147 |
| 148 function stringify(value, whitelist) { |
| 149 var a, // The array holding the partial texts. |
| 150 i, // The loop counter. |
| 151 k, // The member key. |
| 152 l, // Length. |
| 153 r = /["\\\x00-\x1f\x7f-\x9f]/g, |
| 154 v; // The member value. |
| 155 |
| 156 switch (typeof value) { |
| 157 case 'string': |
| 158 |
| 159 // If the string contains no control characters, no quote characters, and no |
| 160 // backslash characters, then we can safely slap some quotes around it. |
| 161 // Otherwise we must also replace the offending characters with safe sequences. |
| 162 |
| 163 return r.test(value) ? |
| 164 '"' + value.replace(r, function (a) { |
| 165 var c = m[a]; |
| 166 if (c) { |
| 167 return c; |
| 168 } |
| 169 c = a.charCodeAt(); |
| 170 return '\\u00' + Math.floor(c / 16).toString(16) + |
| 171 (c % 16).toString(16); |
| 172 }) + '"' : |
| 173 '"' + value + '"'; |
| 174 |
| 175 case 'number': |
| 176 |
| 177 // JSON numbers must be finite. Encode non-finite numbers as null. |
| 178 |
| 179 return isFinite(value) ? String(value) : 'null'; |
| 180 |
| 181 case 'boolean': |
| 182 case 'null': |
| 183 return String(value); |
| 184 |
| 185 case 'object': |
| 186 |
| 187 // Due to a specification blunder in ECMAScript, |
| 188 // typeof null is 'object', so watch out for that case. |
| 189 |
| 190 if (!value) { |
| 191 return 'null'; |
| 192 } |
| 193 |
| 194 // If the object has a toJSON method, call it, and stringify the result. |
| 195 |
| 196 if (typeof value.toJSON === 'function') { |
| 197 return stringify(value.toJSON()); |
| 198 } |
| 199 a = []; |
| 200 if (typeof value.length === 'number' && |
| 201 !(value.propertyIsEnumerable('length'))) { |
| 202 |
| 203 // The object is an array. Stringify every element. Use null as a placeholder |
| 204 // for non-JSON values. |
| 205 |
| 206 l = value.length; |
| 207 for (i = 0; i < l; i += 1) { |
| 208 a.push(stringify(value[i], whitelist) || 'null'); |
| 209 } |
| 210 |
| 211 // Join all of the elements together and wrap them in brackets. |
| 212 |
| 213 return '[' + a.join(',') + ']'; |
| 214 } |
| 215 if (whitelist) { |
| 216 |
| 217 // If a whitelist (array of keys) is provided, use it to select the components |
| 218 // of the object. |
| 219 |
| 220 l = whitelist.length; |
| 221 for (i = 0; i < l; i += 1) { |
| 222 k = whitelist[i]; |
| 223 if (typeof k === 'string') { |
| 224 v = stringify(value[k], whitelist); |
| 225 if (v) { |
| 226 a.push(stringify(k) + ':' + v); |
| 227 } |
| 228 } |
| 229 } |
| 230 } else { |
| 231 |
| 232 // Otherwise, iterate through all of the keys in the object. |
| 233 |
| 234 for (k in value) { |
| 235 if (typeof k === 'string') { |
| 236 v = stringify(value[k], whitelist); |
| 237 if (v) { |
| 238 a.push(stringify(k) + ':' + v); |
| 239 } |
| 240 } |
| 241 } |
| 242 } |
| 243 |
| 244 // Join all of the member texts together and wrap them in braces. |
| 245 |
| 246 return '{' + a.join(',') + '}'; |
| 247 } |
| 248 return undefined; |
| 249 } |
| 250 |
| 251 return { |
| 252 stringify: stringify, |
| 253 parse: function (text, filter) { |
| 254 var j; |
| 255 |
| 256 function walk(k, v) { |
| 257 var i, n; |
| 258 if (v && typeof v === 'object') { |
| 259 for (i in v) { |
| 260 if (Object.prototype.hasOwnProperty.apply(v, [i])) { |
| 261 n = walk(i, v[i]); |
| 262 if (n !== undefined) { |
| 263 v[i] = n; |
| 264 } |
| 265 } |
| 266 } |
| 267 } |
| 268 return filter(k, v); |
| 269 } |
| 270 |
| 271 |
| 272 // Parsing happens in three stages. In the first stage, we run the text against |
| 273 // regular expressions that look for non-JSON patterns. We are especially |
| 274 // concerned with '()' and 'new' because they can cause invocation, and '=' |
| 275 // because it can cause mutation. But just to be safe, we want to reject all |
| 276 // unexpected forms. |
| 277 |
| 278 // We split the first stage into 4 regexp operations in order to work around |
| 279 // crippling inefficiencies in IE's and Safari's regexp engines. First we |
| 280 // replace all backslash pairs with '@' (a non-JSON character). Second, we |
| 281 // replace all simple value tokens with ']' characters. Third, we delete all |
| 282 // open brackets that follow a colon or comma or that begin the text. Finally, |
| 283 // we look to see that the remaining characters are only whitespace or ']' or |
| 284 // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. |
| 285 |
| 286 if (/^[\],:{}\s]*$/.test(text.replace(/\\./g, '@'). |
| 287 replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']')
. |
| 288 replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { |
| 289 |
| 290 // In the second stage we use the eval function to compile the text into a |
| 291 // JavaScript structure. The '{' operator is subject to a syntactic ambiguity |
| 292 // in JavaScript: it can begin a block or an object literal. We wrap the text |
| 293 // in parens to eliminate the ambiguity. |
| 294 |
| 295 j = eval('(' + text + ')'); |
| 296 |
| 297 // In the optional third stage, we recursively walk the new structure, passing |
| 298 // each name/value pair to a filter function for possible transformation. |
| 299 |
| 300 return typeof filter === 'function' ? walk('', j) : j; |
| 301 } |
| 302 |
| 303 // If the text is not JSON parseable, then a SyntaxError is thrown. |
| 304 |
| 305 throw new SyntaxError('parseJSON'); |
| 306 } |
| 307 }; |
| 308 }(); |
| 309 } |
| 310 |
| 311 |
| 312 //----------------------------------------------------------------------------- |
| 313 test(); |
| 314 //----------------------------------------------------------------------------- |
| 315 |
| 316 jit(false); |
| 317 |
| 318 function test() |
| 319 { |
| 320 enterFunc ('test'); |
| 321 printBugNumber(BUGNUMBER); |
| 322 printStatus (summary); |
| 323 |
| 324 |
| 325 var testPairs = [ |
| 326 ["{}", {}], |
| 327 ["[]", []], |
| 328 ['{"foo":"bar"}', {"foo":"bar"}], |
| 329 ['{"null":null}', {"null":null}], |
| 330 ['{"five":5}', {"five":5}], |
| 331 ] |
| 332 |
| 333 var a = []; |
| 334 for (var i=0; i < testPairs.length; i++) { |
| 335 var pair = testPairs[i]; |
| 336 var s = emulatedJSON.stringify(pair[1]) |
| 337 a[i] = s; |
| 338 } |
| 339 print(a.join("\n")); |
| 340 |
| 341 reportCompare(expect, actual, summary); |
| 342 |
| 343 exitFunc ('test'); |
| 344 } |
| 345 |
OLD | NEW |