diff options
Diffstat (limited to 'src/qml/qml/qqmlscriptblob.cpp')
-rw-r--r-- | src/qml/qml/qqmlscriptblob.cpp | 142 |
1 files changed, 66 insertions, 76 deletions
diff --git a/src/qml/qml/qqmlscriptblob.cpp b/src/qml/qml/qqmlscriptblob.cpp index 7b7a842d04..fa9a41e801 100644 --- a/src/qml/qml/qqmlscriptblob.cpp +++ b/src/qml/qml/qqmlscriptblob.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <private/qqmlengine_p.h> #include <private/qqmlirbuilder_p.h> @@ -68,14 +32,18 @@ QQmlRefPointer<QQmlScriptData> QQmlScriptBlob::scriptData() const return m_scriptData; } +bool QQmlScriptBlob::isNative() const +{ + return m_scriptData && !m_scriptData->m_value.isEmpty(); +} + void QQmlScriptBlob::dataReceived(const SourceCodeData &data) { - if (diskCacheEnabled()) { - QQmlRefPointer<QV4::ExecutableCompilationUnit> unit - = QV4::ExecutableCompilationUnit::create(); + if (readCacheFile()) { + auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>(); QString error; if (unit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) { - initializeFromCompilationUnit(unit); + initializeFromCompilationUnit(std::move(unit)); return; } else { qCDebug(DBG_DISK_CACHE()) << "Error loading" << urlString() << "from disk cache:" << error; @@ -97,7 +65,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) return; } - QV4::CompiledData::CompilationUnit unit; + QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit; if (m_isModule) { QList<QQmlJS::DiagnosticMessage> diagnostics; @@ -132,28 +100,26 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data) unit = std::move(irUnit.javaScriptCompilationUnit); } - auto executableUnit = QV4::ExecutableCompilationUnit::create(std::move(unit)); - - if (diskCacheEnabled()) { + if (writeCacheFile()) { QString errorString; - if (executableUnit->saveToDisk(url(), &errorString)) { + if (unit->saveToDisk(url(), &errorString)) { QString error; - if (!executableUnit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) { + if (!unit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) { // ignore error, keep using the in-memory compilation unit. } } else { qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" - << executableUnit->fileName() << "to disk:" << errorString; + << unit->fileName() << "to disk:" << errorString; } } - initializeFromCompilationUnit(executableUnit); + initializeFromCompilationUnit(std::move(unit)); } -void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) +void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *cachedUnit) { - initializeFromCompilationUnit(QV4::ExecutableCompilationUnit::create( - QV4::CompiledData::CompilationUnit(unit->qmlData, unit->aotCompiledFunctions, urlString(), finalUrlString()))); + initializeFromCompilationUnit(QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>( + cachedUnit->qmlData, cachedUnit->aotCompiledFunctions, urlString(), finalUrlString())); } void QQmlScriptBlob::done() @@ -162,15 +128,15 @@ void QQmlScriptBlob::done() return; // Check all script dependencies for errors - for (int ii = 0; ii < m_scripts.count(); ++ii) { + for (int ii = 0; ii < m_scripts.size(); ++ii) { const ScriptReference &script = m_scripts.at(ii); Q_ASSERT(script.script->isCompleteOrError()); if (script.script->isError()) { QList<QQmlError> errors = script.script->errors(); QQmlError error; error.setUrl(url()); - error.setLine(qmlConvertSourceCoordinate<quint32, int>(script.location.line)); - error.setColumn(qmlConvertSourceCoordinate<quint32, int>(script.location.column)); + error.setLine(qmlConvertSourceCoordinate<quint32, int>(script.location.line())); + error.setColumn(qmlConvertSourceCoordinate<quint32, int>(script.location.column())); error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString())); errors.prepend(error); setError(errors); @@ -183,7 +149,7 @@ void QQmlScriptBlob::done() QSet<QString> ns; - for (int scriptIndex = 0; scriptIndex < m_scripts.count(); ++scriptIndex) { + for (int scriptIndex = 0; scriptIndex < m_scripts.size(); ++scriptIndex) { const ScriptReference &script = m_scripts.at(scriptIndex); m_scriptData->scripts.append(script.script); @@ -197,7 +163,7 @@ void QQmlScriptBlob::done() m_scriptData->typeNameCache->add(script.qualifier, scriptIndex, script.nameSpace); } - m_importCache.populateCache(m_scriptData->typeNameCache.data()); + m_importCache->populateCache(m_scriptData->typeNameCache.data()); } m_scripts.clear(); } @@ -218,28 +184,29 @@ void QQmlScriptBlob::scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, m_scripts << ref; } -void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit) +void QQmlScriptBlob::initializeFromCompilationUnit( + QQmlRefPointer<QV4::CompiledData::CompilationUnit> &&unit) { Q_ASSERT(!m_scriptData); + Q_ASSERT(unit); + m_scriptData.adopt(new QQmlScriptData()); m_scriptData->url = finalUrl(); m_scriptData->urlString = finalUrlString(); m_scriptData->m_precompiledScript = unit; - m_importCache.setBaseUrl(finalUrl(), finalUrlString()); - - QQmlRefPointer<QV4::ExecutableCompilationUnit> script = m_scriptData->m_precompiledScript; + m_importCache->setBaseUrl(finalUrl(), finalUrlString()); if (!m_isModule) { QList<QQmlError> errors; - for (quint32 i = 0, count = script->importCount(); i < count; ++i) { - const QV4::CompiledData::Import *import = script->importAt(i); + for (quint32 i = 0, count = unit->importCount(); i < count; ++i) { + const QV4::CompiledData::Import *import = unit->importAt(i); if (!addImport(import, {}, &errors)) { Q_ASSERT(errors.size()); QQmlError error(errors.takeFirst()); - error.setUrl(m_importCache.baseUrl()); - error.setLine(import->location.line); - error.setColumn(import->location.column); + error.setUrl(m_importCache->baseUrl()); + error.setLine(import->location.line()); + error.setColumn(import->location.column()); errors.prepend(error); // put it back on the list after filling out information. setError(errors); return; @@ -247,19 +214,42 @@ void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::Exe } } - auto *v4 = QQmlEnginePrivate::getV4Engine(typeLoader()->engine()); - - v4->injectModule(unit); + const QStringList moduleRequests = unit->moduleRequests(); + for (const QString &request: moduleRequests) { + const QUrl relativeRequest = QUrl(request); + if (m_typeLoader->injectedScript(relativeRequest)) + continue; - for (const QString &request: unit->moduleRequests()) { - if (v4->moduleForUrl(QUrl(request), unit.data())) + const QUrl absoluteRequest = unit->finalUrl().resolved(relativeRequest); + QQmlRefPointer<QQmlScriptBlob> absoluteBlob = typeLoader()->getScript(absoluteRequest); + if (absoluteBlob->m_scriptData && absoluteBlob->m_scriptData->m_precompiledScript) continue; - const QUrl absoluteRequest = unit->finalUrl().resolved(QUrl(request)); - QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(absoluteRequest); - addDependency(blob.data()); - scriptImported(blob, /* ### */QV4::CompiledData::Location(), /*qualifier*/QString(), /*namespace*/QString()); + addDependency(absoluteBlob.data()); + scriptImported( + absoluteBlob, /* ### */QV4::CompiledData::Location(), /*qualifier*/QString(), + /*namespace*/QString()); } } + +/*! + \internal + + This initializes a dummy script blob from a "native" ECMAScript module. + Native modules are just JavaScript values, possibly objects with members. + + \sa QJSEngine::registerModule() + */ +void QQmlScriptBlob::initializeFromNative(const QV4::Value &value) +{ + Q_ASSERT(!m_scriptData); + m_scriptData.adopt(new QQmlScriptData()); + m_scriptData->url = finalUrl(); + m_scriptData->urlString = finalUrlString(); + m_scriptData->m_loaded = true; + m_scriptData->m_value.set(QQmlEnginePrivate::getV4Engine(typeLoader()->engine()), value); + m_importCache->setBaseUrl(finalUrl(), finalUrlString()); +} + QT_END_NAMESPACE |