aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmltypeloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmltypeloader.cpp')
-rw-r--r--src/qml/qml/qqmltypeloader.cpp201
1 files changed, 119 insertions, 82 deletions
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index d713e9ee03..1e671542be 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -81,7 +81,7 @@
#define ASSERT_MAINTHREAD() do { if (m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in main thread"); } while (false)
#define ASSERT_LOADTHREAD() do { if (!m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in load thread"); } while (false)
-#define ASSERT_CALLBACK() do { if(!m_manager || !m_manager->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while(false)
+#define ASSERT_CALLBACK() do { if (!m_typeLoader || !m_typeLoader->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while (false)
#else
@@ -647,6 +647,8 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
{
Q_ASSERT(m_waitingFor.contains(blob));
Q_ASSERT(blob->status() == Error || blob->status() == Complete);
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler,
+ blob->url());
m_inCallback = true;
@@ -909,97 +911,116 @@ void QQmlTypeLoader::unlock()
m_thread->unlock();
}
-/*!
-Load the provided \a blob from the network or filesystem.
+struct PlainLoader {
+ void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->loadThread(blob);
+ }
+ void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->load(blob);
+ }
+ void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadAsync(blob);
+ }
+};
-The loader must be locked.
-*/
-void QQmlTypeLoader::load(QQmlDataBlob *blob, Mode mode)
+struct StaticLoader {
+ const QByteArray &data;
+ StaticLoader(const QByteArray &data) : data(data) {}
+
+ void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->loadWithStaticDataThread(blob, data);
+ }
+ void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadWithStaticData(blob, data);
+ }
+ void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadWithStaticDataAsync(blob, data);
+ }
+};
+
+struct CachedLoader {
+ const QQmlPrivate::CachedQmlUnit *unit;
+ CachedLoader(const QQmlPrivate::CachedQmlUnit *unit) : unit(unit) {}
+
+ void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->loadWithCachedUnitThread(blob, unit);
+ }
+ void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadWithCachedUnit(blob, unit);
+ }
+ void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
+ {
+ loader->m_thread->loadWithCachedUnit(blob, unit);
+ }
+};
+
+template<typename Loader>
+void QQmlTypeLoader::doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode)
{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlTypeLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()),
+ qWarning("QQmlTypeLoader::doLoad(%s): %s thread", qPrintable(blob->m_url.toString()),
m_thread->isThisThread()?"Compile":"Engine");
#endif
blob->startLoading();
if (m_thread->isThisThread()) {
unlock();
- loadThread(blob);
+ loader.loadThread(this, blob);
lock();
- } else if (mode == PreferSynchronous) {
+ } else if (mode == Asynchronous) {
+ blob->m_data.setIsAsync(true);
unlock();
- m_thread->load(blob);
+ loader.loadAsync(this, blob);
lock();
- if (!blob->isCompleteOrError())
- blob->m_data.setIsAsync(true);
} else {
- Q_ASSERT(mode == Asynchronous);
- blob->m_data.setIsAsync(true);
unlock();
- m_thread->loadAsync(blob);
+ loader.load(this, blob);
lock();
+ if (mode == PreferSynchronous) {
+ if (!blob->isCompleteOrError())
+ blob->m_data.setIsAsync(true);
+ } else {
+ Q_ASSERT(mode == Synchronous);
+ while (!blob->isCompleteOrError()) {
+ unlock();
+ m_thread->waitForNextMessage();
+ lock();
+ }
+ }
}
}
/*!
-Load the provided \a blob with \a data. The blob's URL is not used by the data loader in this case.
+Load the provided \a blob from the network or filesystem.
The loader must be locked.
*/
-void QQmlTypeLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode)
+void QQmlTypeLoader::load(QQmlDataBlob *blob, Mode mode)
{
-#ifdef DATABLOB_DEBUG
- qWarning("QQmlTypeLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()),
- m_thread->isThisThread()?"Compile":"Engine");
-#endif
+ doLoad(PlainLoader(), blob, mode);
+}
- blob->startLoading();
+/*!
+Load the provided \a blob with \a data. The blob's URL is not used by the data loader in this case.
- if (m_thread->isThisThread()) {
- unlock();
- loadWithStaticDataThread(blob, data);
- lock();
- } else if (mode == PreferSynchronous) {
- unlock();
- m_thread->loadWithStaticData(blob, data);
- lock();
- if (!blob->isCompleteOrError())
- blob->m_data.setIsAsync(true);
- } else {
- Q_ASSERT(mode == Asynchronous);
- blob->m_data.setIsAsync(true);
- unlock();
- m_thread->loadWithStaticDataAsync(blob, data);
- lock();
- }
+The loader must be locked.
+*/
+void QQmlTypeLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode)
+{
+ doLoad(StaticLoader(data), blob, mode);
}
void QQmlTypeLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode)
{
-#ifdef DATABLOB_DEBUG
- qWarning("QQmlTypeLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()),
- m_thread->isThisThread()?"Compile":"Engine");
-#endif
-
- blob->startLoading();
-
- if (m_thread->isThisThread()) {
- unlock();
- loadWithCachedUnitThread(blob, unit);
- lock();
- } else if (mode == PreferSynchronous) {
- unlock();
- m_thread->loadWithCachedUnit(blob, unit);
- lock();
- if (!blob->isCompleteOrError())
- blob->m_data.setIsAsync(true);
- } else {
- Q_ASSERT(mode == Asynchronous);
- blob->m_data.setIsAsync(true);
- unlock();
- m_thread->loadWithCachedUnitAsync(blob, unit);
- lock();
- }
+ doLoad(CachedLoader(unit), blob, mode);
}
void QQmlTypeLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data)
@@ -1194,6 +1215,8 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
{
QML_MEMORY_SCOPE_URL(blob->url());
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
+
blob->m_inCallback = true;
blob->dataReceived(d);
@@ -1212,6 +1235,8 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
{
QML_MEMORY_SCOPE_URL(blob->url());
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
+
blob->m_inCallback = true;
blob->initializeFromCachedUnit(unit);
@@ -1612,6 +1637,20 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
} else {
QQmlTypeLoader::load(typeData, mode);
}
+ } else if ((mode == PreferSynchronous || mode == Synchronous) && QQmlFile::isSynchronous(url)) {
+ // this was started Asynchronous, but we need to force Synchronous
+ // completion now (if at all possible with this type of URL).
+
+ if (!m_thread->isThisThread()) {
+ // this only works when called directly from the UI thread, but not
+ // when recursively called on the QML thread via resolveTypes()
+
+ while (!typeData->isCompleteOrError()) {
+ unlock();
+ m_thread->waitForNextMessage();
+ lock();
+ }
+ }
}
typeData->addref();
@@ -1623,12 +1662,12 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
Returns a QQmlTypeData for the given \a data with the provided base \a url. The
QQmlTypeData will not be cached.
*/
-QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url)
+QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url, Mode mode)
{
LockHolder<QQmlTypeLoader> holder(this);
QQmlTypeData *typeData = new QQmlTypeData(url, this);
- QQmlTypeLoader::loadWithStaticData(typeData, data);
+ QQmlTypeLoader::loadWithStaticData(typeData, data, mode);
return typeData;
}
@@ -2114,6 +2153,7 @@ void QQmlTypeData::dataReceived(const Data &data)
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
if (!compiler.generateFromQml(code, finalUrlString(), m_document.data())) {
QList<QQmlError> errors;
+ errors.reserve(compiler.errors.count());
foreach (const QQmlJS::DiagnosticMessage &msg, compiler.errors) {
QQmlError e;
e.setUrl(finalUrl());
@@ -2238,8 +2278,6 @@ void QQmlTypeData::compile()
m_compiledData = new QQmlCompiledData(typeLoader()->engine());
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, finalUrlString());
-
QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, m_document.data());
if (!compiler.compile()) {
setError(compiler.compilationErrors());
@@ -2282,8 +2320,8 @@ void QQmlTypeData::resolveTypes()
m_namespaces.insert(csRef.prefix);
}
- int majorVersion = -1;
- int minorVersion = -1;
+ int majorVersion = csRef.majorVersion > -1 ? csRef.majorVersion : -1;
+ int minorVersion = csRef.minorVersion > -1 ? csRef.minorVersion : -1;
if (!resolveType(typeName, majorVersion, minorVersion, ref))
return;
@@ -2452,12 +2490,10 @@ void QQmlScriptData::initialize(QQmlEngine *engine)
addref();
}
-QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt)
+QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt)
{
if (m_loaded)
- return m_value;
-
- QV4::PersistentValue rv;
+ return m_value.value();
Q_ASSERT(parentCtxt && parentCtxt->engine);
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine);
@@ -2507,8 +2543,9 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
} else {
scriptsArray = ctxt->importedScripts.valueRef();
}
+ QV4::ScopedValue v(scope);
for (int ii = 0; ii < scripts.count(); ++ii)
- scriptsArray->putIndexed(ii, *scripts.at(ii)->scriptData()->scriptValueForContext(ctxt).valueRef());
+ scriptsArray->putIndexed(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(ctxt)));
if (!hasEngine())
initialize(parentCtxt->engine);
@@ -2516,13 +2553,13 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
if (!m_program) {
if (shared)
m_loaded = true;
- return QV4::PersistentValue();
+ return QV4::Encode::undefined();
}
- QV4::ScopedValue qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0));
- QV4::QmlContextWrapper::takeContextOwnership(qmlglobal);
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->rootContext()->newQmlContext(ctxt, 0));
+ qmlContext->takeContextOwnership();
- m_program->qml.set(scope.engine, qmlglobal);
+ m_program->qmlContext.set(scope.engine, qmlContext);
m_program->run();
if (scope.engine->hasException) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
@@ -2530,13 +2567,13 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
ep->warning(error);
}
- rv.set(scope.engine, qmlglobal);
+ QV4::ScopedValue retval(scope, qmlContext->d()->qml);
if (shared) {
- m_value = rv;
+ m_value.set(scope.engine, retval);
m_loaded = true;
}
- return rv;
+ return retval->asReturnedValue();
}
void QQmlScriptData::clear()
@@ -2594,7 +2631,7 @@ void QQmlScriptBlob::dataReceived(const Data &data)
return;
}
if (!unit) {
- unit.take(new EmptyCompilationUnit);
+ unit.adopt(new EmptyCompilationUnit);
}
irUnit.javaScriptCompilationUnit = unit;
irUnit.imports = collector.imports;