Skip to content

Commit

Permalink
Fix v8 handle management in QSGLoader
Browse files Browse the repository at this point in the history
Previously, setting the source to a remote url and specified some
initial property values while active was false, and then setting
active to true, would cause undefined behaviour.

This commit ensures that the handles are managed correctly, and that
an appropriate v8 context exists during object creation with initial
property values specified.

Task-number: QTBUG-21868
Change-Id: I101c6546537aa05aaeb420195aca670bc71f31e1
Reviewed-on: http://codereview.qt-project.org/6109
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
  • Loading branch information
Chris Adams authored and Qt by Nokia committed Oct 6, 2011
1 parent 71611d0 commit e29f198
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/declarative/items/qsgloader.cpp
Expand Up @@ -266,7 +266,6 @@ void QSGLoader::setActive(bool newVal)
} else {
loadFromSourceComponent();
}
d->disposeInitialPropertyValues(); // release persistent handles
} else {
if (d->item) {
QSGItemPrivate *p = QSGItemPrivate::get(d->item);
Expand Down Expand Up @@ -487,6 +486,7 @@ void QSGLoader::setSource(QDeclarativeV8Function *args)
d->clear();
QUrl sourceUrl = d->resolveSourceUrl(args);
if (!ipv.IsEmpty()) {
d->disposeInitialPropertyValues();
d->initialPropertyValues = qPersistentNew(ipv);
d->qmlGlobalForIpv = qPersistentNew(args->qmlGlobal());
}
Expand Down Expand Up @@ -539,6 +539,7 @@ void QSGLoaderPrivate::_q_sourceLoaded()
emit q->sourceComponentChanged();
emit q->statusChanged();
emit q->progressChanged();
disposeInitialPropertyValues(); // cleanup
return;
}

Expand All @@ -557,6 +558,7 @@ void QSGLoaderPrivate::_q_sourceLoaded()
completeCreateWithInitialPropertyValues(c, obj, initialPropertyValues, qmlGlobalForIpv);
delete obj;
delete ctxt;
disposeInitialPropertyValues(); // cleanup
return;
}
if (obj) {
Expand Down Expand Up @@ -589,6 +591,7 @@ void QSGLoaderPrivate::_q_sourceLoaded()
emit q->itemChanged();
emit q->loaded();
}
disposeInitialPropertyValues(); // cleanup
}

/*!
Expand Down
3 changes: 3 additions & 0 deletions src/declarative/qml/qdeclarativecomponent.cpp
Expand Up @@ -1134,6 +1134,9 @@ QObject *QDeclarativeComponentPrivate::completeCreateObjectWithInitialProperties
{
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
QV8Engine *v8engine = ep->v8engine();

v8::HandleScope handle_scope;
v8::Context::Scope scope(v8engine->context());
v8::Handle<v8::Value> ov = v8engine->newQObject(toCreate);
Q_ASSERT(ov->IsObject());
v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(ov);
Expand Down
20 changes: 20 additions & 0 deletions tests/auto/declarative/qsgloader/data/initialPropertyValues.8.qml
@@ -0,0 +1,20 @@
import QtQuick 2.0

Item {
id: root
property int initialValue: 0

Loader {
id: loader
objectName: "loader"
active: false
onLoaded: {
root.initialValue = loader.item.canary; // should be six
}
}

Component.onCompleted: {
loader.setSource("http://127.0.0.1:14450/InitialPropertyValuesComponent.qml", {"canary": 6});
loader.active = true;
}
}
11 changes: 11 additions & 0 deletions tests/auto/declarative/qsgloader/tst_qsgloader.cpp
Expand Up @@ -651,6 +651,11 @@ void tst_QSGLoader::initialPropertyValues_data()
<< QStringList()
<< (QStringList() << "loaderValue" << "createObjectValue")
<< (QVariantList() << 1 << 1);

QTest::newRow("ensure initial property values aren't disposed prior to component completion") << TEST_FILE("initialPropertyValues.8.qml")
<< QStringList()
<< (QStringList() << "initialValue")
<< (QVariantList() << 6);
}

void tst_QSGLoader::initialPropertyValues()
Expand All @@ -660,12 +665,18 @@ void tst_QSGLoader::initialPropertyValues()
QFETCH(QStringList, propertyNames);
QFETCH(QVariantList, propertyValues);

TestHTTPServer server(SERVER_PORT);
QVERIFY(server.isValid());
server.serveDirectory(SRCDIR "/data");

foreach (const QString &warning, expectedWarnings)
QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());

QDeclarativeComponent component(&engine, qmlFile);
QObject *object = component.create();
QVERIFY(object != 0);
qApp->processEvents();
QTest::qWait(50);

for (int i = 0; i < propertyNames.size(); ++i)
QCOMPARE(object->property(propertyNames.at(i).toAscii().constData()), propertyValues.at(i));
Expand Down

0 comments on commit e29f198

Please sign in to comment.