aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlcontextwrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmlcontextwrapper.cpp')
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp137
1 files changed, 128 insertions, 9 deletions
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index c867b6e126..0b3b282061 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -47,9 +47,10 @@
#include <private/qv4engine_p.h>
#include <private/qv4value_p.h>
-#include <private/qv4functionobject_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4mm_p.h>
+#include <private/qv4function_p.h>
+#include <private/qv4compileddata_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qqmllistwrapper_p.h>
@@ -62,7 +63,7 @@ DEFINE_MANAGED_VTABLE(QmlContextWrapper);
QmlContextWrapper::QmlContextWrapper(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext)
: Object(QV8Engine::getV4(engine)),
v8(engine), readOnly(true), ownsContext(ownsContext), isNullWrapper(false),
- context(context), scopeObject(scopeObject)
+ context(context), scopeObject(scopeObject), idObjectsWrapper(0)
{
vtbl = &static_vtbl;
}
@@ -135,7 +136,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *has
QV4::Scope scope(v4);
QmlContextWrapper *resource = m->as<QmlContextWrapper>();
if (!resource)
- v4->current->throwTypeError();
+ return v4->current->throwTypeError();
// In V8 the JS global object would come _before_ the QML global object,
// so simulate that here.
@@ -191,11 +192,8 @@ ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *has
if (hasProperty)
*hasProperty = true;
if (r.scriptIndex != -1) {
- int index = r.scriptIndex;
- if (index < context->importedScripts.count())
- return context->importedScripts.at(index).value();
- else
- return QV4::Primitive::undefinedValue().asReturnedValue();
+ QV4::ScopedObject scripts(scope, context->importedScripts);
+ return scripts->getIndexed(r.scriptIndex);
} else if (r.type) {
return QmlTypeWrapper::create(engine, scopeObject, r.type);
} else if (r.importNamespace) {
@@ -281,9 +279,13 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val
{
ExecutionEngine *v4 = m->engine();
QV4::Scope scope(v4);
+ if (scope.hasException())
+ return;
QV4::Scoped<QmlContextWrapper> wrapper(scope, m->as<QmlContextWrapper>());
- if (!wrapper)
+ if (!wrapper) {
v4->current->throwTypeError();
+ return;
+ }
if (wrapper->isNullWrapper) {
if (wrapper && wrapper->readOnly) {
@@ -291,6 +293,7 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val
QLatin1Char('"');
Scoped<String> e(scope, v4->current->engine->newString(error));
v4->current->throwError(e);
+ return;
}
Object::put(m, name, value);
@@ -341,6 +344,7 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
v4->current->throwError(error);
+ return;
}
Object::put(m, name, value);
@@ -351,4 +355,119 @@ void QmlContextWrapper::destroy(Managed *that)
static_cast<QmlContextWrapper *>(that)->~QmlContextWrapper();
}
+void QmlContextWrapper::markObjects(Managed *m, ExecutionEngine *engine)
+{
+ QmlContextWrapper *This = static_cast<QmlContextWrapper*>(m);
+ if (This->idObjectsWrapper)
+ This->idObjectsWrapper->mark(engine);
+ Object::markObjects(m, engine);
+}
+
+void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const CompiledData::Function *compiledFunction)
+{
+ // Let the caller check and avoid the function call :)
+ Q_ASSERT(compiledFunction->hasQmlDependencies());
+
+ QQmlEnginePrivate *ep = engine->v8Engine->engine() ? QQmlEnginePrivate::get(engine->v8Engine->engine()) : 0;
+ if (!ep)
+ return;
+ QQmlEnginePrivate::PropertyCapture *capture = ep->propertyCapture;
+ if (!capture)
+ return;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QmlContextWrapper> contextWrapper(scope, engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>());
+ QQmlContextData *qmlContext = contextWrapper->getContext();
+
+ const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
+ const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
+ for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency)
+ capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings);
+
+ const quint32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
+ const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
+ for (int i = 0; i < contextPropertyDependencyCount; ++i) {
+ const int propertyIndex = *contextPropertyDependency++;
+ const int notifyIndex = *contextPropertyDependency++;
+ capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex);
+ }
+
+ QObject *scopeObject = contextWrapper->getScopeObject();
+ const quint32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
+ const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
+ for (int i = 0; i < scopePropertyDependencyCount; ++i) {
+ const int propertyIndex = *scopePropertyDependency++;
+ const int notifyIndex = *scopePropertyDependency++;
+ capture->captureProperty(scopeObject, propertyIndex, notifyIndex);
+ }
+
+}
+
+ReturnedValue QmlContextWrapper::idObjectsArray()
+{
+ if (!idObjectsWrapper) {
+ ExecutionEngine *v4 = engine();
+ idObjectsWrapper = new (v4->memoryManager) QQmlIdObjectsArray(v4, this);
+ }
+ return idObjectsWrapper->asReturnedValue();
+}
+
+ReturnedValue QmlContextWrapper::qmlSingletonWrapper(const StringRef &name)
+{
+ if (!context->imports)
+ return Encode::undefined();
+ // Search for attached properties, enums and imported scripts
+ QQmlTypeNameCache::Result r = context->imports->query(name);
+
+ Q_ASSERT(r.isValid());
+ Q_ASSERT(r.type);
+ Q_ASSERT(r.type->isSingleton());
+
+ QQmlEngine *e = v8->engine();
+ QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
+ siinfo->init(e);
+
+ QObject *qobjectSingleton = siinfo->qobjectApi(e);
+ return QV4::QObjectWrapper::wrap(engine(), qobjectSingleton);
+}
+
+DEFINE_MANAGED_VTABLE(QQmlIdObjectsArray);
+
+QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QmlContextWrapper *contextWrapper)
+ : Object(engine)
+ , contextWrapper(contextWrapper)
+{
+ vtbl = &static_vtbl;
+}
+
+ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasProperty)
+{
+ QQmlIdObjectsArray *This = static_cast<QQmlIdObjectsArray*>(m);
+ QQmlContextData *context = This->contextWrapper->getContext();
+ if (!context) {
+ if (hasProperty)
+ *hasProperty = false;
+ return Encode::undefined();
+ }
+ if (index >= (uint)context->idValueCount) {
+ if (hasProperty)
+ *hasProperty = false;
+ return Encode::undefined();
+ }
+
+ ExecutionEngine *v4 = m->engine();
+ QQmlEnginePrivate *ep = v4->v8Engine->engine() ? QQmlEnginePrivate::get(v4->v8Engine->engine()) : 0;
+ if (ep)
+ ep->captureProperty(&context->idValues[index].bindings);
+
+ return QObjectWrapper::wrap(This->engine(), context->idValues[index].data());
+}
+
+void QQmlIdObjectsArray::markObjects(Managed *that, ExecutionEngine *engine)
+{
+ QQmlIdObjectsArray *This = static_cast<QQmlIdObjectsArray*>(that);
+ This->contextWrapper->mark(engine);
+ Object::markObjects(that, engine);
+}
+
QT_END_NAMESPACE