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 | 746 | bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const { |
| 632 | 747 | auto isolate = _engine->getIsolate(); |
| 633 | 748 | Q_ASSERT(isolate->IsCurrent()); |