OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_JSON_STRINGIFIER_H_ | 5 #ifndef V8_JSON_STRINGIFIER_H_ |
6 #define V8_JSON_STRINGIFIER_H_ | 6 #define V8_JSON_STRINGIFIER_H_ |
7 | 7 |
8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
9 #include "src/lookup.h" | 9 #include "src/lookup.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 Isolate* isolate, | 26 Isolate* isolate, |
27 Handle<String> object)); | 27 Handle<String> object)); |
28 | 28 |
29 private: | 29 private: |
30 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; | 30 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; |
31 | 31 |
32 MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction( | 32 MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction( |
33 Handle<Object> object, | 33 Handle<Object> object, |
34 Handle<Object> key); | 34 Handle<Object> key); |
35 | 35 |
36 Result SerializeGeneric(Handle<Object> object, | |
37 Handle<Object> key, | |
38 bool deferred_comma, | |
39 bool deferred_key); | |
40 | |
41 // Entry point to serialize the object. | 36 // Entry point to serialize the object. |
42 INLINE(Result SerializeObject(Handle<Object> obj)) { | 37 INLINE(Result SerializeObject(Handle<Object> obj)) { |
43 return Serialize_<false>(obj, false, factory()->empty_string()); | 38 return Serialize_<false>(obj, false, factory()->empty_string()); |
44 } | 39 } |
45 | 40 |
46 // Serialize an array element. | 41 // Serialize an array element. |
47 // The index may serve as argument for the toJSON function. | 42 // The index may serve as argument for the toJSON function. |
48 INLINE(Result SerializeElement(Isolate* isolate, | 43 INLINE(Result SerializeElement(Isolate* isolate, |
49 Handle<Object> object, | 44 Handle<Object> object, |
50 int i)) { | 45 int i)) { |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 builder_.AppendCString("true"); | 351 builder_.AppendCString("true"); |
357 return SUCCESS; | 352 return SUCCESS; |
358 case Oddball::kNull: | 353 case Oddball::kNull: |
359 if (deferred_string_key) SerializeDeferredKey(comma, key); | 354 if (deferred_string_key) SerializeDeferredKey(comma, key); |
360 builder_.AppendCString("null"); | 355 builder_.AppendCString("null"); |
361 return SUCCESS; | 356 return SUCCESS; |
362 default: | 357 default: |
363 return UNCHANGED; | 358 return UNCHANGED; |
364 } | 359 } |
365 case JS_ARRAY_TYPE: | 360 case JS_ARRAY_TYPE: |
366 if (object->IsAccessCheckNeeded()) break; | |
367 if (deferred_string_key) SerializeDeferredKey(comma, key); | 361 if (deferred_string_key) SerializeDeferredKey(comma, key); |
368 return SerializeJSArray(Handle<JSArray>::cast(object)); | 362 return SerializeJSArray(Handle<JSArray>::cast(object)); |
369 case JS_VALUE_TYPE: | 363 case JS_VALUE_TYPE: |
370 if (deferred_string_key) SerializeDeferredKey(comma, key); | 364 if (deferred_string_key) SerializeDeferredKey(comma, key); |
371 return SerializeJSValue(Handle<JSValue>::cast(object)); | 365 return SerializeJSValue(Handle<JSValue>::cast(object)); |
| 366 case SIMD128_VALUE_TYPE: |
| 367 case SYMBOL_TYPE: |
| 368 return UNCHANGED; |
372 default: | 369 default: |
373 if (object->IsString()) { | 370 if (object->IsString()) { |
374 if (deferred_string_key) SerializeDeferredKey(comma, key); | 371 if (deferred_string_key) SerializeDeferredKey(comma, key); |
375 SerializeString(Handle<String>::cast(object)); | 372 SerializeString(Handle<String>::cast(object)); |
376 return SUCCESS; | 373 return SUCCESS; |
377 } else if (object->IsJSReceiver()) { | 374 } else { |
| 375 DCHECK(object->IsJSReceiver()); |
378 if (object->IsCallable()) return UNCHANGED; | 376 if (object->IsCallable()) return UNCHANGED; |
379 // Go to slow path for global proxy and objects requiring access checks. | 377 // Go to slow path for global proxy and objects requiring access checks. |
380 if (object->IsAccessCheckNeeded() || object->IsJSGlobalProxy()) break; | |
381 if (deferred_string_key) SerializeDeferredKey(comma, key); | 378 if (deferred_string_key) SerializeDeferredKey(comma, key); |
382 if (object->IsJSProxy()) { | 379 if (object->IsJSProxy()) { |
383 return SerializeJSProxy(Handle<JSProxy>::cast(object)); | 380 return SerializeJSProxy(Handle<JSProxy>::cast(object)); |
384 } | 381 } |
385 return SerializeJSObject(Handle<JSObject>::cast(object)); | 382 return SerializeJSObject(Handle<JSObject>::cast(object)); |
386 } | 383 } |
387 } | 384 } |
388 | 385 |
389 return SerializeGeneric(object, key, comma, deferred_string_key); | 386 UNREACHABLE(); |
| 387 return UNCHANGED; |
390 } | 388 } |
391 | 389 |
392 | 390 |
393 BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric( | |
394 Handle<Object> object, | |
395 Handle<Object> key, | |
396 bool deferred_comma, | |
397 bool deferred_key) { | |
398 Handle<JSFunction> fun = isolate_->json_serialize_adapter(); | |
399 Handle<Object> indent(Smi::FromInt(indent_), isolate_); | |
400 Handle<Object> argv[] = {key, object, indent, gap_string_}; | |
401 Handle<Object> result; | |
402 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
403 isolate_, result, | |
404 Execution::Call(isolate_, fun, object, arraysize(argv), argv), EXCEPTION); | |
405 if (result->IsUndefined()) return UNCHANGED; | |
406 if (deferred_key) { | |
407 if (key->IsSmi()) key = factory()->NumberToString(key); | |
408 SerializeDeferredKey(deferred_comma, key); | |
409 } | |
410 | |
411 builder_.AppendString(Handle<String>::cast(result)); | |
412 return SUCCESS; | |
413 } | |
414 | |
415 | |
416 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( | 391 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( |
417 Handle<JSValue> object) { | 392 Handle<JSValue> object) { |
418 String* class_name = object->class_name(); | 393 String* class_name = object->class_name(); |
419 if (class_name == isolate_->heap()->String_string()) { | 394 if (class_name == isolate_->heap()->String_string()) { |
420 Handle<Object> value; | 395 Handle<Object> value; |
421 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 396 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
422 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); | 397 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); |
423 SerializeString(Handle<String>::cast(value)); | 398 SerializeString(Handle<String>::cast(value)); |
424 } else if (class_name == isolate_->heap()->Number_string()) { | 399 } else if (class_name == isolate_->heap()->Number_string()) { |
425 Handle<Object> value; | 400 Handle<Object> value; |
426 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), | 401 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), |
427 EXCEPTION); | 402 EXCEPTION); |
428 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); | 403 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); |
429 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); | 404 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); |
430 } else if (class_name == isolate_->heap()->Boolean_string()) { | 405 } else if (class_name == isolate_->heap()->Boolean_string()) { |
431 Object* value = JSValue::cast(*object)->value(); | 406 Object* value = JSValue::cast(*object)->value(); |
432 DCHECK(value->IsBoolean()); | 407 DCHECK(value->IsBoolean()); |
433 builder_.AppendCString(value->IsTrue() ? "true" : "false"); | 408 builder_.AppendCString(value->IsTrue() ? "true" : "false"); |
434 } else { | 409 } else { |
435 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. | 410 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. |
436 CHECK(!object->IsAccessCheckNeeded()); | |
437 CHECK(!object->IsJSGlobalProxy()); | |
438 return SerializeJSObject(object); | 411 return SerializeJSObject(object); |
439 } | 412 } |
440 return SUCCESS; | 413 return SUCCESS; |
441 } | 414 } |
442 | 415 |
443 | 416 |
444 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { | 417 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { |
445 static const int kBufferSize = 100; | 418 static const int kBufferSize = 100; |
446 char chars[kBufferSize]; | 419 char chars[kBufferSize]; |
447 Vector<char> buffer(chars, kBufferSize); | 420 Vector<char> buffer(chars, kBufferSize); |
(...skipping 16 matching lines...) Expand all Loading... |
464 } | 437 } |
465 | 438 |
466 | 439 |
467 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( | 440 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
468 Handle<JSArray> object) { | 441 Handle<JSArray> object) { |
469 HandleScope handle_scope(isolate_); | 442 HandleScope handle_scope(isolate_); |
470 Result stack_push = StackPush(object); | 443 Result stack_push = StackPush(object); |
471 if (stack_push != SUCCESS) return stack_push; | 444 if (stack_push != SUCCESS) return stack_push; |
472 uint32_t length = 0; | 445 uint32_t length = 0; |
473 CHECK(object->length()->ToArrayLength(&length)); | 446 CHECK(object->length()->ToArrayLength(&length)); |
| 447 DCHECK(!object->IsAccessCheckNeeded()); |
474 builder_.AppendCharacter('['); | 448 builder_.AppendCharacter('['); |
475 Indent(); | 449 Indent(); |
476 switch (object->GetElementsKind()) { | 450 switch (object->GetElementsKind()) { |
477 case FAST_SMI_ELEMENTS: { | 451 case FAST_SMI_ELEMENTS: { |
478 Handle<FixedArray> elements(FixedArray::cast(object->elements()), | 452 Handle<FixedArray> elements(FixedArray::cast(object->elements()), |
479 isolate_); | 453 isolate_); |
480 for (uint32_t i = 0; i < length; i++) { | 454 for (uint32_t i = 0; i < length; i++) { |
481 Separator(i == 0); | 455 Separator(i == 0); |
482 SerializeSmi(Smi::cast(elements->get(i))); | 456 SerializeSmi(Smi::cast(elements->get(i))); |
483 } | 457 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 } | 528 } |
555 } | 529 } |
556 return SUCCESS; | 530 return SUCCESS; |
557 } | 531 } |
558 | 532 |
559 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( | 533 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
560 Handle<JSObject> object) { | 534 Handle<JSObject> object) { |
561 HandleScope handle_scope(isolate_); | 535 HandleScope handle_scope(isolate_); |
562 Result stack_push = StackPush(object); | 536 Result stack_push = StackPush(object); |
563 if (stack_push != SUCCESS) return stack_push; | 537 if (stack_push != SUCCESS) return stack_push; |
564 DCHECK(!object->IsJSGlobalProxy() && !object->IsJSGlobalObject()); | |
565 | 538 |
566 if (object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && | 539 if (object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && |
567 object->HasFastProperties() && | 540 object->HasFastProperties() && |
568 Handle<JSObject>::cast(object)->elements()->length() == 0) { | 541 Handle<JSObject>::cast(object)->elements()->length() == 0) { |
569 DCHECK(object->IsJSObject()); | 542 DCHECK(object->IsJSObject()); |
| 543 DCHECK(!object->IsJSGlobalProxy()); |
570 Handle<JSObject> js_obj = Handle<JSObject>::cast(object); | 544 Handle<JSObject> js_obj = Handle<JSObject>::cast(object); |
571 DCHECK(!js_obj->HasIndexedInterceptor()); | 545 DCHECK(!js_obj->HasIndexedInterceptor()); |
572 DCHECK(!js_obj->HasNamedInterceptor()); | 546 DCHECK(!js_obj->HasNamedInterceptor()); |
573 Handle<Map> map(js_obj->map()); | 547 Handle<Map> map(js_obj->map()); |
574 builder_.AppendCharacter('{'); | 548 builder_.AppendCharacter('{'); |
575 Indent(); | 549 Indent(); |
576 bool comma = false; | 550 bool comma = false; |
577 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | 551 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
578 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); | 552 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); |
579 // TODO(rossberg): Should this throw? | 553 // TODO(rossberg): Should this throw? |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 } else { | 741 } else { |
768 SerializeString_<uc16, uc16>(object); | 742 SerializeString_<uc16, uc16>(object); |
769 } | 743 } |
770 } | 744 } |
771 } | 745 } |
772 | 746 |
773 } // namespace internal | 747 } // namespace internal |
774 } // namespace v8 | 748 } // namespace v8 |
775 | 749 |
776 #endif // V8_JSON_STRINGIFIER_H_ | 750 #endif // V8_JSON_STRINGIFIER_H_ |
OLD | NEW |