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

Side by Side Diff: src/json-stringifier.h

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 | « src/json.js ('k') | test/mjsunit/json2.js » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 28 matching lines...) Expand all
39 public: 39 public:
40 explicit BasicJsonStringifier(Isolate* isolate); 40 explicit BasicJsonStringifier(Isolate* isolate);
41 41
42 MaybeObject* Stringify(Handle<Object> object); 42 MaybeObject* Stringify(Handle<Object> object);
43 43
44 private: 44 private:
45 static const int kInitialPartLength = 32; 45 static const int kInitialPartLength = 32;
46 static const int kMaxPartLength = 16 * 1024; 46 static const int kMaxPartLength = 16 * 1024;
47 static const int kPartLengthGrowthFactor = 2; 47 static const int kPartLengthGrowthFactor = 2;
48 48
49 enum Result { UNCHANGED, SUCCESS, BAILOUT, CIRCULAR, STACK_OVERFLOW }; 49 enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW };
50 50
51 template <bool is_ascii> void Extend(); 51 template <bool is_ascii> void Extend();
52 52
53 void ChangeEncoding(); 53 void ChangeEncoding();
54 54
55 void ShrinkCurrentPart(); 55 void ShrinkCurrentPart();
56 56
57 template <bool is_ascii, typename Char> 57 template <bool is_ascii, typename Char>
58 INLINE(void Append_(Char c)); 58 INLINE(void Append_(Char c));
59 59
(...skipping 12 matching lines...) Expand all
72 if (is_ascii_) { 72 if (is_ascii_) {
73 Append_<true>(chars); 73 Append_<true>(chars);
74 } else { 74 } else {
75 Append_<false>(chars); 75 Append_<false>(chars);
76 } 76 }
77 } 77 }
78 78
79 Handle<Object> GetProperty(Handle<JSObject> object, 79 Handle<Object> GetProperty(Handle<JSObject> object,
80 Handle<String> key); 80 Handle<String> key);
81 81
82 bool MayHaveToJsonFunction(Handle<JSObject> object); 82 Handle<Object> ApplyToJsonFunction(Handle<Object> object,
83 Handle<Object> key);
83 84
84 INLINE(Result Serialize(Handle<Object> object)) { 85 // Entry point to serialize the object.
85 return Serialize_<false>(object); 86 INLINE(Result SerializeObject(Handle<Object> obj)) {
87 return Serialize_<false>(obj, false, isolate_->factory()->empty_string());
86 } 88 }
87 89
88 INLINE(Result SerializeDeferred(Handle<Object> object, 90 // Serialize an array element.
89 bool deferred_comma, 91 // The index may serve as argument for the toJSON function.
90 Handle<String> deferred_key)) { 92 INLINE(Result SerializeElement(Handle<Object> object, int i)) {
93 return Serialize_<false>(object, false, Handle<Object>(Smi::FromInt(i)));
94 }
95
96 // Serialize a object property.
97 // The key may or may not be serialized depending on the property.
98 // The key may also serve as argument for the toJSON function.
99 INLINE(Result SerializeProperty(Handle<Object> object,
100 bool deferred_comma,
101 Handle<String> deferred_key)) {
91 ASSERT(!deferred_key.is_null()); 102 ASSERT(!deferred_key.is_null());
92 return Serialize_<true>(object, deferred_comma, deferred_key); 103 return Serialize_<true>(object, deferred_comma, deferred_key);
93 } 104 }
94 105
95 template <bool deferred_key> 106 template <bool deferred_string_key>
96 Result Serialize_(Handle<Object> object, 107 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key);
97 bool comma = false,
98 Handle<String> key = Handle<String>::null());
99 108
100 void SerializeDeferredKey(bool deferred_comma, Handle<String> deferred_key) { 109 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) {
101 if (deferred_comma) Append(','); 110 if (deferred_comma) Append(',');
102 SerializeString(deferred_key); 111 SerializeString(Handle<String>::cast(deferred_key));
103 Append(':'); 112 Append(':');
104 } 113 }
105 114
106 Result SerializeSmi(Smi* object); 115 Result SerializeSmi(Smi* object);
107 116
108 Result SerializeDouble(double number); 117 Result SerializeDouble(double number);
109 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { 118 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) {
110 return SerializeDouble(object->value()); 119 return SerializeDouble(object->value());
111 } 120 }
112 121
113 INLINE(Result SerializeArray(Handle<JSArray> object)); 122 Result SerializeJSValue(Handle<JSValue> object);
114 INLINE(Result SerializeObject(Handle<JSObject> object)); 123
124 INLINE(Result SerializeJSArray(Handle<JSArray> object));
125 INLINE(Result SerializeJSObject(Handle<JSObject> object));
126
127 Result SerializeJSArraySlow(Handle<JSArray> object, int length);
115 128
116 void SerializeString(Handle<String> object); 129 void SerializeString(Handle<String> object);
117 130
118 template <typename SrcChar, typename DestChar> 131 template <typename SrcChar, typename DestChar>
119 INLINE(void SerializeStringUnchecked_(const SrcChar* src, 132 INLINE(void SerializeStringUnchecked_(const SrcChar* src,
120 DestChar* dest, 133 DestChar* dest,
121 int length)); 134 int length));
122 135
123 template <bool is_ascii, typename Char> 136 template <bool is_ascii, typename Char>
124 INLINE(void SerializeString_(Vector<const Char> vector, 137 INLINE(void SerializeString_(Vector<const Char> vector,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 isolate_->factory()->ToObject(isolate_->factory()->empty_string())); 213 isolate_->factory()->ToObject(isolate_->factory()->empty_string()));
201 part_length_ = kInitialPartLength; 214 part_length_ = kInitialPartLength;
202 current_part_ = 215 current_part_ =
203 isolate_->factory()->NewRawAsciiString(kInitialPartLength); 216 isolate_->factory()->NewRawAsciiString(kInitialPartLength);
204 tojson_symbol_ = isolate_->factory()->LookupAsciiSymbol("toJSON"); 217 tojson_symbol_ = isolate_->factory()->LookupAsciiSymbol("toJSON");
205 stack_ = isolate_->factory()->NewJSArray(8); 218 stack_ = isolate_->factory()->NewJSArray(8);
206 } 219 }
207 220
208 221
209 MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) { 222 MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) {
210 switch (Serialize(object)) { 223 switch (SerializeObject(object)) {
224 case UNCHANGED:
225 return isolate_->heap()->undefined_value();
211 case SUCCESS: 226 case SUCCESS:
212 ShrinkCurrentPart(); 227 ShrinkCurrentPart();
213 return *isolate_->factory()->NewConsString(accumulator(), current_part_); 228 return *isolate_->factory()->NewConsString(accumulator(), current_part_);
214 case UNCHANGED:
215 return isolate_->heap()->undefined_value();
216 case CIRCULAR: 229 case CIRCULAR:
217 return isolate_->Throw(*isolate_->factory()->NewTypeError( 230 return isolate_->Throw(*isolate_->factory()->NewTypeError(
218 "circular_structure", HandleVector<Object>(NULL, 0))); 231 "circular_structure", HandleVector<Object>(NULL, 0)));
219 case STACK_OVERFLOW: 232 case STACK_OVERFLOW:
220 return isolate_->StackOverflow(); 233 return isolate_->StackOverflow();
221 default: 234 default:
222 return Smi::FromInt(0); 235 return Failure::Exception();
223 } 236 }
224 } 237 }
225 238
226 239
227 template <bool is_ascii, typename Char> 240 template <bool is_ascii, typename Char>
228 void BasicJsonStringifier::Append_(Char c) { 241 void BasicJsonStringifier::Append_(Char c) {
229 if (is_ascii) { 242 if (is_ascii) {
230 SeqAsciiString::cast(*current_part_)->SeqAsciiStringSet( 243 SeqAsciiString::cast(*current_part_)->SeqAsciiStringSet(
231 current_index_++, c); 244 current_index_++, c);
232 } else { 245 } else {
(...skipping 21 matching lines...) Expand all
254 ASSERT(!value->IsTheHole()); 267 ASSERT(!value->IsTheHole());
255 return Handle<Object>(value); 268 return Handle<Object>(value);
256 } 269 }
257 case FIELD: { 270 case FIELD: {
258 Object* value = lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); 271 Object* value = lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
259 ASSERT(!value->IsTheHole()); 272 ASSERT(!value->IsTheHole());
260 return Handle<Object>(value); 273 return Handle<Object>(value);
261 } 274 }
262 case CONSTANT_FUNCTION: 275 case CONSTANT_FUNCTION:
263 return Handle<Object>(lookup.GetConstantFunction()); 276 return Handle<Object>(lookup.GetConstantFunction());
264 case CALLBACKS: 277 default: {
265 case HANDLER: 278 PropertyAttributes attr;
266 case INTERCEPTOR: 279 return Object::GetProperty(object, object, &lookup, key, &attr);
267 return Handle<Object>::null(); 280 }
268 case TRANSITION:
269 case NONEXISTENT:
270 UNREACHABLE();
271 break;
272 } 281 }
273 return Handle<Object>::null(); 282 return Handle<Object>::null();
274 } 283 }
275 284
276 285
277 bool BasicJsonStringifier::MayHaveToJsonFunction(Handle<JSObject> object) { 286 Handle<Object> BasicJsonStringifier::ApplyToJsonFunction(
287 Handle<Object> object, Handle<Object> key) {
278 LookupResult lookup(isolate_); 288 LookupResult lookup(isolate_);
279 object->LookupRealNamedProperty(*tojson_symbol_, &lookup); 289 JSObject::cast(*object)->LookupRealNamedProperty(*tojson_symbol_, &lookup);
280 if (!lookup.IsProperty()) return false; 290 if (!lookup.IsProperty()) return object;
281 Object* value; 291 PropertyAttributes attr;
282 switch (lookup.type()) { 292 Handle<Object> fun =
283 case NORMAL: 293 Object::GetProperty(object, object, &lookup, tojson_symbol_, &attr);
284 value = lookup.holder()->GetNormalizedProperty(&lookup); 294 if (!fun->IsJSFunction()) return object;
285 break; 295
286 case FIELD: 296 // Call toJSON function.
287 value = lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); 297 if (key->IsSmi()) key = isolate_->factory()->NumberToString(key);
288 break; 298 Handle<Object> argv[] = { key };
289 default: 299 bool has_exception = false;
290 return true; 300 HandleScope scope(isolate_);
291 } 301 object = Execution::Call(fun, object, 1, argv, &has_exception);
292 ASSERT(!value->IsTheHole()); 302 // Return empty handle to signal an exception.
293 return value->IsSpecFunction(); 303 if (has_exception) return Handle<Object>::null();
304 return scope.CloseAndEscape(object);
294 } 305 }
295 306
296 307
297 BasicJsonStringifier::Result BasicJsonStringifier::StackPush( 308 BasicJsonStringifier::Result BasicJsonStringifier::StackPush(
298 Handle<Object> object) { 309 Handle<Object> object) {
299 StackLimitCheck check(isolate_); 310 StackLimitCheck check(isolate_);
300 if (check.HasOverflowed()) return STACK_OVERFLOW; 311 if (check.HasOverflowed()) return STACK_OVERFLOW;
301 312
302 int length = Smi::cast(stack_->length())->value(); 313 int length = Smi::cast(stack_->length())->value();
303 FixedArray* elements = FixedArray::cast(stack_->elements()); 314 FixedArray* elements = FixedArray::cast(stack_->elements());
304 for (int i = 0; i < length; i++) { 315 for (int i = 0; i < length; i++) {
305 if (elements->get(i) == *object) { 316 if (elements->get(i) == *object) {
306 return CIRCULAR; 317 return CIRCULAR;
307 } 318 }
308 } 319 }
309 stack_->EnsureSize(length + 1); 320 stack_->EnsureSize(length + 1);
310 FixedArray::cast(stack_->elements())->set(length, *object); 321 FixedArray::cast(stack_->elements())->set(length, *object);
311 stack_->set_length(Smi::FromInt(length + 1)); 322 stack_->set_length(Smi::FromInt(length + 1));
312 return SUCCESS; 323 return SUCCESS;
313 } 324 }
314 325
315 326
316 void BasicJsonStringifier::StackPop() { 327 void BasicJsonStringifier::StackPop() {
317 int length = Smi::cast(stack_->length())->value(); 328 int length = Smi::cast(stack_->length())->value();
318 stack_->set_length(Smi::FromInt(length - 1)); 329 stack_->set_length(Smi::FromInt(length - 1));
319 } 330 }
320 331
321 332
322 template <bool deferred_key> 333 template <bool deferred_string_key>
323 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_( 334 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_(
324 Handle<Object> object, bool comma, Handle<String> key) { 335 Handle<Object> object, bool comma, Handle<Object> key) {
325 if (object->IsJSObject()) { 336 if (object->IsJSObject()) {
326 // We don't deal with custom toJSON functions. 337 object = ApplyToJsonFunction(object, key);
327 if (MayHaveToJsonFunction(Handle<JSObject>::cast(object))) return BAILOUT; 338 if (object.is_null()) return EXCEPTION;
339 }
328 340
329 if (object->IsJSFunction()) { 341 if (object->IsJSObject()) {
330 return UNCHANGED; 342 if (object->IsJSFunction()) return UNCHANGED;
331 } else if (object->IsJSArray()) { 343 if (deferred_string_key) SerializeDeferredKey(comma, key);
332 if (deferred_key) SerializeDeferredKey(comma, key); 344 if (object->IsJSArray()) {
333 return SerializeArray(Handle<JSArray>::cast(object)); 345 return SerializeJSArray(Handle<JSArray>::cast(object));
334 } else if (object->IsJSValue()) { 346 } else if (object->IsJSValue()) {
335 // JSValue with a custom prototype. 347 return SerializeJSValue(Handle<JSValue>::cast(object));
336 if (object->GetPrototype()->IsJSReceiver()) return BAILOUT;
337 // Unpack value wrapper and fall through.
338 object = Handle<Object>(JSValue::cast(*object)->value());
339 } else { 348 } else {
340 if (deferred_key) SerializeDeferredKey(comma, key); 349 return SerializeJSObject(Handle<JSObject>::cast(object));
341 return SerializeObject(Handle<JSObject>::cast(object));
342 } 350 }
343 } 351 }
344 352
353 // Handle non-JSObject.
345 if (object->IsString()) { 354 if (object->IsString()) {
346 if (deferred_key) SerializeDeferredKey(comma, key); 355 if (deferred_string_key) SerializeDeferredKey(comma, key);
347 SerializeString(Handle<String>::cast(object)); 356 SerializeString(Handle<String>::cast(object));
348 return SUCCESS; 357 return SUCCESS;
349 } else if (object->IsSmi()) { 358 } else if (object->IsSmi()) {
350 if (deferred_key) SerializeDeferredKey(comma, key); 359 if (deferred_string_key) SerializeDeferredKey(comma, key);
351 return SerializeSmi(Smi::cast(*object)); 360 return SerializeSmi(Smi::cast(*object));
352 } else if (object->IsHeapNumber()) { 361 } else if (object->IsHeapNumber()) {
353 if (deferred_key) SerializeDeferredKey(comma, key); 362 if (deferred_string_key) SerializeDeferredKey(comma, key);
354 return SerializeHeapNumber(Handle<HeapNumber>::cast(object)); 363 return SerializeHeapNumber(Handle<HeapNumber>::cast(object));
355 } else if (object->IsOddball()) { 364 } else if (object->IsOddball()) {
356 switch (Oddball::cast(*object)->kind()) { 365 switch (Oddball::cast(*object)->kind()) {
357 case Oddball::kFalse: 366 case Oddball::kFalse:
358 if (deferred_key) SerializeDeferredKey(comma, key); 367 if (deferred_string_key) SerializeDeferredKey(comma, key);
359 Append("false"); 368 Append("false");
360 return SUCCESS; 369 return SUCCESS;
361 case Oddball::kTrue: 370 case Oddball::kTrue:
362 if (deferred_key) SerializeDeferredKey(comma, key); 371 if (deferred_string_key) SerializeDeferredKey(comma, key);
363 Append("true"); 372 Append("true");
364 return SUCCESS; 373 return SUCCESS;
365 case Oddball::kNull: 374 case Oddball::kNull:
366 if (deferred_key) SerializeDeferredKey(comma, key); 375 if (deferred_string_key) SerializeDeferredKey(comma, key);
367 Append("null"); 376 Append("null");
368 return SUCCESS; 377 return SUCCESS;
369 } 378 }
370 } 379 }
371 380
372 return UNCHANGED; 381 return UNCHANGED;
373 } 382 }
374 383
375 384
385 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue(
386 Handle<JSValue> object) {
387 bool has_exception = false;
388 String* class_name = object->class_name();
389 if (class_name == isolate_->heap()->String_symbol()) {
390 Handle<Object> value = Execution::ToString(object, &has_exception);
391 if (has_exception) return EXCEPTION;
392 SerializeString(Handle<String>::cast(value));
393 } else if (class_name == isolate_->heap()->Number_symbol()) {
394 Handle<Object> value = Execution::ToNumber(object, &has_exception);
395 if (has_exception) return EXCEPTION;
396 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value));
397 SerializeHeapNumber(Handle<HeapNumber>::cast(value));
398 } else {
399 ASSERT(class_name == isolate_->heap()->Boolean_symbol());
400 Object* value = JSValue::cast(*object)->value();
401 ASSERT(value->IsBoolean());
402 Append(value->IsTrue() ? "true" : "false");
403 }
404 return SUCCESS;
405 }
406
407
376 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { 408 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) {
377 static const int kBufferSize = 100; 409 static const int kBufferSize = 100;
378 char chars[kBufferSize]; 410 char chars[kBufferSize];
379 Vector<char> buffer(chars, kBufferSize); 411 Vector<char> buffer(chars, kBufferSize);
380 Append(IntToCString(object->value(), buffer)); 412 Append(IntToCString(object->value(), buffer));
381 return SUCCESS; 413 return SUCCESS;
382 } 414 }
383 415
384 416
385 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( 417 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble(
386 double number) { 418 double number) {
387 if (isinf(number) || isnan(number)) { 419 if (isinf(number) || isnan(number)) {
388 Append("null"); 420 Append("null");
389 return SUCCESS; 421 return SUCCESS;
390 } 422 }
391 static const int kBufferSize = 100; 423 static const int kBufferSize = 100;
392 char chars[kBufferSize]; 424 char chars[kBufferSize];
393 Vector<char> buffer(chars, kBufferSize); 425 Vector<char> buffer(chars, kBufferSize);
394 Append(DoubleToCString(number, buffer)); 426 Append(DoubleToCString(number, buffer));
395 return SUCCESS; 427 return SUCCESS;
396 } 428 }
397 429
398 430
399 BasicJsonStringifier::Result BasicJsonStringifier::SerializeArray( 431 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
400 Handle<JSArray> object) { 432 Handle<JSArray> object) {
401 HandleScope handle_scope(isolate_); 433 HandleScope handle_scope(isolate_);
402 Result stack_push = StackPush(object); 434 Result stack_push = StackPush(object);
403 if (stack_push != SUCCESS) return stack_push; 435 if (stack_push != SUCCESS) return stack_push;
404 int length = Smi::cast(object->length())->value(); 436 int length = Smi::cast(object->length())->value();
405 Append('['); 437 Append('[');
406 switch (object->GetElementsKind()) { 438 switch (object->GetElementsKind()) {
407 case FAST_SMI_ELEMENTS: { 439 case FAST_SMI_ELEMENTS: {
408 Handle<FixedArray> elements = Handle<FixedArray>( 440 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
409 FixedArray::cast(object->elements()));
410 for (int i = 0; i < length; i++) { 441 for (int i = 0; i < length; i++) {
411 if (i > 0) Append(','); 442 if (i > 0) Append(',');
412 SerializeSmi(Smi::cast(elements->get(i))); 443 SerializeSmi(Smi::cast(elements->get(i)));
413 } 444 }
414 break; 445 break;
415 } 446 }
416 case FAST_DOUBLE_ELEMENTS: { 447 case FAST_DOUBLE_ELEMENTS: {
417 Handle<FixedDoubleArray> elements = Handle<FixedDoubleArray>( 448 Handle<FixedDoubleArray> elements(
418 FixedDoubleArray::cast(object->elements())); 449 FixedDoubleArray::cast(object->elements()));
419 for (int i = 0; i < length; i++) { 450 for (int i = 0; i < length; i++) {
420 if (i > 0) Append(','); 451 if (i > 0) Append(',');
421 SerializeDouble(elements->get_scalar(i)); 452 SerializeDouble(elements->get_scalar(i));
422 } 453 }
423 break; 454 break;
424 } 455 }
425 case FAST_ELEMENTS: { 456 case FAST_ELEMENTS: {
426 Handle<FixedArray> elements = Handle<FixedArray>( 457 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
427 FixedArray::cast(object->elements()));
428 for (int i = 0; i < length; i++) { 458 for (int i = 0; i < length; i++) {
429 if (i > 0) Append(','); 459 if (i > 0) Append(',');
430 Result result = Serialize(Handle<Object>(elements->get(i))); 460 Result result = SerializeElement(Handle<Object>(elements->get(i)), i);
431 if (result == SUCCESS) continue; 461 if (result == SUCCESS) continue;
432 if (result == UNCHANGED) { 462 if (result == UNCHANGED) {
433 Append("null"); 463 Append("null");
434 } else { 464 } else {
435 return result; 465 return result;
436 } 466 }
437 } 467 }
438 break; 468 break;
439 } 469 }
440 default: 470 // TODO(yangguo): The FAST_HOLEY_* cases could be handled in a faster way.
441 return BAILOUT; 471 // They resemble the non-holey cases except that a prototype chain lookup
472 // is necessary for holes.
473 default: {
474 Result result = SerializeJSArraySlow(object, length);
475 if (result != SUCCESS) return result;
476 break;
477 }
442 } 478 }
443 Append(']'); 479 Append(']');
444 StackPop(); 480 StackPop();
445 current_part_ = handle_scope.CloseAndEscape(current_part_); 481 current_part_ = handle_scope.CloseAndEscape(current_part_);
446 return SUCCESS; 482 return SUCCESS;
447 } 483 }
448 484
449 485
450 BasicJsonStringifier::Result BasicJsonStringifier::SerializeObject( 486 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow(
487 Handle<JSArray> object, int length) {
488 for (int i = 0; i < length; i++) {
489 if (i > 0) Append(',');
490 Handle<Object> element = Object::GetElement(object, i);
491 if (element->IsUndefined()) {
492 Append("null");
493 } else {
494 Result result = SerializeElement(element, i);
495 if (result == SUCCESS) continue;
496 if (result == UNCHANGED) {
497 Append("null");
498 } else {
499 return result;
500 }
501 }
502 }
503 return SUCCESS;
504 }
505
506
507 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
451 Handle<JSObject> object) { 508 Handle<JSObject> object) {
452 HandleScope handle_scope(isolate_); 509 HandleScope handle_scope(isolate_);
453 Result stack_push = StackPush(object); 510 Result stack_push = StackPush(object);
454 if (stack_push != SUCCESS) return stack_push; 511 if (stack_push != SUCCESS) return stack_push;
455 if (object->IsJSGlobalProxy()) return BAILOUT; 512 if (object->IsJSGlobalProxy()) {
456 bool threw = false; 513 object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
514 ASSERT(object->IsGlobalObject());
515 }
516 bool has_exception = false;
457 Handle<FixedArray> contents = 517 Handle<FixedArray> contents =
458 GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw); 518 GetKeysInFixedArrayFor(object, LOCAL_ONLY, &has_exception);
459 if (threw) return BAILOUT; 519 if (has_exception) return EXCEPTION;
460 Append('{'); 520 Append('{');
461 bool comma = false; 521 bool comma = false;
462 for (int i = 0; i < contents->length(); i++) { 522 for (int i = 0; i < contents->length(); i++) {
463 Object* key = contents->get(i); 523 Object* key = contents->get(i);
464 Handle<String> key_handle; 524 Handle<String> key_handle;
465 Handle<Object> property; 525 Handle<Object> property;
466 if (key->IsString()) { 526 if (key->IsString()) {
467 key_handle = Handle<String>(String::cast(key)); 527 key_handle = Handle<String>(String::cast(key));
468 property = GetProperty(object, key_handle); 528 property = GetProperty(object, key_handle);
469 } else { 529 } else {
470 ASSERT(key->IsNumber()); 530 ASSERT(key->IsNumber());
471 key_handle = isolate_->factory()->NumberToString(Handle<Object>(key)); 531 key_handle = isolate_->factory()->NumberToString(Handle<Object>(key));
472 uint32_t index; 532 uint32_t index;
473 if (key->IsSmi()) { 533 if (key->IsSmi()) {
474 property = Object::GetElement(object, Smi::cast(key)->value()); 534 property = Object::GetElement(object, Smi::cast(key)->value());
475 } else if (key_handle->AsArrayIndex(&index)) { 535 } else if (key_handle->AsArrayIndex(&index)) {
476 property = Object::GetElement(object, index); 536 property = Object::GetElement(object, index);
477 } else { 537 } else {
478 property = GetProperty(object, key_handle); 538 property = GetProperty(object, key_handle);
479 } 539 }
480 } 540 }
481 if (property.is_null()) return BAILOUT; 541 if (property.is_null()) return EXCEPTION;
482 Result result = SerializeDeferred(property, comma, key_handle); 542 Result result = SerializeProperty(property, comma, key_handle);
483 if (!comma && result == SUCCESS) comma = true; 543 if (!comma && result == SUCCESS) comma = true;
484 if (result >= BAILOUT) return result; 544 if (result >= EXCEPTION) return result;
485 } 545 }
486 Append('}'); 546 Append('}');
487 StackPop(); 547 StackPop();
488 current_part_ = handle_scope.CloseAndEscape(current_part_); 548 current_part_ = handle_scope.CloseAndEscape(current_part_);
489 return SUCCESS; 549 return SUCCESS;
490 } 550 }
491 551
492 552
493 void BasicJsonStringifier::ShrinkCurrentPart() { 553 void BasicJsonStringifier::ShrinkCurrentPart() {
494 ASSERT(current_index_ < part_length_); 554 ASSERT(current_index_ < part_length_);
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 SerializeString_<false, char>(flat.ToAsciiVector(), object); 722 SerializeString_<false, char>(flat.ToAsciiVector(), object);
663 } else { 723 } else {
664 SerializeString_<false, uc16>(flat.ToUC16Vector(), object); 724 SerializeString_<false, uc16>(flat.ToUC16Vector(), object);
665 } 725 }
666 } 726 }
667 } 727 }
668 728
669 } } // namespace v8::internal 729 } } // namespace v8::internal
670 730
671 #endif // V8_JSON_STRINGIFIER_H_ 731 #endif // V8_JSON_STRINGIFIER_H_
OLDNEW
« no previous file with comments | « src/json.js ('k') | test/mjsunit/json2.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698