History

ScriptValue::repr, detailed representation of a script value for logging

Ada committed 8 months ago

Commit abd6bae1 parent cdb75078 files · +143 −8Browse files

Showing the changes to libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp (1 of 8 files). Show all

Unified · Split

libraries/script-engine/src/v8/ScriptValueV8Wrapper.cpp+115−0
@@ -628,6 +628,121 @@ QObject* ScriptValueV8Wrapper::toQObject() const { · 627 unmodified lines
628 }628 }
629}629}
630 630
631static 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
732QString 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
631bool ScriptValueV8Wrapper::equals(const ScriptValue& other) const {746bool 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());