diff options
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 133 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlvme.cpp | 106 | ||||
-rw-r--r-- | src/qml/qml/qqmlvme_p.h | 1 |
5 files changed, 144 insertions, 108 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 5d29a57441..55858e0b12 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -527,6 +527,13 @@ QObject *QmlObjectCreator::create(int subComponentIndex, QObject *parent) } context->setIdPropertyData(mapping); + if (subComponentIndex == -1) { + foreach (QQmlScriptData *script, compiledData->scripts) + context->importedScripts << script->scriptValueForContext(context); + } else if (parentContext) { + context->importedScripts = parentContext->importedScripts; + } + QObject *instance = createInstance(objectToCreate, parent); if (instance) { QQmlData *ddata = QQmlData::get(instance); 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) { diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index f6eea6c248..b9bf056cb3 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -508,8 +508,7 @@ public: QList<QQmlScriptBlob *> scripts; QQmlScript::Object::ScriptBlock::Pragmas pragmas; - bool isInitialized() const { return hasEngine(); } - void initialize(QQmlEngine *); + QV4::PersistentValue scriptValueForContext(QQmlContextData *parentCtxt); protected: virtual void clear(); // From QQmlCleanup @@ -518,6 +517,8 @@ private: friend class QQmlVME; friend class QQmlScriptBlob; + void initialize(QQmlEngine *); + bool m_loaded; QV4::CompiledData::CompilationUnit *m_precompiledScript; QV4::Script *m_program; diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 5bf679d7a3..21bffee7a7 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -768,7 +768,7 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, QML_END_INSTR(StoreSignal) QML_BEGIN_INSTR(StoreImportedScript) - CTXT->importedScripts << run(CTXT, SCRIPTS.at(instr.value)); + CTXT->importedScripts << SCRIPTS.at(instr.value)->scriptValueForContext(CTXT); QML_END_INSTR(StoreImportedScript) QML_BEGIN_INSTR(StoreScriptString) @@ -1077,110 +1077,6 @@ void QQmlVME::reset() creationContext = 0; } -// Must be called with a handle scope and context -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 QQmlVME::run(QQmlContextData *parentCtxt, QQmlScriptData *script) -{ - if (script->m_loaded) - return script->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 = script->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 = script->url; - ctxt->urlString = script->urlString; - - // For backward compatibility, if there are no imports, we need to use the - // imports from the parent context. See QTBUG-17518. - if (!script->importCache->isEmpty()) { - ctxt->imports = script->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 < script->scripts.count(); ++ii) { - ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData()); - } - - if (!script->isInitialized()) - script->initialize(parentCtxt->engine); - - if (!script->m_program) { - if (shared) - script->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 { - script->m_program->qml = qmlglobal; - script->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) { - script->m_value = rv; - script->m_loaded = true; - } - - return rv; -} - #ifdef QML_THREADED_VME_INTERPRETER void *const *QQmlVME::instructionJumpTable() { diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h index 09e3237aee..5e76143cca 100644 --- a/src/qml/qml/qqmlvme_p.h +++ b/src/qml/qml/qqmlvme_p.h @@ -151,7 +151,6 @@ private: , void *const**storeJumpTable = 0 #endif ); - QV4::PersistentValue run(QQmlContextData *, QQmlScriptData *); #ifdef QML_THREADED_VME_INTERPRETER static void *const*instructionJumpTable(); |