From a2c83874d362dbc09e205db25607958ca280f0d9 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 27 Sep 2016 09:00:13 +0200 Subject: [PATCH] Debugger: Some dumper improvements for QV4 types Start displaying QV4::Value again for numeric values and QJSValue for ints, doubles and strings. Change-Id: I18ce226c21168087ce280cb05aa0e250bd3187d9 Reviewed-by: Alexandru Croitor Reviewed-by: hjk --- share/qtcreator/debugger/dumper.py | 18 +- share/qtcreator/debugger/qttypes.py | 363 +++++++++++++++++++++++----- src/plugins/debugger/watchdata.cpp | 6 +- tests/auto/debugger/tst_dumpers.cpp | 80 ++++++ 4 files changed, 390 insertions(+), 77 deletions(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 6783235336b..4830864beae 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -283,6 +283,7 @@ class DumperBase: self.typesReported = {} self.typesToReport = {} self.qtNamespaceToReport = None + self.passExceptions = False self.resetCaches() self.resetStats() @@ -670,6 +671,12 @@ class DumperBase: elided, data = self.encodeStringHelper(self.extractPointer(value), self.displayStringLimit) self.putValue(data, "utf16", elided=elided) + def putPtrItem(self, name, value): + with SubItem(self, name): + self.putValue("0x%x" % value) + self.putType("void*") + self.putNumChild(0) + def putIntItem(self, name, value): with SubItem(self, name): if isinstance(value, self.Value): @@ -1211,8 +1218,7 @@ class DumperBase: # Explicitly requested bald pointer. #warn("RAW") self.putType(typeName) - self.putValue(self.hexencode(str(value)), "utf8:1:0") - self.putNumChild(1) + self.putValue("0x%x" % pointer) if self.currentIName in self.expandedINames: with Children(self): with SubItem(self, '*'): @@ -2411,12 +2417,6 @@ class DumperBase: def isReportableInterpreterFrame(self, functionName): return functionName and functionName.find("QV4::Moth::VME::exec") >= 0 - def extractQmlData(self, value): - if value.type.code == TypeCodePointer: - value = value.dereference() - data = value["data"] - return data.cast(self.lookupType(value.type.name.replace("QV4::", "QV4::Heap::"))) - def extractInterpreterStack(self): return self.sendInterpreterRequest('backtrace', {'limit': 10 }) @@ -3174,7 +3174,7 @@ class DumperBase: return typish if isinstance(typish, str): if typish[0] == 'Q': - if typish in ("QByteArray", "QString", "QList", "QStringList"): + if typish in ("QByteArray", "QString", "QList", "QStringList", "QStringDataPtr"): typish = self.qtNamespace() + typish size = self.ptrSize() elif typish == "QImage": diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 6318990be11..ad9bd5ecc33 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -1287,8 +1287,11 @@ def qdump__QStaticStringData(d, value): d.putPlainChildren(value) def qdump__QStringData(d, value): - d.putStringValueByAddress(value.integer()) + (ref, size, alloc, pad, offset) = value.split('III@p') + elided, shown = d.computeLimit(size, d.displayStringLimit) + data = d.readMemory(value.address() + offset, shown * 2) d.putNumChild(0) + d.putValue(data, "utf16", elided=elided) def qdump__QHashedString(d, value): qdump__QString(d, value) @@ -1815,97 +1818,325 @@ def qdump__QXmlStreamAttribute(d, value): # ####################################################################### -def qdump__QV4__Object(d, value): - d.putBetterType(d.currentType) - d.putItem(d.extractQmlData(value)) +def extractQmlData(d, value): + #if value.type.code == TypeCodePointer: + # value = value.dereference() + base = value.split('p')[0] + #mmdata = d.split('Q', base)[0] + #PointerMask = 0xfffffffffffffffd + #vtable = mmdata & PointerMask + #warn("QML DATA: %s" % value.stringify()) + #data = value["data"] + #return #data.cast(d.lookupType(value.type.name.replace("QV4::", "QV4::Heap::"))) + typeName = value.type.name.replace("QV4::", "QV4::Heap::") + #warn("TYOE DATA: %s" % typeName) + return d.createValue(base, typeName) -def qdump__QV4__FunctionObject(d, value): - d.putBetterType(d.currentType) - d.putItem(d.extractQmlData(value)) - -def qdump__QV4__CompilationUnit(d, value): - d.putBetterType(d.currentType) - d.putItem(d.extractQmlData(value)) - -def qdump__QV4__CallContext(d, value): - d.putBetterType(d.currentType) - d.putItem(d.extractQmlData(value)) - -def qdump__QV4__ScriptFunction(d, value): - d.putBetterType(d.currentType) - d.putItem(d.extractQmlData(value)) - -def qdump__QV4__SimpleScriptFunction(d, value): - d.putBetterType(d.currentType) - d.putItem(d.extractQmlData(value)) - -def qdump__QV4__ExecutionContext(d, value): - d.putBetterType(d.currentType) - d.putItem(d.extractQmlData(value)) - -def qdump__QV4__TypedValue(d, value): - d.putBetterType(d.currentType) - qdump__QV4__Value(d, d.directBaseObject(value)) - -def qdump__QV4__CallData(d, value): - argc = value["argc"].integer() - d.putItemCount(argc) +def qdump__QV4__Heap__Base(d, value): + mm_data = value.extractPointer() + d.putValue("[%s]" % mm_data) if d.isExpanded(): with Children(d): - d.putSubItem("[this]", value["thisObject"]) - for i in range(0, argc): - d.putSubItem(i, value["args"][i]) + with SubItem(d, "vtable"): + d.putItem(d.createValue(mm_data & (~3), d.qtNamespace() + "QV4::VTable")) + d.putBoolItem("isMarked", mm_data & 1) + d.putBoolItem("inUse", (mm_data & 2) == 0) + with SubItem(d, "nextFree"): + d.putItem(d.createValue(mm_data & (~3), value.type)) -def qdump__QV4__String(d, value): - d.putStringValue(value.address() + 2 * d.ptrSize()) +def qdump__QV4__Heap__String(d, value): + # Note: There's also the 'Identifier' case. And the largestSubLength != 0 case. + (baseClass, textOrLeft, idOrRight, subtype, stringHash, largestSub, length, mm) \ + = value.split('QppIIIIp') + textPtr = d.split('{QStringDataPtr}', textOrLeft)[0] + qdump__QStringData(d, d.createValue(textOrLeft, d.qtNamespace() + "QStringData")) + if d.isExpanded(): + with Children(d): + d.putFields(value) + +def qmlPutHeapChildren(d, value): + d.putEmptyValue() + if d.isExpanded(): + with Children(d): + d.putFields(value) + d.putSubItem("heap", extractQmlData(d, value)) + + +def qdump__QV4__Object(d, value): + qmlPutHeapChildren(d, value) + +def qdump__QV4__FunctionObject(d, value): + #qmlPutHeapChildren(d, value) + d.putEmptyValue() + if d.isExpanded(): + with Children(d): + d.putFields(value) + d.putSubItem("heap", extractQmlData(d, value)) + d.putCallItem("sourceLocation", d.qtNamespace() + "QQmlSourceLocation", + value, "sourceLocation") + +def qdump__QV4__CompilationUnit(d, value): + qmlPutHeapChildren(d, value) + +def qdump__QV4__CallContext(d, value): + qmlPutHeapChildren(d, value) + +def qdump__QV4__ScriptFunction(d, value): + qmlPutHeapChildren(d, value) + +def qdump__QV4__SimpleScriptFunction(d, value): + qdump__QV4__FunctionObject(d, value) + +def qdump__QV4__ExecutionContext(d, value): + qmlPutHeapChildren(d, value) + +def qdump__QQmlSourceLocation(d, value): + (sourceFile, line, col) = value.split("pHH") + (data, size, alloc) = d.stringData(value) + d.putValue(d.readMemory(data, 2 * size), "utf16") + d.put("valuesuffix=\":%s:%s\"," % (line, col)) + d.putPlainChildren(value) + + +#def qdump__QV4__CallData(d, value): +# argc = value["argc"].integer() +# d.putItemCount(argc) +# if d.isExpanded(): +# with Children(d): +# d.putSubItem("[this]", value["thisObject"]) +# for i in range(0, argc): +# d.putSubItem(i, value["args"][i]) +# +#def qdump__QV4__String(d, value): +# qmlPutHeapChildren(d, value) + +if False: + # 32 bit. + QV4_Masks_SilentNaNBit = 0x00040000 + QV4_Masks_NaN_Mask = 0x7ff80000 + QV4_Masks_NotDouble_Mask = 0x7ffa0000 + QV4_Masks_Type_Mask = 0xffffc000 + QV4_Masks_Immediate_Mask = QV4_Masks_NotDouble_Mask | 0x00004000 | QV4_Masks_SilentNaNBit + QV4_Masks_IsNullOrUndefined_Mask = QV4_Masks_Immediate_Mask | 0x08000 + QV4_Masks_Tag_Shift = 32 + + QV4_ValueType_Undefined_Type = QV4_Masks_Immediate_Mask | 0x00000 + QV4_ValueType_Null_Type = QV4_Masks_Immediate_Mask | 0x10000 + QV4_ValueType_Boolean_Type = QV4_Masks_Immediate_Mask | 0x08000 + QV4_ValueType_Integer_Type = QV4_Masks_Immediate_Mask | 0x18000 + QV4_ValueType_Managed_Type = QV4_Masks_NotDouble_Mask | 0x00000 | QV4_Masks_SilentNaNBit + QV4_ValueType_Empty_Type = QV4_Masks_NotDouble_Mask | 0x18000 | QV4_Masks_SilentNaNBit + + QV4_ConvertibleToInt = QV4_Masks_Immediate_Mask | 0x1 + + QV4_ValueTypeInternal_Null_Type_Internal = QV4_ValueType_Null_Type | QV4_ConvertibleToInt + QV4_ValueTypeInternal_Boolean_Type_Internal = QV4_ValueType_Boolean_Type | QV4_ConvertibleToInt + QV4_ValueTypeInternal_Integer_Type_Internal = QV4_ValueType_Integer_Type | QV4_ConvertibleToInt + +else: + # 64 bit. + QV4_NaNEncodeMask = 0xffff800000000000 + QV4_IsInt32Mask = 0x0002000000000000 + QV4_IsDoubleMask = 0xfffc000000000000 + QV4_IsNumberMask = QV4_IsInt32Mask | QV4_IsDoubleMask + QV4_IsNullOrUndefinedMask = 0x0000800000000000 + QV4_IsNullOrBooleanMask = 0x0001000000000000 + QV4_PointerMask = 0xfffffffffffffffd + + QV4_Masks_NaN_Mask = 0x7ff80000 + QV4_Masks_Type_Mask = 0xffff8000 + QV4_Masks_IsDouble_Mask = 0xfffc0000 + QV4_Masks_Immediate_Mask = 0x00018000 + QV4_Masks_IsNullOrUndefined_Mask = 0x00008000 + QV4_Masks_IsNullOrBoolean_Mask = 0x00010000 + QV4_Masks_Tag_Shift = 32 + + QV4_ValueType_Undefined_Type = QV4_Masks_IsNullOrUndefined_Mask + QV4_ValueType_Null_Type = QV4_Masks_IsNullOrUndefined_Mask | QV4_Masks_IsNullOrBoolean_Mask + QV4_ValueType_Boolean_Type = QV4_Masks_IsNullOrBoolean_Mask + QV4_ValueType_Integer_Type = 0x20000 | QV4_Masks_IsNullOrBoolean_Mask + QV4_ValueType_Managed_Type = 0 + QV4_ValueType_Empty_Type = QV4_ValueType_Undefined_Type | 0x4000 + + QV4_ValueTypeInternal_Null_Type_Internal = QV4_ValueType_Null_Type + QV4_ValueTypeInternal_Boolean_Type_Internal = QV4_ValueType_Boolean_Type + QV4_ValueTypeInternal_Integer_Type_Internal = QV4_ValueType_Integer_Type + + QV4_IsDouble_Shift = 64-14 + QV4_IsNumber_Shift = 64-15 + QV4_IsConvertibleToInt_Shift = 64-16 + QV4_IsManaged_Shift = 64-17 + + +def QV4_getValue(d, jsval): # (Dumper, QJSValue *jsval) -> QV4::Value * + dd = d.split('Q', jsval)[0] + if dd & 3: + return 0 + return dd + +def QV4_getVariant(d, jsval): # (Dumper, QJSValue *jsval) -> QVariant * + dd = d.split('Q', jsval)[0] + if dd & 1: + return dd & ~3 + return 0 + +def QV4_valueForData(d, jsval): # (Dumper, QJSValue *jsval) -> QV4::Value * + v = QV4_getValue(d, jsval) + if v: + return v + warn("Not implemented: VARIANT") + return 0 + +def QV4_putObjectValue(d, objectPtr): + ns = d.qtNamespace() + base = d.extractPointer(objectPtr) + (inlineMemberOffset, inlineMemberSize, internalClass, prototype, + memberData, arrayData) = d.split('IIpppp', base) + d.putValue("PTR: 0x%x" % objectPtr) + if d.isExpanded(): + with Children(d): + with SubItem(d, "[raw]"): + d.putValue("[0x%x]" % objectPtr) + d.putType(" "); + d.putNumChild(0) + d.putIntItem("inlineMemberOffset", inlineMemberOffset) + d.putIntItem("inlineMemberSize", inlineMemberSize) + d.putIntItem("internalClass", internalClass) + d.putIntItem("prototype", prototype) + d.putPtrItem("memberData", memberData) + d.putPtrItem("arrayData", arrayData) + d.putSubItem("OBJ", d.createValue(objectPtr, ns + "QV4::Object")) + #d.putFields(value) + +def qdump__QV4_Object(d, value): + ns = d.qtNamespace() + d.putEmptyValue() + if d.isExpanded(): + with Children(d): + with SubItem(d, "[raw]"): + base = d.extractPointer(objectPtr) + (inlineMemberOffset, inlineMemberSize, internalClass, prototype, + memberData, arrayData) = d.split('IIpppp', base) + d.putValue("PTR: 0x%x" % objectPtr) def qdump__QV4__Value(d, value): - v = int(str(value["_val"])) - NaNEncodeMask = 0xffff800000000000 - IsInt32Mask = 0x0002000000000000 - IsDoubleMask = 0xfffc000000000000 - IsNumberMask = IsInt32Mask | IsDoubleMask - IsNullOrUndefinedMask = 0x0000800000000000 - IsNullOrBooleanMask = 0x0001000000000000 - IsConvertibleToIntMask = IsInt32Mask | IsNullOrBooleanMask + v = value.split('Q')[0] + if d.ptrSize() == 4: + d.putValue("[0x%x]" % v) + d.putPlainChildren(value) + return + tag = v >> QV4_Masks_Tag_Shift + vtable = v & QV4_PointerMask ns = d.qtNamespace() - if v & IsInt32Mask: + if (v >> QV4_IsNumber_Shift) == 1: d.putBetterType("%sQV4::Value (int32)" % ns) vv = v & 0xffffffff vv = vv if vv < 0x80000000 else -(0x100000000 - vv) d.putBetterType("%sQV4::Value (int32)" % ns) d.putValue("%d" % vv) - elif v & IsDoubleMask: + elif (v >> QV4_IsDouble_Shift): d.putBetterType("%sQV4::Value (double)" % ns) - d.putValue("%x" % (v ^ 0xffff800000000000), "float:8") + d.putValue("%x" % (v ^ QV4_NaNEncodeMask), "float:8") + elif tag == QV4_ValueType_Undefined_Type: + d.putBetterType("%sQV4::Value (undefined)" % ns) + d.putValue("(undefined)") + elif tag == QV4_ValueTypeInternal_Null_Type_Internal: + d.putBetterType("%sQV4::Value (null?)" % ns) + d.putValue("(null?)") elif v == 0: d.putBetterType("%sQV4::Value (null)" % ns) d.putValue("(null)") - elif v & IsNullOrUndefinedMask: - d.putBetterType("%sQV4::Value (null/undef)" % ns) - d.putValue("(null/undef)") - elif v & IsNullOrBooleanMask: - d.putBetterType("%sQV4::Value (null/bool)" % ns) - d.putValue("(null/bool)") - d.putValue(v & 1) + #elif ((v >> QV4_IsManaged_Shift) & ~1) == 1: + # d.putBetterType("%sQV4::Value (null/undef)" % ns) + # d.putValue("(null/undef)") + #elif v & QV4_IsNullOrBooleanMask: + # d.putBetterType("%sQV4::Value (null/bool)" % ns) + # d.putValue("(null/bool)") + # d.putValue(v & 1) else: - vtable = value["m"]["vtable"] - if vtable["isString"].integer(): + (parentv, flags, pad, className) = d.split('pIIp', vtable) + #vtable = value["m"]["vtable"] + if flags & 2: # isString" d.putBetterType("%sQV4::Value (string)" % ns) - d.putStringValue(d.extractPointer(value) + 2 * d.ptrSize()) - elif vtable["isObject"].integer(): + qdump__QV4__Heap__String(d, d.createValue(v, ns + "QV4::Heap::String")) + #d.putStringValue(d.extractPointer(value) + 2 * d.ptrSize()) + #d.putValue("ptr: 0x%x" % d.extractPointer(value)) + return + elif flags & 4: # isObject d.putBetterType("%sQV4::Value (object)" % ns) - d.putValue("[0x%x]" % v) + #QV4_putObjectValue(d, d.extractPointer(value) + 2 * d.ptrSize()) + arrayVTable = d.symbolAddress(ns + "QV4::ArrayObject::static_vtbl") + warn("ARRAY VTABLE: 0x%x" % arrayVTable) + d.putNumChild(1) + d.putItem(d.createValue(d.extractPointer(value) + 2 * d.ptrSize(), ns + "QV4::Object")) + return + elif flags & 8: # isFunction + d.putBetterType("%sQV4::Value (function)" % ns) + d.putEmptyValue() else: d.putBetterType("%sQV4::Value (unknown)" % ns) - d.putValue("[0x%x]" % v) - d.putNumChild(1) + #d.putValue("[0x%x]" % v) + d.putValue("[0x%x : flag 0x%x : tag 0x%x]" % (v, flags, tag)) if d.isExpanded(): with Children(d): with SubItem(d, "[raw]"): d.putValue("[0x%x]" % v) d.putType(" "); d.putNumChild(0) + with SubItem(d, "[vtable]"): + d.putItem(d.createValue(vtable, ns + "QV4::VTable")) + d.putType(" "); + d.putNumChild(0) + d.putFields(value) + +def qdump__QV__PropertyHashData(d, value): + (ref, alloc, size, numBits, entries) = value.split('IIIIp') + d.putItemCount(size) + if d.isExpanded(): + with Children(d): + d.putFields(value) + +def qdump__QV__PropertyHash(d, value): + qdump__QV__PropertyHashData(d, d.createValue(d.extractPointer(), value.type.name + 'Data')) + + +def qdump__QV4__Scoped(d, value): + innerType = value.type[0] + d.putItem(d.createValue(value.extractPointer(), innerType)) + #d.putEmptyValue() + #if d.isExpanded(): + # with Children(d): + # d.putSubItem('[]', d.createValue(value.extractPointer(), innerType)) + # d.putFields(value) + +def qdump__QJSValue(d, value): + ns = d.qtNamespace() + dd = value.split('Q')[0] + if dd & 1: + variant = d.createValue(dd & ~3, ns + "QVariant") + qdump__QVariant(d, variant) + d.putBetterType(d.currentType.value.replace('QVariant', 'QJSValue', 1)) + elif dd == 0: + d.putValue("(null)") + d.putType(value.type.name + " (null)") + else: + #d.putEmptyValue() + qdump__QV4__Value(d, d.createValue(dd, ns + 'QV4::Value')) + return + if d.isExpanded(): + with Children(d): + with SubItem(d, "[raw]"): + d.putValue("[0x%x]" % dd) + d.putType(" "); + d.putNumChild(0) + d.putFields(value) + +def qdump__QQmlBinding(d, value): + d.putEmptyValue() + if d.isExpanded(): + with Children(d): + d.putCallItem("expressionIdentifier", d.qtNamespace() + "QString", + value, "expressionIdentifier") d.putFields(value) @@ -1973,7 +2204,6 @@ def qdump__QTJSC__JSValue(d, value): except: pass - def qdump__QScriptValue(d, value): # structure: # engine QScriptEnginePrivate @@ -2269,4 +2499,3 @@ def qdump__QJsonArray(d, value): def qdump__QJsonObject(d, value): qdumpHelper_QJsonObject(d, value["d"].integer(), value["o"].integer()) - diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp index 98bd59d4458..14c47bdfef1 100644 --- a/src/plugins/debugger/watchdata.cpp +++ b/src/plugins/debugger/watchdata.cpp @@ -434,8 +434,12 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort) mi = input["value"]; QString enc = input["valueencoded"].data(); - if (mi.isValid() || !enc.isEmpty()) + if (mi.isValid() || !enc.isEmpty()) { setValue(decodeData(mi.data(), enc)); + mi = input["valuesuffix"]; + if (mi.isValid()) + value += mi.data(); + } mi = input["size"]; if (mi.isValid()) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index bda2d6eeb0d..0ed09bccba2 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -637,6 +637,8 @@ struct CorePrivateProfile {}; struct GuiProfile {}; struct GuiPrivateProfile {}; struct NetworkProfile {}; +struct QmlProfile {}; +struct QmlPrivateProfile {}; struct BigArrayProfile {}; @@ -822,6 +824,28 @@ public: return *this; } + const Data &operator+(const QmlProfile &) const + { + profileExtra += + "greaterThan(QT_MAJOR_VERSION, 4) {\n" + " QT += qml\n" + "}"; + + return *this; + } + + const Data &operator+(const QmlPrivateProfile &) const + { + this->operator+(QmlProfile()); + profileExtra += + "greaterThan(QT_MAJOR_VERSION, 4) {\n" + " QT += qml-private\n" + " CONFIG += no_private_qt_headers_warning\n" + "}"; + + return *this; + } + const Data &operator+(const ForceC &) const { forceC = true; @@ -3117,6 +3141,12 @@ void tst_Dumpers::dumper_data() "QString str3(\"Hello\\rQt\"); unused(&str3);\n" "QString str4(\"Hello\\tQt\"); unused(&str4);\n\n" + "static const QStaticStringData<3> qstring_literal = {\n" + " Q_STATIC_STRING_DATA_HEADER_INITIALIZER(3),\n" + " QT_UNICODE_LITERAL(u\"ABC\") };\n" + "QStringDataPtr holder = { qstring_literal.data_ptr() };\n" + "const QString qstring_literal_temp(holder); unused(&holder);\n\n" + "QStaticStringData<1> sd;\n" "sd.data[0] = 'Q';\n" "sd.data[1] = 0;\n") @@ -3147,6 +3177,9 @@ void tst_Dumpers::dumper_data() + Check("str3", "\"Hello\rQt\"", "@QString") + Check("str4", "\"Hello\tQt\"", "@QString") + + Check("holder", "", "@QStringDataPtr") + + Check("holder.ptr", "\"ABC\"", "@QStringData") + + Check("sd", "\"Q\"", "@QStaticStringData<1>"); @@ -6102,6 +6135,53 @@ void tst_Dumpers::dumper_data() + Check("ob.2", "\"ccc\"", "\"hallo\"", "QJsonValue (String)") + Check("ob.3", "\"d\"", "<1 items>", "QJsonValue (Object)") + Check("ob.4", "\"s\"", "\"ssss\"", "QJsonValue (String)"); + + QTest::newRow("QV4") + << Data("#include \n" + "#include \n" + "#include \n" + "#include \n", + "QGuiApplication app(argc, argv);\n" + "QJSEngine eng;\n\n" + "QV4::Value q0; unused(&q0);\n\n" + "QV4::Value q1; unused(&q1);\n" + "q1.setInt_32(1);\n\n" + "QV4::Value q2; unused(&q2);\n" + "q2.setDouble(2.5);\n\n" + "QJSValue v10; unused(&v10);\n" + "QJSValue v11 = QJSValue(true); unused(&v11);\n" + "QJSValue v12 = QJSValue(1); unused(&v12);\n" + "QJSValue v13 = QJSValue(2.5); unused(&v13);\n" + "QJSValue v14 = QJSValue(QLatin1String(\"latin1\")); unused(&v14);\n" + "QJSValue v15 = QJSValue(QString(\"utf16\")); unused(&v15);\n" + "QJSValue v16 = QJSValue(bool(true)); unused(&v12);\n" + "QJSValue v17 = eng.newArray(100); unused(&v17);\n" + "QJSValue v18 = eng.newObject(); unused(&v18);\n\n" + "v18.setProperty(\"PropA\", 1);\n" + "v18.setProperty(\"PropB\", 2.5);\n" + "v18.setProperty(\"PropC\", v10);\n\n" + "QV4::Value s11, *p11 = QJSValuePrivate::valueForData(&v11, &s11); unused(&p11);\n" + "QV4::Value s12, *p12 = QJSValuePrivate::valueForData(&v12, &s12); unused(&p12);\n" + "QV4::Value s13, *p13 = QJSValuePrivate::valueForData(&v13, &s13); unused(&p13);\n" + "QV4::Value s14, *p14 = QJSValuePrivate::valueForData(&v14, &s14); unused(&p14);\n" + "QV4::Value s15, *p15 = QJSValuePrivate::valueForData(&v15, &s15); unused(&p15);\n" + "QV4::Value s16, *p16 = QJSValuePrivate::valueForData(&v16, &s16); unused(&p16);\n" + "QV4::Value s17, *p17 = QJSValuePrivate::valueForData(&v17, &s17); unused(&p17);\n" + "QV4::Value s18, *p18 = QJSValuePrivate::valueForData(&v18, &s18); unused(&p18);\n" + ) + + QmlPrivateProfile() + + QtVersion(0x50000) + //+ Check("q0", "(null)", "@QV4::Value (null)") # Works in GUI. Why? + + Check("q1", "1", "@QV4::Value (int32)") + + Check("q2", FloatValue("2.5"), "@QV4::Value (double)") + //+ Check("v10", "(null)", "@QJSValue (null)") # Works in GUI. Why? + + Check("v11", "true", "@QJSValue (bool)") + + Check("v12", "1", "@QJSValue (int)") + + Check("v13", FloatValue("2.5"), "@QJSValue (double)") + + Check("v14", "\"latin1\"", "@QJSValue (QString)") + + Check("v14.2", "[2]", "116", "@QChar") + + Check("v15", "\"utf16\"", "@QJSValue (QString)") + + Check("v15.1", "[1]", "116", "@QChar"); } int main(int argc, char *argv[])