#include <private/qv4string_p.h>
#include <private/qv4objectiterator_p.h>
#include <private/qv4identifier_p.h>
+#include <private/qv4runtime_p.h>
#include <QtCore/qjsonarray.h>
m_collectedRefs->append(addRef(value));
}
-QJsonObject QV4DataCollector::lookupRef(Ref ref)
+const QV4::Object *collectProperty(const QV4::ScopedValue &value, QV4::ExecutionEngine *engine,
+ QJsonObject &dict)
{
- QJsonObject dict;
- if (lookupSpecialRef(ref, &dict))
- return dict;
-
- dict.insert(QStringLiteral("handle"), qint64(ref));
+ QV4::Scope scope(engine);
+ QV4::ScopedValue typeString(scope, QV4::Runtime::typeofValue(engine, value));
+ dict.insert(QStringLiteral("type"), typeString->toQStringNoThrow());
- QV4::Scope scope(engine());
- QV4::ScopedValue value(scope, getValue(ref));
+ const QLatin1String valueKey("value");
switch (value->type()) {
case QV4::Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
- break;
+ return 0;
case QV4::Value::Undefined_Type:
- dict.insert(QStringLiteral("type"), QStringLiteral("undefined"));
- break;
+ dict.insert(valueKey, QJsonValue::Undefined);
+ return 0;
case QV4::Value::Null_Type:
+ // "null" is not the correct type, but we leave this in until QtC can deal with "object"
dict.insert(QStringLiteral("type"), QStringLiteral("null"));
- break;
+ dict.insert(valueKey, QJsonValue::Null);
+ return 0;
case QV4::Value::Boolean_Type:
- dict.insert(QStringLiteral("type"), QStringLiteral("boolean"));
- dict.insert(QStringLiteral("value"), value->booleanValue() ? QStringLiteral("true")
- : QStringLiteral("false"));
- break;
+ dict.insert(valueKey, value->booleanValue());
+ return 0;
case QV4::Value::Managed_Type:
- if (QV4::String *s = value->as<QV4::String>()) {
- dict.insert(QStringLiteral("type"), QStringLiteral("string"));
- dict.insert(QStringLiteral("value"), s->toQString());
- } else if (QV4::Object *o = value->as<QV4::Object>()) {
- dict.insert(QStringLiteral("type"), QStringLiteral("object"));
- dict.insert(QStringLiteral("properties"), collectProperties(o));
+ if (const QV4::String *s = value->as<QV4::String>()) {
+ dict.insert(valueKey, s->toQString());
+ } else if (const QV4::ArrayObject *a = value->as<QV4::ArrayObject>()) {
+ // size of an array is number of its numerical properties; We don't consider free form
+ // object properties here.
+ dict.insert(valueKey, qint64(a->getLength()));
+ return a;
+ } else if (const QV4::Object *o = value->as<QV4::Object>()) {
+ int numProperties = 0;
+ QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
+ QV4::PropertyAttributes attrs;
+ uint index;
+ QV4::ScopedProperty p(scope);
+ QV4::ScopedString name(scope);
+ while (true) {
+ it.next(name.getRef(), &index, p, &attrs);
+ if (attrs.isEmpty())
+ break;
+ else
+ ++numProperties;
+ }
+ dict.insert(valueKey, numProperties);
+ return o;
} else {
Q_UNREACHABLE();
}
- break;
+ return 0;
case QV4::Value::Integer_Type:
- dict.insert(QStringLiteral("type"), QStringLiteral("number"));
- dict.insert(QStringLiteral("value"), value->integerValue());
- break;
+ dict.insert(valueKey, value->integerValue());
+ return 0;
default: // double
- dict.insert(QStringLiteral("type"), QStringLiteral("number"));
- dict.insert(QStringLiteral("value"), value->doubleValue());
- break;
+ dict.insert(valueKey, value->doubleValue());
+ return 0;
}
+}
+
+QJsonObject QV4DataCollector::lookupRef(Ref ref)
+{
+ QJsonObject dict;
+ if (lookupSpecialRef(ref, &dict))
+ return dict;
+
+ dict.insert(QStringLiteral("handle"), qint64(ref));
+ QV4::Scope scope(engine());
+ QV4::ScopedValue value(scope, getValue(ref));
+
+ if (const QV4::Object *o = collectProperty(value, engine(), dict))
+ dict.insert(QStringLiteral("properties"), collectProperties(o));
return dict;
}
QJsonObject dict;
dict.insert(QStringLiteral("handle"), qint64(ref));
dict.insert(QStringLiteral("type"), QStringLiteral("function"));
- dict.insert(QStringLiteral("className"), QStringLiteral("Function"));
dict.insert(QStringLiteral("name"), functionName);
specialRefs.insert(ref, dict);
return true;
}
-QJsonArray QV4DataCollector::collectProperties(QV4::Object *object)
+QJsonArray QV4DataCollector::collectProperties(const QV4::Object *object)
{
QJsonArray res;
QJsonObject dict;
if (!name.isNull())
dict.insert(QStringLiteral("name"), name);
- Ref ref = addRef(value);
- dict.insert(QStringLiteral("ref"), qint64(ref));
- if (m_collectedRefs)
- m_collectedRefs->append(ref);
-
- // TODO: enable this when creator can handle it.
- if (false) {
- if (value->isManaged() && !value->isString()) {
- QV4::Scope scope(engine());
- QV4::ScopedObject obj(scope, value->as<QV4::Object>());
- dict.insert(QStringLiteral("propertycount"), qint64(obj->getLength()));
- }
+ if (value->isManaged() && !value->isString()) {
+ Ref ref = addRef(value);
+ dict.insert(QStringLiteral("ref"), qint64(ref));
+ if (m_collectedRefs)
+ m_collectedRefs->append(ref);
}
+ collectProperty(value, engine(), dict);
return dict;
}
QVERIFY(b_props.at(0).isObject());
QJsonObject b_head = b_props.at(0).toObject();
QCOMPARE(b_head.value("name").toString(), QStringLiteral("head"));
- QVERIFY(b_head.contains("ref"));
- QJsonObject b_head_value = frame0.collector->lookupRef(b_head.value("ref").toInt());
- QCOMPARE(b_head_value.value("type").toString(), QStringLiteral("number"));
- QCOMPARE(b_head_value.value("value").toDouble(), 1.0);
+ QCOMPARE(b_head.value("type").toString(), QStringLiteral("number"));
+ QCOMPARE(b_head.value("value").toDouble(), 1.0);
QVERIFY(b_props.at(1).isObject());
QJsonObject b_tail = b_props.at(1).toObject();
QCOMPARE(b_tail.value("name").toString(), QStringLiteral("tail"));
QCOMPARE(b_tail_props.size(), 2);
QJsonObject b_tail_head = b_tail_props.at(0).toObject();
QCOMPARE(b_tail_head.value("name").toString(), QStringLiteral("head"));
- QVERIFY(b_tail_head.contains("ref"));
- QJsonObject b_tail_head_value = frame0.collector->lookupRef(b_tail_head.value("ref").toInt());
- QCOMPARE(b_tail_head_value.value("type").toString(), QStringLiteral("string"));
- QCOMPARE(b_tail_head_value.value("value").toString(), QStringLiteral("asdf"));
+ QCOMPARE(b_tail_head.value("type").toString(), QStringLiteral("string"));
+ QCOMPARE(b_tail_head.value("value").toString(), QStringLiteral("asdf"));
QJsonObject b_tail_tail = b_tail_props.at(1).toObject();
QCOMPARE(b_tail_tail.value("name").toString(), QStringLiteral("tail"));
- QVERIFY(b_tail_tail.contains("ref"));
-
- QJsonObject b_tail_tail_value = frame0.collector->lookupRef(b_tail_tail.value("ref").toInt());
- QCOMPARE(b_tail_tail_value.value("type").toString(), QStringLiteral("null"));
+ QCOMPARE(b_tail_tail.value("type").toString(), QStringLiteral("null"));
+ QVERIFY(b_tail_tail.value("value").isNull());
}
void tst_qv4debugger::readContextInAllFrames()