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

Side by Side Diff: src/json.js

Issue 11315009: Handle edge cases in basic JSON.stringify. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased Created 8 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/json-stringifier.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 return %_ValueOf(value) ? "true" : "false"; 171 return %_ValueOf(value) ? "true" : "false";
172 } else { 172 } else {
173 return SerializeObject(value, replacer, stack, indent, gap); 173 return SerializeObject(value, replacer, stack, indent, gap);
174 } 174 }
175 } 175 }
176 // Undefined or a callable object. 176 // Undefined or a callable object.
177 return void 0; 177 return void 0;
178 } 178 }
179 179
180 180
181 function BasicSerializeArray(value, stack, builder) {
182 var len = value.length;
183 if (len == 0) {
184 builder.push("[]");
185 return;
186 }
187 if (!%PushIfAbsent(stack, value)) {
188 throw MakeTypeError('circular_structure', $Array());
189 }
190 builder.push("[");
191 var val = value[0];
192 if (IS_STRING(val)) {
193 // First entry is a string. Remaining entries are likely to be strings too.
194 var array_string = %QuoteJSONStringArray(value);
195 if (!IS_UNDEFINED(array_string)) {
196 // array_string also includes bracket characters so we are done.
197 builder[builder.length - 1] = array_string;
198 stack.pop();
199 return;
200 } else {
201 builder.push(%QuoteJSONString(val));
202 for (var i = 1; i < len; i++) {
203 val = value[i];
204 if (IS_STRING(val)) {
205 builder.push(%QuoteJSONStringComma(val));
206 } else {
207 builder.push(",");
208 var before = builder.length;
209 BasicJSONSerialize(i, val, stack, builder);
210 if (before == builder.length) builder[before - 1] = ",null";
211 }
212 }
213 }
214 } else if (IS_NUMBER(val)) {
215 // First entry is a number. Remaining entries are likely to be numbers too.
216 builder.push(JSON_NUMBER_TO_STRING(val));
217 for (var i = 1; i < len; i++) {
218 builder.push(",");
219 val = value[i];
220 if (IS_NUMBER(val)) {
221 builder.push(JSON_NUMBER_TO_STRING(val));
222 } else {
223 var before = builder.length;
224 BasicJSONSerialize(i, val, stack, builder);
225 if (before == builder.length) builder[before - 1] = ",null";
226 }
227 }
228 } else {
229 var before = builder.length;
230 BasicJSONSerialize(0, val, stack, builder);
231 if (before == builder.length) builder.push("null");
232 for (var i = 1; i < len; i++) {
233 builder.push(",");
234 before = builder.length;
235 BasicJSONSerialize(i, value[i], stack, builder);
236 if (before == builder.length) builder[before - 1] = ",null";
237 }
238 }
239 stack.pop();
240 builder.push("]");
241 }
242
243
244 function BasicSerializeObject(value, stack, builder) {
245 if (!%PushIfAbsent(stack, value)) {
246 throw MakeTypeError('circular_structure', $Array());
247 }
248 builder.push("{");
249 var first = true;
250 var keys = %ObjectKeys(value);
251 var len = keys.length;
252 for (var i = 0; i < len; i++) {
253 var p = keys[i];
254 if (!first) {
255 builder.push(%QuoteJSONStringComma(p));
256 } else {
257 builder.push(%QuoteJSONString(p));
258 }
259 builder.push(":");
260 var before = builder.length;
261 BasicJSONSerialize(p, value[p], stack, builder);
262 if (before == builder.length) {
263 builder.pop();
264 builder.pop();
265 } else {
266 first = false;
267 }
268 }
269 stack.pop();
270 builder.push("}");
271 }
272
273
274 function BasicJSONSerialize(key, value, stack, builder) {
275 if (IS_SPEC_OBJECT(value)) {
276 var toJSON = value.toJSON;
277 if (IS_SPEC_FUNCTION(toJSON)) {
278 value = %_CallFunction(value, ToString(key), toJSON);
279 }
280 }
281 if (IS_STRING(value)) {
282 builder.push(value !== "" ? %QuoteJSONString(value) : '""');
283 } else if (IS_NUMBER(value)) {
284 builder.push(JSON_NUMBER_TO_STRING(value));
285 } else if (IS_BOOLEAN(value)) {
286 builder.push(value ? "true" : "false");
287 } else if (IS_NULL(value)) {
288 builder.push("null");
289 } else if (IS_SPEC_OBJECT(value) && !(typeof value == "function")) {
290 // Value is a non-callable object.
291 // Unwrap value if necessary
292 if (IS_NUMBER_WRAPPER(value)) {
293 value = ToNumber(value);
294 builder.push(JSON_NUMBER_TO_STRING(value));
295 } else if (IS_STRING_WRAPPER(value)) {
296 builder.push(%QuoteJSONString(ToString(value)));
297 } else if (IS_BOOLEAN_WRAPPER(value)) {
298 builder.push(%_ValueOf(value) ? "true" : "false");
299 } else if (IS_ARRAY(value)) {
300 BasicSerializeArray(value, stack, builder);
301 } else {
302 BasicSerializeObject(value, stack, builder);
303 }
304 }
305 }
306
307
308 function JSONStringify(value, replacer, space) { 181 function JSONStringify(value, replacer, space) {
309 if (%_ArgumentsLength() == 1) { 182 if (%_ArgumentsLength() == 1) {
310 var result = %BasicJSONStringify(value); 183 return %BasicJSONStringify(value);
311 if (result != 0) return result;
312 var builder = new InternalArray();
313 BasicJSONSerialize('', value, new InternalArray(), builder);
314 if (builder.length == 0) return;
315 result = %_FastAsciiArrayJoin(builder, "");
316 if (!IS_UNDEFINED(result)) return result;
317 return %StringBuilderConcat(builder, builder.length, "");
318 } 184 }
319 if (IS_OBJECT(space)) { 185 if (IS_OBJECT(space)) {
320 // Unwrap 'space' if it is wrapped 186 // Unwrap 'space' if it is wrapped
321 if (IS_NUMBER_WRAPPER(space)) { 187 if (IS_NUMBER_WRAPPER(space)) {
322 space = ToNumber(space); 188 space = ToNumber(space);
323 } else if (IS_STRING_WRAPPER(space)) { 189 } else if (IS_STRING_WRAPPER(space)) {
324 space = ToString(space); 190 space = ToString(space);
325 } 191 }
326 } 192 }
327 var gap; 193 var gap;
328 if (IS_NUMBER(space)) { 194 if (IS_NUMBER(space)) {
329 space = MathMax(0, MathMin(ToInteger(space), 10)); 195 space = MathMax(0, MathMin(ToInteger(space), 10));
330 gap = SubString(" ", 0, space); 196 gap = SubString(" ", 0, space);
331 } else if (IS_STRING(space)) { 197 } else if (IS_STRING(space)) {
332 if (space.length > 10) { 198 if (space.length > 10) {
333 gap = SubString(space, 0, 10); 199 gap = SubString(space, 0, 10);
334 } else { 200 } else {
335 gap = space; 201 gap = space;
336 } 202 }
337 } else { 203 } else {
338 gap = ""; 204 gap = "";
339 } 205 }
340 return JSONSerialize('', {'': value}, replacer, new InternalArray(), "", gap); 206 return JSONSerialize('', {'': value}, replacer, new InternalArray(), "", gap);
341 } 207 }
342 208
209
343 function SetUpJSON() { 210 function SetUpJSON() {
344 %CheckIsBootstrapping(); 211 %CheckIsBootstrapping();
345 InstallFunctions($JSON, DONT_ENUM, $Array( 212 InstallFunctions($JSON, DONT_ENUM, $Array(
346 "parse", JSONParse, 213 "parse", JSONParse,
347 "stringify", JSONStringify 214 "stringify", JSONStringify
348 )); 215 ));
349 } 216 }
350 217
351 SetUpJSON(); 218 SetUpJSON();
OLDNEW
« no previous file with comments | « no previous file | src/json-stringifier.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698