aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-30 03:28:47 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-30 18:21:32 +0200
commit62ee548d5fb8cbcbc4f126f761f125891dd79aed (patch)
tree79628c29245320ca3c17d7647c72653d2e308ba1 /src
parentc48d727e25f0a07d709a81765af6196bc0ddb4c5 (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')
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp7
-rw-r--r--src/qml/qml/qqmltypeloader.cpp133
-rw-r--r--src/qml/qml/qqmltypeloader_p.h5
-rw-r--r--src/qml/qml/qqmlvme.cpp106
-rw-r--r--src/qml/qml/qqmlvme_p.h1
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();