diff options
-rw-r--r-- | src/qml/compiler/qv4compiler_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqml.cpp | 104 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 13 |
3 files changed, 117 insertions, 2 deletions
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h index 4f3c718175..5155c25c06 100644 --- a/src/qml/compiler/qv4compiler_p.h +++ b/src/qml/compiler/qv4compiler_p.h @@ -125,6 +125,8 @@ struct Q_QMLCOMPILER_PRIVATE_EXPORT JSUnitGenerator { int registerSetterLookup(int nameIndex); int registerGlobalGetterLookup(int nameIndex); int registerQmlContextPropertyGetterLookup(int nameIndex); + int lookupNameIndex(int index) const { return lookups[index].nameIndex; } + QString lookupName(int index) const { return stringForIndex(lookupNameIndex(index)); } int registerRegExp(QQmlJS::AST::RegExpLiteral *regexp); diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index ae8cde8a87..26efb493d3 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -49,6 +49,7 @@ #include <private/qqmltypemodule_p.h> #include <private/qqmltypenotavailable_p.h> #include <private/qqmlcomponent_p.h> +#include <private/qv4lookup_p.h> #include <QtCore/qmutex.h> @@ -696,4 +697,107 @@ void QQmlPrivate::AOTCompiledContext::setInstructionPointer(int offset) const frame->instructionPointer = offset; } +QJSValue QQmlPrivate::AOTCompiledContext::loadQmlContextPropertyLookup(uint index) const +{ + QV4::Lookup *l = compilationUnit->runtimeLookups + index; + return QJSValuePrivate::fromReturnedValue(l->qmlContextPropertyGetter( + l, engine->handle(), nullptr)); +} + +QJSValue QQmlPrivate::AOTCompiledContext::callQmlContextPropertyLookup( + uint index, const QJSValueList &args) const +{ + QV4::Scope scope(engine->handle()); + const int argc = args.length(); + QV4::Value *argv = scope.alloc(args.length()); + for (int i = 0; i < argc; ++i) + argv[i] = QJSValuePrivate::convertToReturnedValue(scope.engine, args.at(i)); + return QJSValuePrivate::fromReturnedValue(QV4::Runtime::CallQmlContextPropertyLookup::call( + engine->handle(), index, argv, argc)); +} + +QJSValue QQmlPrivate::AOTCompiledContext::getLookup(uint index, const QJSValue &object) const +{ + QV4::Lookup *l = compilationUnit->runtimeLookups + index; + + if (object.isNull() || object.isUndefined()) { + QString message = QStringLiteral("Cannot read property '%1' of %2") + .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString(), object.toString()); + return QJSValuePrivate::fromReturnedValue(engine->handle()->throwTypeError(message)); + } + + return QJSValuePrivate::fromReturnedValue( + l->getter(l, engine->handle(), + QJSValuePrivate::convertToReturnedValue(engine->handle(), object))); +} + +void QQmlPrivate::AOTCompiledContext::setLookup( + uint index, const QJSValue &object, const QJSValue &value) const +{ + QV4::Lookup *l = compilationUnit->runtimeLookups + index; + QV4::Scope scope(engine->handle()); + QV4::ScopedValue o(scope, QJSValuePrivate::convertToReturnedValue(scope.engine, object)); + if (!l->setter(l, engine->handle(), *o, + QJSValuePrivate::convertToReturnedValue(engine->handle(), value))) { + engine->handle()->throwTypeError(); + } +} + +QJSValue QQmlPrivate::AOTCompiledContext::callPropertyLookup( + uint index, const QJSValue &object, const QJSValueList &args) const +{ + QV4::Lookup *l = compilationUnit->runtimeLookups + index; + QV4::Scope scope(engine->handle()); + QV4::ScopedValue o(scope, QJSValuePrivate::convertToReturnedValue(scope.engine, object)); + + // ok to have the value on the stack here + QV4::Value f = QV4::Value::fromReturnedValue(l->getter(l, engine->handle(), o)); + + if (Q_UNLIKELY(!f.isFunctionObject())) { + QString message = QStringLiteral("Property '%1' of object %2 is not a function") + .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString(), + object.toString()); + engine->handle()->throwTypeError(message); + return QJSValue(); + } + + const int argc = args.length(); + QV4::Value *argv = scope.alloc(args.length()); + for (int i = 0; i < argc; ++i) + argv[i] = QJSValuePrivate::convertToReturnedValue(scope.engine, args.at(i)); + + return QJSValuePrivate::fromReturnedValue( + static_cast<QV4::FunctionObject &>(f).call(o, argv, argc)); +} + +QJSValue QQmlPrivate::AOTCompiledContext::callGlobalLookup( + uint index, const QJSValueList &args) const +{ + QV4::Scope scope(engine->handle()); + QV4::Lookup *l = compilationUnit->runtimeLookups + index; + QV4::Value function = QV4::Value::fromReturnedValue(l->globalGetter(l, scope.engine)); + if (!function.isFunctionObject()) { + const QString msg = QStringLiteral("Property '%1' of object [null] is not a function") + .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString()); + return QJSValuePrivate::fromReturnedValue(scope.engine->throwTypeError(msg)); + } + + const int argc = args.length(); + QV4::Value *argv = scope.alloc(args.length()); + for (int i = 0; i < argc; ++i) + argv[i] = QJSValuePrivate::convertToReturnedValue(scope.engine, args.at(i)); + + QV4::Value thisObject = QV4::Value::undefinedValue(); + QV4::ReturnedValue result = static_cast<QV4::FunctionObject &>(function).call( + &thisObject, argv, argc); + + return scope.engine->hasException ? QJSValue() : QJSValuePrivate::fromReturnedValue(result); +} + +QJSValue QQmlPrivate::AOTCompiledContext::loadGlobalLookup(uint index) const +{ + QV4::Lookup *l = compilationUnit->runtimeLookups + index; + return QJSValuePrivate::fromReturnedValue(l->globalGetter(l, engine->handle())); +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index fb2d80b3df..8c47c71305 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -83,9 +83,9 @@ using QQmlAttachedPropertiesFunc = A *(*)(QObject *); namespace QV4 { struct ExecutionEngine; +class ExecutableCompilationUnit; namespace CompiledData { struct Unit; -struct CompilationUnit; } } namespace QmlIR { @@ -606,10 +606,19 @@ namespace QQmlPrivate QQmlContext *qmlContext; QObject *qmlScopeObject; QJSEngine *engine; - QV4::CompiledData::CompilationUnit *compilationUnit; + QV4::ExecutableCompilationUnit *compilationUnit; QJSValue jsMetaType(int index) const; void setInstructionPointer(int offset) const; + + QJSValue loadQmlContextPropertyLookup(uint index) const; + QJSValue callQmlContextPropertyLookup(uint index, const QJSValueList &args) const; + QJSValue getLookup(uint index, const QJSValue &object) const; + void setLookup(uint index, const QJSValue &object, const QJSValue &value) const; + QJSValue callPropertyLookup(uint index, const QJSValue &object, + const QJSValueList &args) const; + QJSValue callGlobalLookup(uint index, const QJSValueList &args) const; + QJSValue loadGlobalLookup(uint index) const; }; struct AOTCompiledFunction { |