Showing the changes to libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp (1 of 8 files). Show all
Unified · Split
| @@ -628,6 +628,121 @@ QObject* ScriptValueV8Wrapper::toQObject() const { · 627 unmodified lines | |||
| 628 | } | 628 | } |
| 629 | } | 629 | } |
| 630 | 630 | ||
| 631 | static QString reprImpl( | ||
| 632 | v8::Isolate* isolate, | ||
| 633 | v8::Local<v8::Context> context, | ||
| 634 | v8::Local<v8::Value> value, | ||
| 635 | int indent = 0, | ||
| 636 | bool prependIndent = true | ||
| 637 | ) { | ||
| 638 | constexpr int INDENT_WIDTH = 4; | ||
| 639 | |||
| 640 | QString str; | ||
| 641 | |||
| 642 | if (prependIndent) { str = QString(INDENT_WIDTH * indent, ' '); } | ||
| 643 | |||
| 644 | if (value->IsUndefined()) { | ||
| 645 | str += "undefined"; | ||
| 646 | } else if (value->IsNull()) { | ||
| 647 | str += "null"; | ||
| 648 | } else if (value->IsFunction()) { | ||
| 649 | if (auto funcString = value->ToString(context); !funcString.IsEmpty()) { | ||
| 650 | // source available | ||
| 651 | str += QString(*v8::String::Utf8Value(isolate, funcString.ToLocalChecked())); | ||
| 652 | } else { | ||
| 653 | v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(value); | ||
| 654 | v8::Local<v8::Value> debugName = func->GetDebugName(); | ||
| 655 | |||
| 656 | str += "function "; | ||
| 657 | str += QString(*v8::String::Utf8Value(isolate, debugName->ToString(context).ToLocalChecked())); | ||
| 658 | str += "() { [native code] }"; | ||
| 659 | } | ||
| 660 | } else if (value->IsArray()) { | ||
| 661 | v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); | ||
| 662 | auto length = array->Length(); | ||
| 663 | |||
| 664 | str += "Array("; | ||
| 665 | str += QString::number(length); | ||
| 666 | str += ") [\n"; | ||
| 667 | |||
| 668 | for (uint32_t i = 0; i < length; i++) { | ||
| 669 | str += QString(INDENT_WIDTH * (indent + 1), ' '); | ||
| 670 | str += QString::number(i); | ||
| 671 | str += ": "; | ||
| 672 | |||
| 673 | // arrays in javascript can have unoccupied elements | ||
| 674 | if (array->Has(context, i).ToChecked()) { | ||
| 675 | str += reprImpl( | ||
| 676 | isolate, | ||
| 677 | context, | ||
| 678 | array->Get(context, i).ToLocalChecked(), | ||
| 679 | indent + 1, | ||
| 680 | false | ||
| 681 | ); | ||
| 682 | } else { | ||
| 683 | str += "<empty slot>"; | ||
| 684 | } | ||
| 685 | |||
| 686 | str += ",\n"; | ||
| 687 | } | ||
| 688 | |||
| 689 | str += QString(INDENT_WIDTH * indent, ' '); | ||
| 690 | str += ']'; | ||
| 691 | } else if (value->IsObject()) { | ||
| 692 | v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); | ||
| 693 | v8::Local<v8::String> constructorName = object->GetConstructorName(); | ||
| 694 | |||
| 695 | str += QString(*v8::String::Utf8Value(isolate, constructorName->ToString(context).ToLocalChecked()));; | ||
| 696 | |||
| 697 | v8::Local<v8::Array> properties = object->GetPropertyNames(context).ToLocalChecked(); | ||
| 698 | |||
| 699 | if (properties->Length() != 0) { | ||
| 700 | str += " {\n"; | ||
| 701 | |||
| 702 | for (uint32_t i = 0; i < properties->Length(); i++) { | ||
| 703 | auto name = properties->Get(context, i).ToLocalChecked(); | ||
| 704 | auto elem = object->Get(context, name).ToLocalChecked(); | ||
| 705 | |||
| 706 | str += QString(INDENT_WIDTH * (indent + 1), ' '); | ||
| 707 | str += QString(*v8::String::Utf8Value(isolate, name->ToString(context).ToLocalChecked()));; | ||
| 708 | str += ": "; | ||
| 709 | str += reprImpl( | ||
| 710 | isolate, | ||
| 711 | context, | ||
| 712 | elem, | ||
| 713 | indent + 1, | ||
| 714 | false | ||
| 715 | ); | ||
| 716 | str += "\n"; | ||
| 717 | } | ||
| 718 | |||
| 719 | str += QString(INDENT_WIDTH * indent, ' '); | ||
| 720 | str += "}"; | ||
| 721 | } else { | ||
| 722 | str += " {}"; | ||
| 723 | } | ||
| 724 | } else { | ||
| 725 | // Number, String, Boolean | ||
| 726 | return QString(*v8::String::Utf8Value(isolate, value->ToString(context).ToLocalChecked())); | ||
| 727 | } | ||
| 728 | |||
| 729 | return str; | ||
| 730 | } | ||
| 731 | |||
| 732 | QString ScriptValueV8Wrapper::repr() const { | ||
| 733 | auto* isolate = _engine->getIsolate(); | ||
| 734 | Q_ASSERT(isolate->IsCurrent()); | ||
| 735 | |||
| 736 | v8::HandleScope handleScope(isolate); | ||
| 737 | |||
| 738 | auto context = _engine->getContext(); | ||
| 739 | v8::Context::Scope contextScope(context); | ||
| 740 | |||
| 741 | auto value = toV8Value().constGet(); | ||
| 742 | |||
| 743 | return reprImpl(isolate, context, value); | ||
| 744 | } | ||
| 745 | |||
| 631 | bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const { | 746 | bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const { |
| 632 | auto isolate = _engine->getIsolate(); | 747 | auto isolate = _engine->getIsolate(); |
| 633 | Q_ASSERT(isolate->IsCurrent()); | 748 | Q_ASSERT(isolate->IsCurrent()); |