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