From 9e71faae038de4c41c206f1321da1b37ab6ca8b1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 4 Oct 2014 17:18:15 +0200 Subject: Fix QQmlExpression/QQmlScriptString/QQmlBinding crashes In the QQmlScriptString we store the binding id and it is an index into the runtimeFunctions array of the compilation unit. However we don't store the compilation unit and instead in QQmlBinding and QQmlExpression try to retrieve it from the cache via the context url (we have the context after all). That turns out to be not a reliable way, as sometimes the URL might slightly differ from the originally compiled cache (qrc:/// turning to qrc:/ maybe). Consequently the type is (unnecessarily) compiled again and unfortunately not _linked_, therefore the runtime functions array is empty. Another option is that when the component was created from a QByteArray, then no entry exists in the cache in the first place. This patch addresses the problem by storing a reference to the compilation unit in the QQmlContextData. That we can safely retrieve and it'll make sure the compilation unit also stays alive. In the process of that the manual reference counting was switched over to QQmlRefCount and QQmlRefPointer for QV4::CompilationUnit. Task-number: QTBUG-41193 Change-Id: I9111f9a3b65618e453954abcd789c039e65a94f7 Reviewed-by: Lars Knoll --- src/qml/qml/qqmltypeloader.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'src/qml/qml/qqmltypeloader.cpp') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 0e2d4d027a..1b222fe1a3 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2541,7 +2541,6 @@ void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData: QQmlScriptData::QQmlScriptData() : importCache(0) , m_loaded(false) - , m_precompiledScript(0) , m_program(0) { } @@ -2549,10 +2548,6 @@ QQmlScriptData::QQmlScriptData() QQmlScriptData::~QQmlScriptData() { delete m_program; - if (m_precompiledScript) { - m_precompiledScript->deref(); - m_precompiledScript = 0; - } } void QQmlScriptData::initialize(QQmlEngine *engine) @@ -2713,13 +2708,10 @@ void QQmlScriptBlob::dataReceived(const Data &data) } QList errors; - QV4::CompiledData::CompilationUnit *unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors); - if (unit) - unit->ref(); + QQmlRefPointer unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors); + // No need to addref on unit, it's initial refcount is 1 source.clear(); if (!errors.isEmpty()) { - if (unit) - unit->deref(); setError(errors); return; } @@ -2732,7 +2724,6 @@ void QQmlScriptBlob::dataReceived(const Data &data) unit->data = unitData; initializeFromCompilationUnit(unit); - unit->deref(); } void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) @@ -2805,8 +2796,6 @@ void QQmlScriptBlob::initializeFromCompilationUnit(QV4::CompiledData::Compilatio m_scriptData->url = finalUrl(); m_scriptData->urlString = finalUrlString(); m_scriptData->m_precompiledScript = unit; - if (m_scriptData->m_precompiledScript) - m_scriptData->m_precompiledScript->ref(); m_importCache.setBaseUrl(finalUrl(), finalUrlString()); -- cgit v1.2.3