diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-09-30 03:28:47 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-30 18:21:32 +0200 |
commit | 62ee548d5fb8cbcbc4f126f761f125891dd79aed (patch) | |
tree | 79628c29245320ca3c17d7647c72653d2e308ba1 /src/qml/qml/qqmltypeloader.cpp | |
parent | c48d727e25f0a07d709a81765af6196bc0ddb4c5 (diff) |
Fix support for JS imports in QML files in the new compiler
Remove the v4 value initialization for imported scripts code out of the VME
(the method didn't even need any members of the VME class) and into ScriptData,
for re-use on the QmlObjectCreator side.
Also add the script index setup for the import cache (used by qml context
wrapper) to the type loader.
Change-Id: Idc3953a48f6fb66d008008e88a2b9b556c775537
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml/qqmltypeloader.cpp')
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 07639aa6ba..52b42e85a3 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -41,6 +41,8 @@ #include "qqmltypeloader_p.h" #include "qqmlabstracturlinterceptor.h" +#include "qqmlcontextwrapper_p.h" +#include "qqmlexpression_p.h" #include <private/qqmlengine_p.h> #include <private/qqmlglobal_p.h> @@ -2306,6 +2308,28 @@ void QQmlTypeData::compile() } } + // Collect imported scripts + m_compiledData->scripts.reserve(m_scripts.count()); + for (int scriptIndex = 0; scriptIndex < m_scripts.count(); ++scriptIndex) { + const ScriptReference &script = m_scripts.at(scriptIndex); + + QString qualifier = script.qualifier; + QString enclosingNamespace; + + const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.')); + if (lastDotIndex != -1) { + enclosingNamespace = qualifier.left(lastDotIndex); + qualifier = qualifier.mid(lastDotIndex+1); + } + + m_compiledData->importCache->add(qualifier, scriptIndex, enclosingNamespace); + QQmlScriptData *scriptData = script.script->scriptData(); + scriptData->addref(); + m_compiledData->scripts << scriptData; + } + + // Compile JS binding expressions and signal handlers + JSCodeGen jsCodeGen; jsCodeGen.generateJSCodeForFunctionsAndBindings(finalUrlString(), parsedQML.data()); @@ -2315,6 +2339,8 @@ void QQmlTypeData::compile() isel->setUseFastLookups(false); QV4::CompiledData::CompilationUnit *jsUnit = isel->compile(/*generated unit data*/false); + // Generate QML compiled type data structures + QmlUnitGenerator qmlGenerator; QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(*parsedQML.data()); @@ -2331,6 +2357,8 @@ void QQmlTypeData::compile() QList<QQmlError> errors; + // Build property caches and VME meta object data + m_compiledData->datas.reserve(qmlUnit->nObjects); m_compiledData->propertyCaches.reserve(qmlUnit->nObjects); @@ -2366,6 +2394,8 @@ void QQmlTypeData::compile() } } + // Resolve component boundaries and aliases + if (errors.isEmpty()) { // Scan for components, determine their scopes and resolve aliases within the scope. QQmlComponentAndAliasResolver resolver(m_compiledData->url, m_compiledData->qmlUnit, m_compiledData->resolvedTypes, m_compiledData->propertyCaches, @@ -2621,6 +2651,109 @@ QQmlScriptData::~QQmlScriptData() } } +void QQmlScriptData::initialize(QQmlEngine *engine) +{ + Q_ASSERT(!m_program); + Q_ASSERT(engine); + Q_ASSERT(!hasEngine()); + + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + QV8Engine *v8engine = ep->v8engine(); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8engine); + + m_program = new QV4::Script(v4, QV4::ObjectRef::null(), m_precompiledScript); + + addToEngine(engine); + + addref(); +} + +QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt) +{ + if (m_loaded) + return m_value; + + QV4::PersistentValue rv; + + Q_ASSERT(parentCtxt && parentCtxt->engine); + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine); + QV8Engine *v8engine = ep->v8engine(); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(parentCtxt->engine); + QV4::Scope scope(v4); + + bool shared = pragmas & QQmlScript::Object::ScriptBlock::Shared; + + QQmlContextData *effectiveCtxt = parentCtxt; + if (shared) + effectiveCtxt = 0; + + // Create the script context if required + QQmlContextData *ctxt = new QQmlContextData; + ctxt->isInternal = true; + ctxt->isJSContext = true; + if (shared) + ctxt->isPragmaLibraryContext = true; + else + ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext; + ctxt->url = url; + ctxt->urlString = urlString; + + // For backward compatibility, if there are no imports, we need to use the + // imports from the parent context. See QTBUG-17518. + if (!importCache->isEmpty()) { + ctxt->imports = importCache; + } else if (effectiveCtxt) { + ctxt->imports = effectiveCtxt->imports; + ctxt->importedScripts = effectiveCtxt->importedScripts; + } + + if (ctxt->imports) { + ctxt->imports->addref(); + } + + if (effectiveCtxt) { + ctxt->setParent(effectiveCtxt, true); + } else { + ctxt->engine = parentCtxt->engine; // Fix for QTBUG-21620 + } + + for (int ii = 0; ii < scripts.count(); ++ii) { + ctxt->importedScripts << scripts.at(ii)->scriptData()->scriptValueForContext(ctxt); + } + + if (!hasEngine()) + initialize(parentCtxt->engine); + + if (!m_program) { + if (shared) + m_loaded = true; + return QV4::PersistentValue(); + } + + QV4::ScopedValue qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v8engine, ctxt, 0)); + QV4::QmlContextWrapper::takeContextOwnership(qmlglobal); + + QV4::ExecutionContext *ctx = QV8Engine::getV4(v8engine)->current; + try { + m_program->qml = qmlglobal; + m_program->run(); + } catch (QV4::Exception &e) { + e.accept(ctx); + QQmlError error; + QQmlExpressionPrivate::exceptionToError(e, error); + if (error.isValid()) + ep->warning(error); + } + + rv = qmlglobal; + if (shared) { + m_value = rv; + m_loaded = true; + } + + return rv; +} + void QQmlScriptData::clear() { if (importCache) { |