Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: src/json-delay.js

Issue 93066: Built-in JSON support (Closed)
Patch Set: Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 var $JSON = global.JSON;
29
30 function IsValidJSON(s) {
31 // All empty whitespace is not valid.
32 if (/^\s*$/.test(s))
33 return false;
34
35 // This is taken from http://www.json.org/json2.js which is released to the
36 // public domain.
37 // Changes: We dissallow \u2028 Line separator and \u2029 Paragraph separator
38 // inside strings. We also treat \u2028 and \u2029 as whitespace which they
39 // are in the RFC but IE and Safari does not match \s to these so we need to
40 // include them in the reg exps in all places where whitespace is allowed.
Lasse Reichstein 2009/04/23 15:28:49 Is this our comment? Since Irregexp does include
Christian Plesner Hansen 2009/04/24 08:11:22 Good point.
41
42 var backslashesRe = /\\["\\\/bfnrtu]/g;
43 var simpleValuesRe =
44 /"[^"\\\n\r\u2028\u2029\x00-\x1f\x7f-\x9f]*"|true|false|null|-?\d+(?:\.\d* )?(?:[eE][+\-]?\d+)?/g;
45 var openBracketsRe = /(?:^|:|,)(?:[\s\u2028\u2029]*\[)+/g;
46 var remainderRe = /^[\],:{}\s\u2028\u2029]*$/;
47
48 return remainderRe.test(s.replace(backslashesRe, '@').
49 replace(simpleValuesRe, ']').
50 replace(openBracketsRe, ''));
51 }
52
53 function ParseJSONUnfiltered(text) {
54 var s = $String(text);
55 if (IsValidJSON(s)) {
56 try {
57 return global.eval('(' + s + ')');
arv (Not doing code reviews) 2009/04/23 21:07:58 I hope this is just a temporary solution. This sol
Christian Plesner Hansen 2009/04/24 08:11:22 That's not the reason I'm adding it but more to ha
Christian Plesner Hansen 2009/04/24 13:41:11 Update: it turned out to be straightforward to mov
58 } catch (e) {
59 // ignore exceptions
60 }
61 }
62 throw MakeSyntaxError('invalid_json', [s]);
63 }
64
65 function Revive(holder, name, reviver) {
66 var val = holder[name];
67 if (IS_OBJECT(val)) {
68 if (IS_ARRAY(val)) {
69 var length = val.length;
70 for (var i = 0; i < length; i++) {
71 var newElement = Revive(val, $String(i), reviver);
72 val[i] = newElement;
73 }
74 } else {
75 for (var p in val) {
76 if (ObjectHasOwnProperty.call(val, p)) {
77 var newElement = Revive(val, p, reviver);
78 if (IS_UNDEFINED(newElement)) {
79 delete val[p];
80 } else {
81 val[p] = newElement;
82 }
83 }
84 }
85 }
86 }
87 return reviver.call(holder, name, val);
88 }
89
90 function JSONParse(text, reviver) {
91 var unfiltered = ParseJSONUnfiltered(text);
92 if (IS_FUNCTION(reviver)) {
93 return Revive({'': unfiltered}, '', reviver);
94 } else {
95 return unfiltered;
96 }
97 }
98
99 var characterQuoteCache = {
100 '\"': '\\"',
101 '\\': '\\\\',
102 '/': '\\/',
103 '\b': '\\b',
104 '\f': '\\f',
105 '\n': '\\n',
106 '\r': '\\r',
107 '\t': '\\t',
108 '\x0B': '\\u000b'
109 };
110
111 function QuoteSingleJSONCharacter(c) {
112 if (c in characterQuoteCache)
113 return characterQuoteCache[c];
114 var charCode = c.charCodeAt(0);
115 var result;
116 if (charCode < 16) result = '\\u000';
117 else if (charCode < 256) result = '\\u00';
118 else if (charCode < 4096) result = '\\u0';
119 else result = '\\u';
120 result += charCode.toString(16);
121 characterQuoteCache[c] = result;
122 return result;
123 }
124
125 function QuoteJSONString(str) {
126 var quotable = /[\\\"\x00-\x1f\x80-\uffff]/g;
127 return '"' + str.replace(quotable, QuoteSingleJSONCharacter) + '"';
128 }
129
130 function StackContains(stack, val) {
131 var length = stack.length;
132 for (var i = 0; i < length; i++) {
133 if (stack[i] === val)
134 return true;
135 }
136 return false;
137 }
138
139 function SerializeArray(value, replacer, stack, indent, gap) {
140 if (StackContains(stack, value))
141 throw MakeTypeError('circular_structure', []);
142 stack.push(value);
143 var stepback = indent;
144 indent += gap;
145 var partial = [];
146 var len = value.length;
147 for (var i = 0; i < len; i++) {
148 var strP = JSONSerialize($String(i), value, replacer, stack,
149 indent, gap);
150 if (IS_UNDEFINED(strP))
151 strP = "null";
152 partial.push(strP);
153 }
154 var final;
155 if (gap == "") {
156 final = "[" + partial.join(",") + "]";
157 } else if (partial.length > 0) {
158 var separator = ",\n" + indent;
159 final = "[\n" + indent + partial.join(separator) + "\n" +
160 stepback + "]";
161 } else {
162 final = "[]";
163 }
164 stack.pop();
165 indent = stepback;
Lasse Reichstein 2009/04/23 15:28:49 indent is a local variable here, so setting it jus
Christian Plesner Hansen 2009/04/24 08:11:22 Good point. I was following the spec a bit too cl
166 return final;
167 }
168
169 function SerializeObject(value, replacer, stack, indent, gap) {
170 if (StackContains(stack, value))
171 throw MakeTypeError('circular_structure', []);
172 stack.push(value);
173 var stepback = indent;
174 indent += gap;
175 var partial = [];
176 if (IS_ARRAY(replacer)) {
177 var length = replacer.length;
178 for (var i = length - 1; i >= 0; i--) {
179 if (ObjectHasOwnProperty.call(replacer, i)) {
Lasse Reichstein 2009/04/23 15:28:49 The specification says that the properties of repl
Christian Plesner Hansen 2009/04/24 08:11:22 I got ascending and descending mixed up. Even tho
180 var p = replacer[i];
181 var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
182 if (!IS_UNDEFINED(strP)) {
183 var member = QuoteJSONString(p) + ":";
184 if (gap != "")
185 member += " ";
Lasse Reichstein 2009/04/23 15:28:49 Should be on previous line (or indented and put in
Christian Plesner Hansen 2009/04/24 08:11:22 Gah. But you're right.
186 member += strP;
187 partial.push(member);
188 }
189 }
190 }
191 } else {
192 for (var p in value) {
193 if (ObjectHasOwnProperty.call(value, p)) {
194 var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
195 if (!IS_UNDEFINED(strP)) {
196 var member = QuoteJSONString(p) + ":";
197 if (gap != "")
198 member += " ";
Mads Ager (chromium) 2009/04/23 19:09:25 Indentation.
199 member += strP;
200 partial.push(member);
201 }
202 }
203 }
204 }
205 var final;
206 if (gap == "") {
207 final = "{" + partial.join(",") + "}";
208 } else if (partial.length > 0) {
209 var separator = ",\n" + indent;
210 final = "{\n" + indent + partial.join(separator) + "\n" +
211 stepback + "}";
212 } else {
213 final = "{}";
214 }
215 stack.pop();
216 indent = stepback;
Lasse Reichstein 2009/04/23 15:28:49 Again unnecessary.
217 return final;
218 }
219
220 function JSONSerialize(key, holder, replacer, stack, indent, gap) {
221 var value = holder[key];
222 if (IS_OBJECT(value) && value) {
223 var toJSON = value.toJSON;
224 if (IS_FUNCTION(toJSON))
225 value = toJSON.call(value, key);
226 }
227 if (IS_FUNCTION(replacer))
228 value = replacer.call(holder, key, value);
229 // Unwrap value if necessary
230 if (IS_OBJECT(value)) {
231 if (IS_NUMBER_WRAPPER(value)) {
232 value = $Number(value);
233 } else if (IS_STRING_WRAPPER(value)) {
234 value = $String(value);
235 }
236 }
237 switch (typeof value) {
238 case "string":
239 return QuoteJSONString(value);
240 case "object":
241 if (!value) {
242 return "null";
243 } else if (IS_ARRAY(value)) {
244 return SerializeArray(value, replacer, stack, indent, gap);
245 } else {
246 return SerializeObject(value, replacer, stack, indent, gap);
247 }
248 case "number":
249 return $isFinite(value) ? $String(value) : "null";
250 case "boolean":
251 return value ? "true" : "false";
252 }
253 }
254
255 function JSONStringify(value, replacer, space) {
256 var stack = [];
257 var indent = "";
258 if (IS_OBJECT(space)) {
259 // Unwrap 'space' if it is wrapped
260 if (IS_NUMBER_WRAPPER(space)) {
261 space = $Number(space);
262 } else if (IS_STRING_WRAPPER(space)) {
263 space = $String(space);
264 }
265 }
266 var gap;
267 if (IS_NUMBER(space)) {
268 space = $Math.min(space, 100);
269 gap = "";
270 for (var i = 0; i < space; i++)
271 gap += " ";
272 } else if (IS_STRING(space)) {
273 gap = space;
274 } else {
275 gap = "";
276 }
277 return JSONSerialize('', {'': value}, replacer, stack, indent, gap);
278 }
279
280 function SetupJSON() {
281 InstallFunctions($JSON, DONT_ENUM, $Array(
282 "parse", JSONParse,
283 "stringify", JSONStringify
284 ));
285 }
286
287 SetupJSON();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698