aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorJüri Valdmann <juri.valdmann@qt.io>2018-10-12 16:56:14 +0200
committerJani Heikkinen <jani.heikkinen@qt.io>2018-11-02 16:44:11 +0000
commit627226520a2bbb977ce32a21bdffd2004cb28796 (patch)
treee3989c73887505a179e875baf2984be10fcbdda8 /src/qml/qml
parentf20839aed0f2e4fe9134a239adda4853d7bd204a (diff)
Expose let/const variables from imported JS scripts
This patch allows QML to access let/const variables defined in JS files. Detailed changes: - The recently added ContextType::ScriptImportedByQML is changed to avoid creating Push/PopScriptContext instructions, similar to ContextType::ESModule. - QV4::Module is changed to also work with CompilationUnits which are not ESModules. In this case QV4::Module will behave as if all lexically scoped variables were exported. - CompilationUnit is changed to support instantiating and evaluating QV4::Modules for non-ESModules as well. - QQmlTypeLoader is changed to always create QV4::Modules for evaluating scripts. For the non-ESModule case, the QV4::Module is evaluated inside a QV4::QmlContext, as before. - A pointer to the QV4::Module is added to QV4::QQmlContextWrapper, and used in virtualGet to access the let/const variables in the CallContext. Access is read-only. Fixes: QTBUG-69408 Change-Id: I6f299363fdf5e1c5a4a0f1d9e655b4dc5112dd00 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmltypeloader.cpp86
-rw-r--r--src/qml/qml/qqmltypeloader_p.h3
2 files changed, 31 insertions, 58 deletions
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 89b023c164..7480475ca7 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2881,30 +2881,9 @@ void QQmlTypeData::scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, co
QQmlScriptData::QQmlScriptData()
: typeNameCache(nullptr)
, m_loaded(false)
- , m_program(nullptr)
{
}
-QQmlScriptData::~QQmlScriptData()
-{
- delete m_program;
-}
-
-void QQmlScriptData::initialize(QQmlEngine *engine)
-{
- Q_ASSERT(!m_program);
- Q_ASSERT(engine);
- Q_ASSERT(!hasEngine());
-
- QV4::ExecutionEngine *v4 = engine->handle();
-
- m_program = new QV4::Script(v4, nullptr, m_precompiledScript);
-
- addToEngine(engine);
-
- addref();
-}
-
QQmlContextData *QQmlScriptData::qmlContextDataForContext(QQmlContextData *parentQmlContextData)
{
Q_ASSERT(parentQmlContextData && parentQmlContextData->engine);
@@ -2954,57 +2933,54 @@ QQmlContextData *QQmlScriptData::qmlContextDataForContext(QQmlContextData *paren
return qmlContextData;
}
-QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt)
+QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentQmlContextData)
{
if (m_loaded)
return m_value.value();
- Q_ASSERT(parentCtxt && parentCtxt->engine);
- QV4::ExecutionEngine *v4 = parentCtxt->engine->handle();
-
- if (m_precompiledScript->isESModule()) {
- m_loaded = true;
-
- m_value.set(v4, m_precompiledScript->instantiate(v4));
- if (!m_value.isNullOrUndefined())
- m_precompiledScript->evaluate();
+ Q_ASSERT(parentQmlContextData && parentQmlContextData->engine);
+ QV4::ExecutionEngine *v4 = parentQmlContextData->engine->handle();
+ QV4::Scope scope(v4);
- return m_value.value();
+ if (!hasEngine()) {
+ addToEngine(parentQmlContextData->engine);
+ addref();
}
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine);
- QV4::Scope scope(v4);
-
- // Create the script context if required
- QQmlContextDataRef ctxt(qmlContextDataForContext(parentCtxt));
+ QQmlContextDataRef qmlContextData = qmlContextDataForContext(parentQmlContextData);
+ QV4::Scoped<QV4::QmlContext> qmlExecutionContext(scope);
+ if (qmlContextData)
+ qmlExecutionContext =
+ QV4::QmlContext::create(v4->rootContext(), qmlContextData, /* scopeObject: */ nullptr);
- if (!hasEngine())
- initialize(parentCtxt->engine);
+ QV4::Scoped<QV4::Module> module(scope, m_precompiledScript->instantiate(v4));
+ if (module) {
+ if (qmlContextData) {
+ module->d()->scope->outer.set(v4, qmlExecutionContext->d());
+ qmlExecutionContext->d()->qml()->module.set(v4, module->d());
+ }
- if (!m_program) {
- if (m_precompiledScript->isSharedLibrary())
- m_loaded = true;
- return QV4::Encode::undefined();
+ module->evaluate();
}
- QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(v4->rootContext(), ctxt, nullptr));
-
- m_program->qmlContext.set(scope.engine, qmlContext);
- m_program->run();
- m_program->qmlContext.clear();
- if (scope.engine->hasException) {
- QQmlError error = scope.engine->catchExceptionAsQmlError();
+ if (v4->hasException) {
+ QQmlError error = v4->catchExceptionAsQmlError();
if (error.isValid())
- ep->warning(error);
+ QQmlEnginePrivate::get(v4)->warning(error);
}
- QV4::ScopedValue retval(scope, qmlContext->d()->qml());
- if (m_precompiledScript->isSharedLibrary()) {
- m_value.set(scope.engine, retval);
+ QV4::ScopedValue value(scope);
+ if (qmlContextData)
+ value = qmlExecutionContext->d()->qml();
+ else if (module)
+ value = module->d();
+
+ if (m_precompiledScript->isSharedLibrary() || m_precompiledScript->isESModule()) {
m_loaded = true;
+ m_value.set(v4, value);
}
- return retval->asReturnedValue();
+ return value->asReturnedValue();
}
void QQmlScriptData::clear()
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 29c91346de..5bb4e9d490 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -534,8 +534,6 @@ private:
QQmlScriptData();
public:
- ~QQmlScriptData() override;
-
QUrl url;
QString urlString;
QQmlTypeNameCache *typeNameCache;
@@ -556,7 +554,6 @@ private:
bool m_loaded;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_precompiledScript;
- QV4::Script *m_program;
QV4::PersistentValue m_value;
};