diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-08-08 08:18:13 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-08-08 12:49:44 +0200 |
commit | 2329a3145e59c16b5bbc37cedad7e67e16f14fb8 (patch) | |
tree | 73900588daab4c2c91ef0ff6566818905375ca85 /src/qml/qml | |
parent | d0eb6f9e07156880c6d9de4b98b2e4abfc4a0bfb (diff) | |
parent | 432e27ae092397cb2154f48103e729852c38cf2d (diff) |
Merge remote-tracking branch 'origin/dev' into wip/pointerhandler
Change-Id: I0af7b0c3e0a21aae68c82ec11c5ca579c1661ce9
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlbinding.cpp | 53 | ||||
-rw-r--r-- | src/qml/qml/qqmlbinding_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 26 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlexpression.cpp | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlextensioninterface.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 40 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport_p.h | 13 | ||||
-rw-r--r-- | src/qml/qml/qqmljavascriptexpression.cpp | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmljavascriptexpression_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 151 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmlnotifier.cpp | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmlnotifier_p.h | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 23 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 21 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 33 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmltypenamecache.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmltypenamecache_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlxmlhttprequest.cpp | 9 |
22 files changed, 288 insertions, 153 deletions
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 62288a5845..84f30af066 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -195,7 +195,7 @@ class QQmlNonbindingBinding: public QQmlBinding { protected: void doUpdate(const DeleteWatcher &watcher, - QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) Q_DECL_OVERRIDE Q_DECL_FINAL + QQmlPropertyData::WriteFlags flags, QV4::Scope &scope) Q_DECL_OVERRIDE { auto ep = QQmlEnginePrivate::get(scope.engine); ep->referenceScarceResources(); @@ -296,6 +296,50 @@ protected: } }; +class QQmlTranslationBinding : public GenericBinding<QMetaType::QString> { +public: + QQmlTranslationBinding(QV4::CompiledData::CompilationUnit *compilationUnit, const QV4::CompiledData::Binding *binding) + { + setCompilationUnit(compilationUnit); + m_binding = binding; + setSourceLocation(QQmlSourceLocation(compilationUnit->fileName(), binding->valueLocation.line, binding->valueLocation.column)); + } + + void doUpdate(const DeleteWatcher &watcher, + QQmlPropertyData::WriteFlags flags, QV4::Scope &) Q_DECL_OVERRIDE Q_DECL_FINAL + { + if (watcher.wasDeleted()) + return; + + if (!isAddedToObject() || hasError()) + return; + + const QString result = m_binding->valueAsString(m_compilationUnit->data); + + Q_ASSERT(targetObject()); + + QQmlPropertyData *pd; + QQmlPropertyData vpd; + getPropertyData(&pd, &vpd); + Q_ASSERT(pd); + doStore(result, pd, flags); + } + +private: + const QV4::CompiledData::Binding *m_binding; +}; + +QQmlBinding *QQmlBinding::createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt) +{ + QQmlTranslationBinding *b = new QQmlTranslationBinding(unit, binding); + + b->setNotifyOnValueChanged(true); + b->QQmlJavaScriptExpression::setContext(ctxt); + b->setScopeObject(obj); + + return b; +} + Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData, const QV4::Value &result, @@ -515,7 +559,12 @@ void QQmlBinding::getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyD Q_ASSERT(propertyData); QQmlData *data = QQmlData::get(*m_target, false); - Q_ASSERT(data && data->propertyCache); + Q_ASSERT(data); + + if (Q_UNLIKELY(!data->propertyCache)) { + data->propertyCache = QQmlEnginePrivate::get(context()->engine)->cache(m_target->metaObject()); + data->propertyCache->addref(); + } *propertyData = data->propertyCache->property(m_targetIndex.coreIndex()); Q_ASSERT(*propertyData); diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index 0f2fb329f5..1c894148e4 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -77,6 +77,8 @@ public: const QString &url = QString(), quint16 lineNumber = 0); static QQmlBinding *create(const QQmlPropertyData *property, QV4::Function *function, QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope); + static QQmlBinding *createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding, + QObject *obj, QQmlContextData *ctxt); ~QQmlBinding(); void setTarget(const QQmlProperty &); diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index fd516c9815..38a2978712 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -596,7 +596,7 @@ The following functions are also on the Qt object. \li application.font \endlist - \sa Screen, Window, {QtQuick::Window::screen}{Window.screen} + \sa Screen, Window, {QtQuick.Window::Window::screen}{Window.screen} */ /*! @@ -1328,6 +1328,27 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled) } /*! + Refreshes all binding expressions that use strings marked for translation. + + Call this function after you have installed a new translator with + QCoreApplication::installTranslator, to ensure that your user-interface + shows up-to-date translations. + + \note Due to a limitation in the implementation, this function + refreshes all the engine's bindings, not only those that use strings + marked for translation. + This may be optimized in a future release. + + \since 5.10 +*/ +void QQmlEngine::retranslate() +{ + Q_D(QQmlEngine); + if (QQmlContextData *firstChildContext = QQmlContextData::get(d->rootContext)->childContexts) + firstChildContext->refreshExpressions(); +} + +/*! Returns the QQmlContext for the \a object, or 0 if no context has been set. @@ -1447,6 +1468,9 @@ bool QQmlEngine::event(QEvent *e) Q_D(QQmlEngine); if (e->type() == QEvent::User) d->doDeleteInEngineThread(); + else if (e->type() == QEvent::LanguageChange) { + retranslate(); + } return QJSEngine::event(e); } diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index 8cada954fe..2bf4c0497b 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -144,6 +144,10 @@ public: bool outputWarningsToStandardError() const; void setOutputWarningsToStandardError(bool); +public Q_SLOTS: + void retranslate(); + +public: static QQmlContext *contextForObject(const QObject *); static void setContextForObject(QObject *, QQmlContext *); diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index b70db5ed86..1e1fbcf448 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -202,7 +202,6 @@ QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope, */ QQmlExpression::~QQmlExpression() { - clearError(); } /*! diff --git a/src/qml/qml/qqmlextensioninterface.h b/src/qml/qml/qqmlextensioninterface.h index ef56d5e312..62b9b26569 100644 --- a/src/qml/qml/qqmlextensioninterface.h +++ b/src/qml/qml/qqmlextensioninterface.h @@ -66,7 +66,10 @@ public: Q_DECLARE_INTERFACE(QQmlTypesExtensionInterface, "org.qt-project.Qt.QQmlTypesExtensionInterface/1.0") +// NOTE: When changing this to a new version and deciding to add backup code to +// continue to support the previous version, make sure to support both of these iids. #define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface/1.0" +#define QQmlExtensionInterface_iid_old "org.qt-project.Qt.QQmlExtensionInterface" Q_DECLARE_INTERFACE(QQmlExtensionInterface, QQmlExtensionInterface_iid) diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index ee5b38717b..fc8e60e3f2 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -295,7 +295,8 @@ public: QList<QQmlError> *errors); bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor, - QQmlType** type_return, QList<QQmlError> *errors); + QQmlType** type_return, QList<QQmlError> *errors, + QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion); QUrl baseUrl; QString base; @@ -620,7 +621,8 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) */ bool QQmlImports::resolveType(const QHashedStringRef &type, QQmlType** type_return, int *vmaj, int *vmin, - QQmlImportNamespace** ns_return, QList<QQmlError> *errors) const + QQmlImportNamespace** ns_return, QList<QQmlError> *errors, + QQmlImport::RecursionRestriction recursionRestriction) const { QQmlImportNamespace* ns = d->findQualifiedNamespace(type); if (ns) { @@ -629,7 +631,7 @@ bool QQmlImports::resolveType(const QHashedStringRef &type, return true; } if (type_return) { - if (d->resolveType(type,vmaj,vmin,type_return, errors)) { + if (d->resolveType(type,vmaj,vmin,type_return, errors, recursionRestriction)) { if (qmlImportTrace()) { #define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \ << ')' << "::resolveType: " << type.toString() << " => " @@ -712,7 +714,8 @@ bool QQmlImports::resolveType(QQmlImportNamespace* ns, const QHashedStringRef &t bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, int *vmajor, int *vminor, - QQmlType** type_return, QString *base, bool *typeRecursionDetected) const + QQmlType** type_return, QString *base, bool *typeRecursionDetected, + QQmlImport::RecursionRestriction recursionRestriction) const { if (majversion >= 0 && minversion >= 0) { QQmlType *t = QQmlMetaType::qmlType(type, uri, majversion, minversion); @@ -747,7 +750,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, if (resolveLocalUrl(*base, c.fileName) != componentUrl) continue; // failed attempt to access an internal type } - if (*base == componentUrl) { + if (recursionRestriction == QQmlImport::PreventRecursion && *base == componentUrl) { if (typeRecursionDetected) *typeRecursionDetected = true; continue; // no recursion @@ -790,7 +793,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, } if (exists) { - if (base && (*base == qmlUrl)) { // no recursion + if (recursionRestriction == QQmlImport::PreventRecursion && base && (*base == qmlUrl)) { // no recursion if (typeRecursionDetected) *typeRecursionDetected = true; } else { @@ -806,7 +809,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, } bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor, - QQmlType** type_return, QList<QQmlError> *errors) + QQmlType** type_return, QList<QQmlError> *errors, + QQmlImport::RecursionRestriction recursionRestriction) { QQmlImportNamespace *s = 0; int dot = type.indexOf(Dot); @@ -835,7 +839,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, } QHashedStringRef unqualifiedtype = dot < 0 ? type : QHashedStringRef(type.constData()+dot+1, type.length()-dot-1); if (s) { - if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return, &base, errors)) + if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return, &base, errors, recursionRestriction)) return true; if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) { // qualified, and only 1 url @@ -858,13 +862,14 @@ QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, int *vmajor, int *vminor, QQmlType** type_return, - QString *base, QList<QQmlError> *errors) + QString *base, QList<QQmlError> *errors, + QQmlImport::RecursionRestriction recursionRestriction) { bool typeRecursionDetected = false; for (int i=0; i<imports.count(); ++i) { const QQmlImportInstance *import = imports.at(i); if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, - base, &typeRecursionDetected)) { + base, &typeRecursionDetected, recursionRestriction)) { if (qmlCheckTypes()) { // check for type clashes for (int j = i+1; j<imports.count(); ++j) { @@ -966,8 +971,8 @@ static QVector<QStaticPlugin> makePlugins() // the list the first time called to only contain QML plugins: const auto staticPlugins = QPluginLoader::staticPlugins(); for (const QStaticPlugin &plugin : staticPlugins) { - if (plugin.metaData().value(QLatin1String("IID")).toString() - == QLatin1String(QQmlExtensionInterface_iid)) { + const QString iid = plugin.metaData().value(QLatin1String("IID")).toString(); + if (iid == QLatin1String(QQmlExtensionInterface_iid) || iid == QLatin1String(QQmlExtensionInterface_iid_old)) { plugins.append(plugin); } } @@ -1489,6 +1494,17 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix if (!url.endsWith(Slash) && !url.endsWith(Backslash)) url += Slash; + // ### For enum support, we are now adding the implicit import always (and earlier). Bail early + // if the implicit import has already been explicitly added, otherwise we can run into issues + // with duplicate imports + if (isImplicitImport) { + for (QList<QQmlImportInstance *>::const_iterator it = nameSpace->imports.constBegin(); + it != nameSpace->imports.constEnd(); ++it) { + if ((*it)->uri == importUri) + return true; + } + } + QQmlImportInstance *inserted = addImportToNamespace(nameSpace, importUri, url, vmaj, vmin, QV4::CompiledData::Import::ImportFile, errors, isImplicitImport); Q_ASSERT(inserted); diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index 7c691a468c..1a50d5c16a 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -70,6 +70,10 @@ class QQmlImportDatabase; class QQmlTypeLoader; class QQmlTypeLoaderQmldirContent; +namespace QQmlImport { + enum RecursionRestriction { PreventRecursion, AllowRecursion }; +} + struct QQmlImportInstance { QString uri; // e.g. QtQuick @@ -87,7 +91,8 @@ struct QQmlImportInstance bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, int *vmajor, int *vminor, QQmlType** type_return, - QString *base = 0, bool *typeRecursionDetected = 0) const; + QString *base = 0, bool *typeRecursionDetected = 0, + QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const; }; class QQmlImportNamespace @@ -102,7 +107,8 @@ public: bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, int *vmajor, int *vminor, QQmlType** type_return, - QString *base = 0, QList<QQmlError> *errors = 0); + QString *base = 0, QList<QQmlError> *errors = 0, + QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion); // Prefix when used as a qualified import. Otherwise empty. QHashedString prefix; @@ -128,7 +134,8 @@ public: QQmlType** type_return, int *version_major, int *version_minor, QQmlImportNamespace** ns_return, - QList<QQmlError> *errors = 0) const; + QList<QQmlError> *errors = 0, + QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const; bool resolveType(QQmlImportNamespace*, const QHashedStringRef& type, QQmlType** type_return, int *version_major, int *version_minor) const; diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 17cccc0bbd..31c277d283 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -111,6 +111,7 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression() clearActiveGuards(); clearPermanentGuards(); + clearError(); if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion. m_scopeObject.asT2()->_s = 0; @@ -282,7 +283,7 @@ void QQmlPropertyCapture::captureProperty(QQmlNotifier *n, Duration duration) \a n is in the signal index range (see QObjectPrivate::signalIndex()). */ -void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, Duration duration) +void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, Duration duration, bool doNotify) { if (watcher->wasDeleted()) return; @@ -318,7 +319,7 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, Duration dur Q_ASSERT(g->isConnected(o, n)); } else { g = QQmlJavaScriptExpressionGuard::New(expression, engine); - g->connect(o, n, engine); + g->connect(o, n, engine, doNotify); } if (duration == Permanently) @@ -349,7 +350,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct QV4::Scoped<QV4::QmlContext> context(scope, engine->qmlContext()); QQmlContextData *qmlContext = context->qmlContext(); - const QV4::CompiledData::LEUInt32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable(); + const quint32_le *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable(); const int idObjectDependencyCount = compiledFunction->nDependingIdObjects; for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) { Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount); @@ -358,7 +359,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct } Q_ASSERT(qmlContext->contextObject); - const QV4::CompiledData::LEUInt32 *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable(); + const quint32_le *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable(); const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties; for (int i = 0; i < contextPropertyDependencyCount; ++i) { const int propertyIndex = *contextPropertyDependency++; @@ -368,7 +369,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::CompiledData::Funct } QObject *scopeObject = context->qmlScope(); - const QV4::CompiledData::LEUInt32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable(); + const quint32_le *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable(); const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties; for (int i = 0; i < scopePropertyDependencyCount; ++i) { const int propertyIndex = *scopePropertyDependency++; @@ -460,7 +461,12 @@ void QQmlJavaScriptExpression::setupFunction(QV4::ExecutionContext *qmlContext, return; m_qmlScope.set(qmlContext->engine(), *qmlContext); m_v4Function = f; - m_compilationUnit = m_v4Function->compilationUnit; + setCompilationUnit(m_v4Function->compilationUnit); +} + +void QQmlJavaScriptExpression::setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit) +{ + m_compilationUnit = compilationUnit; } void QQmlJavaScriptExpression::clearActiveGuards() diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h index 646cc5ab3d..8b4b64f4d2 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -160,11 +160,13 @@ protected: } void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f); + void setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit); private: friend class QQmlContextData; friend class QQmlPropertyCapture; friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **); + friend class QQmlTranslationBinding; QQmlDelayedError *m_error; @@ -204,7 +206,7 @@ public: static void registerQmlDependencies(const QV4::CompiledData::Function *compiledFunction, const QV4::Scope &scope); void captureProperty(QQmlNotifier *, Duration duration = OnlyOnce); - void captureProperty(QObject *, int, int, Duration duration = OnlyOnce); + void captureProperty(QObject *, int, int, Duration duration = OnlyOnce, bool doNotify = true); QQmlEngine *engine; QQmlJavaScriptExpression *expression; diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 0672618225..b75508e1e5 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -160,8 +160,9 @@ public: ~QQmlTypePrivate(); void init() const; - void initEnums() const; + void initEnums(const QQmlPropertyCache *cache = 0) const; void insertEnums(const QMetaObject *metaObject) const; + void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const; QQmlType::RegistrationType regType; @@ -500,75 +501,17 @@ QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const return QQmlMetaType::qmlType(mo); } -int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const +QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) const { + // similar logic to resolveCompositeBaseType Q_ASSERT(isComposite()); - *ok = false; - QQmlType *type = resolveCompositeBaseType(engine); - if (!type) - return -1; - return type->enumValue(engine, name, ok); -} - -int QQmlType::resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const -{ - Q_ASSERT(isComposite()); - *ok = false; - QQmlType *type = resolveCompositeBaseType(engine); - if (!type) - return -1; - return type->scopedEnumIndex(engine, name, ok); -} - -int QQmlType::resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const -{ - Q_ASSERT(isComposite()); - *ok = false; - QQmlType *type = resolveCompositeBaseType(engine); - if (!type) - return -1; - return type->scopedEnumIndex(engine, name, ok); -} - - -int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const -{ - Q_ASSERT(isComposite()); - *ok = false; - QQmlType *type = resolveCompositeBaseType(engine); - if (!type) - return -1; - return type->scopedEnumValue(engine, index, name, ok); -} - -int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const -{ - Q_ASSERT(isComposite()); - *ok = false; - QQmlType *type = resolveCompositeBaseType(engine); - if (!type) - return -1; - return type->scopedEnumValue(engine, index, name, ok); -} - -int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedName, const QByteArray &name, bool *ok) const -{ - Q_ASSERT(isComposite()); - *ok = false; - QQmlType *type = resolveCompositeBaseType(engine); - if (!type) - return -1; - return type->scopedEnumValue(engine, scopedName, name, ok); -} - -int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedName, const QStringRef &name, bool *ok) const -{ - Q_ASSERT(isComposite()); - *ok = false; - QQmlType *type = resolveCompositeBaseType(engine); - if (!type) - return -1; - return type->scopedEnumValue(engine, scopedName, name, ok); + if (!engine) + return 0; + QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt); + if (td.isNull() || !td->isComplete()) + return 0; + QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit(); + return compilationUnit->rootPropertyCache(); } static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, @@ -737,7 +680,7 @@ void QQmlTypePrivate::init() const lock.unlock(); } -void QQmlTypePrivate::initEnums() const +void QQmlTypePrivate::initEnums(const QQmlPropertyCache *cache) const { if (isEnumSetup) return; @@ -746,6 +689,8 @@ void QQmlTypePrivate::initEnums() const QMutexLocker lock(metaTypeDataLock()); if (isEnumSetup) return; + if (cache) + insertEnumsFromPropertyCache(cache); if (baseMetaObject) // could be singleton type without metaobject insertEnums(baseMetaObject); @@ -784,6 +729,31 @@ void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const } } +void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const +{ + const QMetaObject *cppMetaObject = cache->firstCppMetaObject(); + + while (cache && cache->metaObject() != cppMetaObject) { + QStringHash<int> *scoped = new QStringHash<int>(); + + int count = cache->qmlEnumCount(); + for (int ii = 0; ii < count; ++ii) { + QQmlEnumData *enumData = cache->qmlEnum(ii); + + for (int jj = 0; jj < enumData->values.count(); ++jj) { + const QQmlEnumValue &value = enumData->values.at(jj); + enums.insert(value.namedValue, value.value); + scoped->insert(value.namedValue, value.value); + } + scopedEnums << scoped; + scopedEnumIndex.insert(enumData->name, scopedEnums.count()-1); + } + cache = cache->parent(); + } + insertEnums(cppMetaObject); +} + + QByteArray QQmlType::typeName() const { if (d->regType == SingletonType || d->regType == CompositeSingletonType) @@ -1033,11 +1003,11 @@ QUrl QQmlType::sourceUrl() const int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const { Q_ASSERT(ok); - if (isComposite()) - return resolveCompositeEnumValue(engine, name.toString(), ok); + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; + *ok = true; - d->initEnums(); + d->initEnums(cache); int *rv = d->enums.value(name); if (rv) @@ -1050,11 +1020,11 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const { Q_ASSERT(ok); - if (isComposite()) - return resolveCompositeEnumValue(engine, name.toUtf16(), ok); + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; + *ok = true; - d->initEnums(); + d->initEnums(cache); int *rv = d->enums.value(name); if (rv) @@ -1067,11 +1037,10 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const { Q_ASSERT(ok); - if (isComposite()) - return resolveCompositeEnumValue(engine, name->toQString(), ok); + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; *ok = true; - d->initEnums(); + d->initEnums(cache); int *rv = d->enums.value(name); if (rv) @@ -1084,11 +1053,10 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const { Q_ASSERT(ok); - if (isComposite()) - return resolveCompositeScopedEnumIndex(engine, name, ok); + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; *ok = true; - d->initEnums(); + d->initEnums(cache); int *rv = d->scopedEnumIndex.value(name); if (rv) @@ -1101,11 +1069,10 @@ int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const { Q_ASSERT(ok); - if (isComposite()) - return resolveCompositeScopedEnumIndex(engine, name, ok); + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; *ok = true; - d->initEnums(); + d->initEnums(cache); int *rv = d->scopedEnumIndex.value(name); if (rv) @@ -1117,9 +1084,8 @@ int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bo int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const { + Q_UNUSED(engine) Q_ASSERT(ok); - if (isComposite()) - return resolveCompositeScopedEnumValue(engine, index, name, ok); *ok = true; Q_ASSERT(index > -1 && index < d->scopedEnums.count()); @@ -1133,9 +1099,8 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::S int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const { + Q_UNUSED(engine) Q_ASSERT(ok); - if (isComposite()) - return resolveCompositeScopedEnumValue(engine, index, name, ok); *ok = true; Q_ASSERT(index > -1 && index < d->scopedEnums.count()); @@ -1150,11 +1115,10 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QStrin int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedEnumName, const QByteArray &name, bool *ok) const { Q_ASSERT(ok); - if (isComposite()) - return resolveCompositeScopedEnumValue(engine, scopedEnumName, name, ok); + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; *ok = true; - d->initEnums(); + d->initEnums(cache); int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length())); if (rv) { @@ -1172,11 +1136,10 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scope int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedEnumName, const QStringRef &name, bool *ok) const { Q_ASSERT(ok); - if (isComposite()) - return resolveCompositeScopedEnumValue(engine, scopedEnumName, name, ok); + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; *ok = true; - d->initEnums(); + d->initEnums(cache); int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName)); if (rv) { diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 4dd28bbd36..ead4f130ec 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -135,6 +135,7 @@ public: struct QQmlMetaTypeData; class QHashedCStringRef; +class QQmlPropertyCache; class Q_QML_PRIVATE_EXPORT QQmlType { public: @@ -227,13 +228,7 @@ public: private: QQmlType *superType() const; QQmlType *resolveCompositeBaseType(QQmlEnginePrivate *engine) const; - int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const; - int resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const; - int resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const; - int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *, bool *ok) const; - int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const; - int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedName, const QByteArray &name, bool *ok) const; - int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedName, const QStringRef &name, bool *ok) const; + QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const; friend class QQmlTypePrivate; friend struct QQmlMetaTypeData; diff --git a/src/qml/qml/qqmlnotifier.cpp b/src/qml/qml/qqmlnotifier.cpp index 538ca822ee..938e2b77e2 100644 --- a/src/qml/qml/qqmlnotifier.cpp +++ b/src/qml/qml/qqmlnotifier.cpp @@ -117,7 +117,7 @@ void QQmlNotifier::emitNotify(QQmlNotifierEndpoint *endpoint, void **a) \a sourceSignal MUST be in the signal index range (see QObjectPrivate::signalIndex()). This is different from QMetaMethod::methodIndex(). */ -void QQmlNotifierEndpoint::connect(QObject *source, int sourceSignal, QQmlEngine *engine) +void QQmlNotifierEndpoint::connect(QObject *source, int sourceSignal, QQmlEngine *engine, bool doNotify) { disconnect(); @@ -142,8 +142,11 @@ void QQmlNotifierEndpoint::connect(QObject *source, int sourceSignal, QQmlEngine QQmlPropertyPrivate::flushSignal(source, sourceSignal); QQmlData *ddata = QQmlData::get(source, true); ddata->addNotify(sourceSignal, this); - QObjectPrivate * const priv = QObjectPrivate::get(source); - priv->connectNotify(QMetaObjectPrivate::signal(source->metaObject(), sourceSignal)); + if (doNotify) { + needsConnectNotify = doNotify; + QObjectPrivate * const priv = QObjectPrivate::get(source); + priv->connectNotify(QMetaObjectPrivate::signal(source->metaObject(), sourceSignal)); + } } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h index dad79e0e55..6e91369793 100644 --- a/src/qml/qml/qqmlnotifier_p.h +++ b/src/qml/qml/qqmlnotifier_p.h @@ -100,7 +100,7 @@ public: inline bool isConnected(QObject *source, int sourceSignal) const; inline bool isConnected(QQmlNotifier *) const; - void connect(QObject *source, int sourceSignal, QQmlEngine *engine); + void connect(QObject *source, int sourceSignal, QQmlEngine *engine, bool doNotify = true); inline void connect(QQmlNotifier *); inline void disconnect(); @@ -121,9 +121,10 @@ private: inline QQmlNotifier *senderAsNotifier() const; Callback callback:4; + int needsConnectNotify:1; // The index is in the range returned by QObjectPrivate::signalIndex(). // This is different from QMetaMethod::methodIndex(). - signed int sourceSignal:28; + signed int sourceSignal:27; }; QQmlNotifier::QQmlNotifier() @@ -155,7 +156,7 @@ void QQmlNotifier::notify() } QQmlNotifierEndpoint::QQmlNotifierEndpoint(Callback callback) -: next(0), prev(0), senderPtr(0), callback(callback), sourceSignal(-1) +: next(0), prev(0), senderPtr(0), callback(callback), needsConnectNotify(false), sourceSignal(-1) { } @@ -205,7 +206,8 @@ void QQmlNotifierEndpoint::disconnect() if (sourceSignal != -1) { QObject * const obj = senderAsObject(); QObjectPrivate * const priv = QObjectPrivate::get(obj); - priv->disconnectNotify(QMetaObjectPrivate::signal(obj->metaObject(), sourceSignal)); + if (needsConnectNotify) + priv->disconnectNotify(QMetaObjectPrivate::signal(obj->metaObject(), sourceSignal)); } if (isNotifying()) *((qintptr *)(senderPtr & ~0x1)) = 0; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 2cbcfbbfb6..9206395c8f 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -801,17 +801,13 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con && !_valueTypeProperty) QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(property->coreIndex())); - if (binding->type == QV4::CompiledData::Binding::Type_Script) { - QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]; - - QV4::Scope scope(v4); - QV4::Scoped<QV4::QmlContext> qmlContext(scope, currentQmlContext()); - + if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->containsTranslations()) { if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) { + QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]; int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex()); QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine); QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex, - context, _scopeObject, runtimeFunction, qmlContext); + context, _scopeObject, runtimeFunction, currentQmlContext()); bs->takeExpression(expr); } else { @@ -827,7 +823,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con prop = _valueTypeProperty; subprop = property; } - qmlBinding = QQmlBinding::create(prop, runtimeFunction, _scopeObject, context, qmlContext); + if (binding->containsTranslations()) { + qmlBinding = QQmlBinding::createTranslationBinding(compilationUnit, binding, _scopeObject, context); + } else { + QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]; + qmlBinding = QQmlBinding::create(prop, runtimeFunction, _scopeObject, context, currentQmlContext()); + } qmlBinding->setTarget(_bindingTarget, *prop, subprop); sharedState->allCreatedBindings.push(QQmlAbstractBinding::Ptr(qmlBinding)); @@ -996,7 +997,7 @@ void QQmlObjectCreator::setupFunctions() QV4::ScopedValue function(scope); QV4::ScopedContext qmlContext(scope, currentQmlContext()); - const QV4::CompiledData::LEUInt32 *functionIdx = _compiledObject->functionOffsetTable(); + const quint32_le *functionIdx = _compiledObject->functionOffsetTable(); for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) { QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[*functionIdx]; const QString name = runtimeFunction->name()->toQString(); @@ -1026,12 +1027,12 @@ void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::O context->setIdProperty(object->id, instance); } -QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext() +QV4::QmlContext *QQmlObjectCreator::currentQmlContext() { if (!_qmlContext->isManaged()) _qmlContext->setM(QV4::QmlContext::create(v4->rootContext(), context, _scopeObject)); - return _qmlContext->d(); + return _qmlContext; } QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject) diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 982324be3c..45c14f0963 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -122,7 +122,7 @@ private: void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const; - QV4::Heap::QmlContext *currentQmlContext(); + QV4::QmlContext *currentQmlContext(); enum Phase { Startup, diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index d18159841c..15b9fe8312 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -321,12 +321,13 @@ QQmlPropertyCache *QQmlPropertyCache::copy() } QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int methodCount, - int signalCount) + int signalCount, int enumCount) { QQmlPropertyCache *rv = copy(propertyCount + methodCount + signalCount); rv->propertyIndexCache.reserve(propertyCount); rv->methodIndexCache.reserve(methodCount); rv->signalHandlerIndexCache.reserve(signalCount); + rv->enumCache.reserve(enumCount); rv->_metaObject = 0; return rv; @@ -421,6 +422,14 @@ void QQmlPropertyCache::appendMethod(const QString &name, QQmlPropertyData::Flag setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0)); } +void QQmlPropertyCache::appendEnum(const QString &name, const QVector<QQmlEnumValue> &values) +{ + QQmlEnumData data; + data.name = name; + data.values = values; + enumCache.append(data); +} + // Returns this property cache's metaObject, creating it if necessary. const QMetaObject *QQmlPropertyCache::createMetaObject() { @@ -1245,6 +1254,16 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder) method.setReturnType(returnType); } + for (int ii = 0; ii < enumCache.count(); ++ii) { + const QQmlEnumData &enumData = enumCache.at(ii); + QMetaEnumBuilder enumeration = builder.addEnumerator(enumData.name.toUtf8()); + enumeration.setIsScoped(true); + for (int jj = 0; jj < enumData.values.count(); ++jj) { + const QQmlEnumValue &value = enumData.values.at(jj); + enumeration.addKey(value.namedValue.toUtf8(), value.value); + } + } + if (!_defaultPropertyName.isEmpty()) { QQmlPropertyData *dp = property(_defaultPropertyName, 0, 0); if (dp && dp->coreIndex() >= propertyIndexCacheStart) { diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 64be1cb206..392768c1b1 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -349,6 +349,20 @@ private: bool notFullyResolved() const { return _flags.notFullyResolved; } }; +struct QQmlEnumValue +{ + QQmlEnumValue() : value(-1) {} + QQmlEnumValue(const QString &n, int v) : namedValue(n), value(v) {} + QString namedValue; + int value; +}; + +struct QQmlEnumData +{ + QString name; + QVector<QQmlEnumValue> values; +}; + class QQmlPropertyCacheMethodArguments; class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup { @@ -374,13 +388,14 @@ public: QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags()); QQmlPropertyCache *copyAndReserve(int propertyCount, - int methodCount, int signalCount); + int methodCount, int signalCount, int enumCount); void appendProperty(const QString &, QQmlPropertyRawData::Flags flags, int coreIndex, int propType, int notifyIndex); void appendSignal(const QString &, QQmlPropertyRawData::Flags, int coreIndex, const int *types = 0, const QList<QByteArray> &names = QList<QByteArray>()); void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex, const QList<QByteArray> &names = QList<QByteArray>()); + void appendEnum(const QString &, const QVector<QQmlEnumValue> &); const QMetaObject *metaObject() const; const QMetaObject *createMetaObject(); @@ -395,6 +410,7 @@ public: QQmlPropertyData *property(int) const; QQmlPropertyData *method(int) const; QQmlPropertyData *signal(int index) const; + QQmlEnumData *qmlEnum(int) const; int methodIndexToSignalIndex(int) const; QString defaultPropertyName() const; @@ -434,6 +450,7 @@ public: inline int methodOffset() const; inline int signalCount() const; inline int signalOffset() const; + inline int qmlEnumCount() const; static bool isDynamicMetaObject(const QMetaObject *); @@ -507,6 +524,7 @@ private: IndexCache signalHandlerIndexCache; StringCache stringCache; AllowedRevisionCache allowedRevisionCache; + QVector<QQmlEnumData> enumCache; bool _hasPropertyOverrides : 1; bool _ownMetaObject : 1; @@ -747,6 +765,14 @@ inline QQmlPropertyData *QQmlPropertyCache::signal(int index) const return ensureResolved(rv); } +inline QQmlEnumData *QQmlPropertyCache::qmlEnum(int index) const +{ + if (index < 0 || index >= enumCache.count()) + return 0; + + return const_cast<QQmlEnumData *>(&enumCache.at(index)); +} + inline int QQmlPropertyCache::methodIndexToSignalIndex(int index) const { if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count())) @@ -817,6 +843,11 @@ int QQmlPropertyCache::signalOffset() const return signalHandlerIndexCacheStart; } +int QQmlPropertyCache::qmlEnumCount() const +{ + return enumCache.count(); +} + bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const { if (_jsFactoryMethodIndex != -1) { diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index e4293596d8..151a7cd883 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2651,6 +2651,10 @@ void QQmlTypeData::resolveTypes() m_resolvedTypes.insert(unresolvedRef.key(), ref); } + + // ### this allows enums to work without explicit import or instantiation of the type + if (!m_implicitImportLoaded) + loadImplicitImport(); } QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp index c8e2b92c29..35ef8ada57 100644 --- a/src/qml/qml/qqmltypenamecache.cpp +++ b/src/qml/qml/qqmltypenamecache.cpp @@ -140,7 +140,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name, return result; } -QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name) const +QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, QQmlImport::RecursionRestriction recursionRestriction) const { Result result = query(m_namedImports, name); @@ -156,7 +156,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name) cons QQmlImportNamespace *typeNamespace = 0; QList<QQmlError> errors; QQmlType *t = 0; - bool typeFound = m_imports.resolveType(typeName, &t, 0, 0, &typeNamespace, &errors); + bool typeFound = m_imports.resolveType(typeName, &t, 0, 0, &typeNamespace, &errors, recursionRestriction); if (typeFound) { return Result(t); } diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h index 7cdcbe91b6..f7ba2a91b7 100644 --- a/src/qml/qml/qqmltypenamecache_p.h +++ b/src/qml/qml/qqmltypenamecache_p.h @@ -90,7 +90,7 @@ public: }; Result query(const QHashedStringRef &) const; Result query(const QHashedStringRef &, const void *importNamespace) const; - Result query(const QV4::String *) const; + Result query(const QV4::String *, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const; Result query(const QV4::String *, const void *importNamespace) const; private: diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 9e8735cbc6..113ef0c412 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1823,8 +1823,13 @@ void QQmlXMLHttpRequestCtor::method_send(const QV4::BuiltinFunction *, QV4::Scop THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); QByteArray data; - if (callData->argc > 0) - data = callData->args[0].toQStringNoThrow().toUtf8(); + if (callData->argc > 0) { + if (const ArrayBuffer *buffer = callData->args[0].as<ArrayBuffer>()) { + data = buffer->asByteArray(); + } else { + data = callData->args[0].toQStringNoThrow().toUtf8(); + } + } scope.result = r->send(w, scope.engine->callingQmlContext(), data); } |