diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-04-22 15:04:42 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-04-22 15:32:19 +0200 |
commit | 07782f48f4318a7261f1b0ddcd686b19ec812e36 (patch) | |
tree | 3fa2aa3a1170ad7ebaf5b1641cdce19a941ca480 /src/qml/qml | |
parent | 50fcdfd705c2ad9560641986bf4152b017ee8bb6 (diff) | |
parent | f15a90e5d10465e66698209a5d88f1e63ae336fa (diff) |
Merge remote-tracking branch 'origin/5.5' into dev
Conflicts:
src/qml/qml/qqmlbinding.cpp
src/qml/jsruntime/qv4arraybuffer.cpp
src/qml/jsruntime/qv4functionobject.cpp
Change-Id: Ic752e9dfd69b282093651c9234c110a49762f06d
Diffstat (limited to 'src/qml/qml')
23 files changed, 334 insertions, 266 deletions
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 44bbe14d43..455c94f138 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -93,8 +93,8 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context); QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine()); - if (engine && ctxtdata && !ctxtdata->url.isEmpty() && ctxtdata->typeCompilationUnit) { - url = ctxtdata->url.toString(); + if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit) { + url = ctxtdata->urlString(); if (scriptPrivate->bindingId != QQmlBinding::Invalid) runtimeFunction = ctxtdata->typeCompilationUnit->runtimeFunctions.at(scriptPrivate->bindingId); } @@ -165,34 +165,13 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) if (QQmlData::wasDeleted(object())) return; - QString url; - quint16 lineNumber; - quint16 columnNumber; - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine); QV4::Scope scope(ep->v4engine()); QV4::ScopedFunctionObject f(scope, v4function.value()); Q_ASSERT(f); - if (f->isBinding()) { - Q_ASSERT(f->as<QV4::QQmlBindingFunction>()); - QQmlSourceLocation loc = static_cast<QV4::Heap::QQmlBindingFunction *>(f->d())->bindingLocation; - url = loc.sourceFile; - lineNumber = loc.line; - columnNumber = loc.column; - } else { - QV4::Function *function = f->as<QV4::FunctionObject>()->function(); - Q_ASSERT(function); - - url = function->sourceFile(); - lineNumber = function->compiledFunction->location.line; - columnNumber = function->compiledFunction->location.column; - } - - int lineNo = qmlSourceCoordinate(lineNumber); - int columnNo = qmlSourceCoordinate(columnNumber); if (!updatingFlag()) { - QQmlBindingProfiler prof(ep->profiler, url, lineNo, columnNo); + QQmlBindingProfiler prof(ep->profiler, f); setUpdatingFlag(true); QQmlAbstractExpression::DeleteWatcher watcher(this); @@ -222,7 +201,7 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) if (!watcher.wasDeleted()) { if (needsErrorLocationData) - delayedError()->setErrorLocation(QUrl(url), lineNumber, columnNumber); + delayedError()->setErrorLocation(f->sourceLocation()); if (hasError()) { if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine)); diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 1005d097d2..f08f650913 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -305,12 +305,10 @@ void QQmlContext::setContextProperty(const QString &name, const QVariant &value) } } - if (data->propertyNames.isEmpty()) - data->propertyNames = QV4::IdentifierHash<int>(QV8Engine::getV4(engine()->handle())); - - int idx = data->propertyNames.value(name); + QV4::IdentifierHash<int> &properties = data->propertyNames(); + int idx = properties.value(name); if (idx == -1) { - data->propertyNames.add(name, data->idValueCount + d->propertyValues.count()); + properties.add(name, data->idValueCount + d->propertyValues.count()); d->propertyValues.append(value); data->refreshExpressions(); @@ -343,12 +341,11 @@ void QQmlContext::setContextProperty(const QString &name, QObject *value) return; } - if (data->propertyNames.isEmpty()) - data->propertyNames = QV4::IdentifierHash<int>(QV8Engine::getV4(engine()->handle())); - int idx = data->propertyNames.value(name); + QV4::IdentifierHash<int> &properties = data->propertyNames(); + int idx = properties.value(name); if (idx == -1) { - data->propertyNames.add(name, data->idValueCount + d->propertyValues.count()); + properties.add(name, data->idValueCount + d->propertyValues.count()); d->propertyValues.append(QVariant::fromValue(value)); data->refreshExpressions(); @@ -370,8 +367,9 @@ QVariant QQmlContext::contextProperty(const QString &name) const QQmlContextData *data = d->data; - if (data->propertyNames.count()) - idx = data->propertyNames.value(name); + const QV4::IdentifierHash<int> &properties = data->propertyNames(); + if (properties.count()) + idx = properties.value(name); if (idx == -1) { if (data->contextObject) { @@ -428,14 +426,14 @@ QUrl QQmlContextData::resolvedUrl(const QUrl &src) if (src.isRelative() && !src.isEmpty()) { if (ctxt) { while(ctxt) { - if(ctxt->url.isValid()) + if (ctxt->url().isValid()) break; else ctxt = ctxt->parent; } if (ctxt) - resolved = ctxt->url.resolved(src); + resolved = ctxt->url().resolved(src); else if (engine) resolved = engine->baseUrl().resolved(src); } @@ -464,8 +462,8 @@ void QQmlContext::setBaseUrl(const QUrl &baseUrl) { Q_D(QQmlContext); - d->data->url = baseUrl; - d->data->urlString = baseUrl.toString(); + d->data->baseUrl = baseUrl; + d->data->baseUrlString = baseUrl.toString(); } /*! @@ -476,11 +474,11 @@ QUrl QQmlContext::baseUrl() const { Q_D(const QQmlContext); const QQmlContextData* data = d->data; - while (data && data->url.isEmpty()) + while (data && data->url().isEmpty()) data = data->parent; if (data) - return data->url; + return data->url(); else return QUrl(); } @@ -762,33 +760,31 @@ void QQmlContextData::setIdProperty(int idx, QObject *obj) idValues[idx].context = this; } -void QQmlContextData::setIdPropertyData(const QVector<ObjectIdMapping> &data) +void QQmlContextData::setIdPropertyData(const QHash<int, int> &data) { - Q_ASSERT(propertyNames.isEmpty()); - propertyNames = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle())); - for (QVector<ObjectIdMapping>::ConstIterator it = data.begin(), end = data.end(); - it != end; ++it) - propertyNames.add(it->name, it->id); - + Q_ASSERT(objectIndexToId.isEmpty()); + objectIndexToId = data; + Q_ASSERT(propertyNameCache.isEmpty()); idValueCount = data.count(); idValues = new ContextGuard[idValueCount]; } QString QQmlContextData::findObjectId(const QObject *obj) const { - if (propertyNames.isEmpty()) + const QV4::IdentifierHash<int> &properties = propertyNames(); + if (propertyNameCache.isEmpty()) return QString(); for (int ii = 0; ii < idValueCount; ii++) { if (idValues[ii] == obj) - return propertyNames.findId(ii); + return properties.findId(ii); } if (publicContext) { QQmlContextPrivate *p = QQmlContextPrivate::get(publicContext); for (int ii = 0; ii < p->propertyValues.count(); ++ii) if (p->propertyValues.at(ii) == QVariant::fromValue((QObject *)obj)) - return propertyNames.findId(ii); + return properties.findId(ii); } if (linkedContext) @@ -808,4 +804,33 @@ QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate() return QQmlContextPrivate::get(asQQmlContext()); } +QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const +{ + if (propertyNameCache.isEmpty()) { + propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle())); + for (QHash<int, int>::ConstIterator it = objectIndexToId.begin(), end = objectIndexToId.end(); + it != end; ++it) { + const QV4::CompiledData::Object *obj = typeCompilationUnit->data->objectAt(it.key()); + const QString name = typeCompilationUnit->data->stringAt(obj->idIndex); + propertyNameCache.add(name, it.value()); + } + objectIndexToId.clear(); + } + return propertyNameCache; +} + +QUrl QQmlContextData::url() const +{ + if (typeCompilationUnit) + return typeCompilationUnit->url(); + return baseUrl; +} + +QString QQmlContextData::urlString() const +{ + if (typeCompilationUnit) + return typeCompilationUnit->fileName(); + return baseUrlString; +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index f0e0ab26c6..f5fd7d0a5c 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -144,8 +144,9 @@ public: // Compilation unit for contexts that belong to a compiled type. QQmlRefPointer<QV4::CompiledData::CompilationUnit> typeCompilationUnit; - // Property name cache - QV4::IdentifierHash<int> propertyNames; + mutable QHash<int, int> objectIndexToId; + mutable QV4::IdentifierHash<int> propertyNameCache; + QV4::IdentifierHash<int> &propertyNames() const; // Context object QObject *contextObject; @@ -153,9 +154,11 @@ public: // Any script blocks that exist on this context QV4::PersistentValue importedScripts; // This is a JS Array - // Context base url - QUrl url; - QString urlString; + QUrl baseUrl; + QString baseUrlString; + + QUrl url() const; + QString urlString() const; // List of imports that apply to this context QQmlTypeNameCache *imports; @@ -188,17 +191,10 @@ public: QFlagPointer<QQmlContextData> context; QQmlNotifier bindings; }; - struct ObjectIdMapping { - ObjectIdMapping() : id(-1) {} - ObjectIdMapping(const QString &name, int id) - : name(name), id(id) {} - QString name; - int id; - }; ContextGuard *idValues; int idValueCount; void setIdProperty(int, QObject *); - void setIdPropertyData(const QVector<ObjectIdMapping> &); + void setIdPropertyData(const QHash<int, int> &); // Linked contexts. this owns linkedContext. QQmlContextData *linkedContext; diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 64ff6c390e..69071cd6c2 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -60,6 +60,7 @@ Heap::QmlContextWrapper::QmlContextWrapper(QV4::ExecutionEngine *engine, QQmlCon , isNullWrapper(false) , context(context) , scopeObject(scopeObject) + , idObjectsWrapper(Q_NULLPTR) { } @@ -82,7 +83,8 @@ ReturnedValue QmlContextWrapper::urlScope(ExecutionEngine *v4, const QUrl &url) Scope scope(v4); QQmlContextData *context = new QQmlContextData; - context->url = url; + context->baseUrl = url; + context->baseUrlString = url.toString(); context->isInternal = true; context->isJSContext = true; @@ -199,8 +201,9 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr while (context) { // Search context properties - if (context->propertyNames.count()) { - int propertyIdx = context->propertyNames.value(name); + const QV4::IdentifierHash<int> &properties = context->propertyNames(); + if (properties.count()) { + int propertyIdx = properties.value(name); if (propertyIdx != -1) { @@ -308,8 +311,9 @@ void QmlContextWrapper::put(Managed *m, String *name, const Value &value) QObject *scopeObject = wrapper->getScopeObject(); while (context) { + const QV4::IdentifierHash<int> &properties = context->propertyNames(); // Search context properties - if (context->propertyNames.count() && -1 != context->propertyNames.value(name)) + if (properties.count() && properties.value(name) != -1) return; // Search scope object diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index 15ca126365..88282b1bbc 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -100,7 +100,7 @@ protected: private: QList<QQmlError> exceptions; - QQmlCustomParserCompilerBackend *compiler; + const QQmlCustomParserCompilerBackend *compiler; Flags m_flags; QBiPointer<const QQmlImports, QQmlTypeNameCache> imports; friend class QQmlPropertyValidator; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 96fb2f1cdb..5bf8479e55 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -621,8 +621,14 @@ QQmlEnginePrivate::~QQmlEnginePrivate() for (TypePropertyCacheIt iter = typePropertyCache.begin(), end = typePropertyCache.end(); iter != end; ++iter) (*iter)->release(); - for (CompositeTypesIt iter = m_compositeTypes.begin(), end = m_compositeTypes.end(); iter != end; ++iter) + for (CompositeTypesIt iter = m_compositeTypes.begin(), end = m_compositeTypes.end(); iter != end; ++iter) { iter.value()->isRegisteredWithEngine = false; + + // since unregisterInternalCompositeType() will not be called in this + // case, we have to clean up the type registration manually + QMetaType::unregisterType(iter.value()->metaTypeId); + QMetaType::unregisterType(iter.value()->listMetaTypeId); + } delete profiler; } @@ -2337,6 +2343,9 @@ void QQmlEnginePrivate::unregisterInternalCompositeType(QQmlCompiledData *data) Locker locker(this); m_qmlLists.remove(lst_type); m_compositeTypes.remove(ptr_type); + + QMetaType::unregisterType(ptr_type); + QMetaType::unregisterType(lst_type); } bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 18f882e1e0..35e0bc8c64 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -149,8 +149,8 @@ QQmlExpression::QQmlExpression(const QQmlScriptString &script, QQmlContext *ctxt if (scriptPrivate->context) { QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context); QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine()); - if (engine && ctxtdata && !ctxtdata->url.isEmpty() && ctxtdata->typeCompilationUnit) { - d->url = ctxtdata->url.toString(); + if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit) { + d->url = ctxtdata->urlString(); d->line = scriptPrivate->lineNumber; d->column = scriptPrivate->columnNumber; diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 6a5cab02fd..906e073cab 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1829,7 +1829,7 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b { // Create a scope for QWriteLocker to keep it as narrow as possible, and // to ensure that we release it before the call to initalizeEngine below - QWriteLocker lock(QQmlMetaType::typeRegistrationLock()); + QMutexLocker lock(QQmlMetaType::typeRegistrationLock()); if (!typeNamespace.isEmpty()) { // This is an 'identified' module diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp index 85979b8dc0..b9f96a724c 100644 --- a/src/qml/qml/qqmlinfo.cpp +++ b/src/qml/qml/qqmlinfo.cpp @@ -140,7 +140,7 @@ QQmlInfo::~QQmlInfo() QQmlData *ddata = QQmlData::get(object, false); if (ddata && ddata->outerContext) { - error.setUrl(ddata->outerContext->url); + error.setUrl(ddata->outerContext->url()); error.setLine(ddata->lineNumber); error.setColumn(ddata->columnNumber); } diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 6411b569ee..6919042e0f 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -40,6 +40,7 @@ #include <private/qv4script_p.h> #include <private/qv4errorobject_p.h> #include <private/qv4scopedvalue_p.h> +#include <private/qqmlglobal_p.h> QT_BEGIN_NAMESPACE @@ -59,11 +60,11 @@ bool QQmlDelayedError::addError(QQmlEnginePrivate *e) return true; } -void QQmlDelayedError::setErrorLocation(const QUrl &url, quint16 line, quint16 column) +void QQmlDelayedError::setErrorLocation(const QQmlSourceLocation &sourceLocation) { - m_error.setUrl(url); - m_error.setLine(line); - m_error.setColumn(column); + m_error.setUrl(QUrl(sourceLocation.sourceFile)); + m_error.setLine(sourceLocation.line); + m_error.setColumn(sourceLocation.column); } void QQmlDelayedError::setErrorDescription(const QString &description) diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h index 3f1a8c173d..989d5a0b0d 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +struct QQmlSourceLocation; + class QQmlDelayedError { public: @@ -72,7 +74,7 @@ public: inline const QQmlError &error() const { return m_error; } inline void clearError() { m_error = QQmlError(); } - void setErrorLocation(const QUrl &url, quint16 line, quint16 column); + void setErrorLocation(const QQmlSourceLocation &sourceLocation); void setErrorDescription(const QString &description); void setErrorObject(QObject *object); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 9779773b05..2f7834fa41 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -127,7 +127,7 @@ public: }; Q_GLOBAL_STATIC(QQmlMetaTypeData, metaTypeData) -Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, metaTypeDataLock, (QReadWriteLock::Recursive)) +Q_GLOBAL_STATIC_WITH_ARGS(QMutex, metaTypeDataLock, (QMutex::Recursive)) static uint qHash(const QQmlMetaTypeData::VersionedUri &v) { @@ -565,7 +565,7 @@ void QQmlTypePrivate::init() const if (isSetup) return; - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); if (isSetup) return; @@ -646,7 +646,7 @@ void QQmlTypePrivate::initEnums() const init(); - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); if (isEnumSetup) return; if (baseMetaObject) // could be singleton type without metaobject @@ -1000,7 +1000,7 @@ void QQmlTypeModulePrivate::add(QQmlType *type) QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QList<QQmlType *> *types = d->typeHash.value(name); if (!types) return 0; @@ -1014,7 +1014,7 @@ QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor) QQmlType *QQmlTypeModule::type(const QV4::String *name, int minor) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QList<QQmlType *> *types = d->typeHash.value(name); if (!types) return 0; @@ -1028,7 +1028,7 @@ QQmlType *QQmlTypeModule::type(const QV4::String *name, int minor) QList<QQmlType*> QQmlTypeModule::singletonTypes(int minor) const { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QList<QQmlType *> retn; for (int ii = 0; ii < d->types.count(); ++ii) { @@ -1089,7 +1089,7 @@ QQmlType *QQmlTypeModuleVersion::type(const QV4::String *name) const void qmlClearTypeRegistrations() // Declared in qqml.h { //Only cleans global static, assumed no running engine - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); for (int i = 0; i < data->types.count(); ++i) @@ -1112,7 +1112,7 @@ void qmlClearTypeRegistrations() // Declared in qqml.h int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent) { - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); data->parentFunctions.append(autoparent.function); @@ -1125,7 +1125,7 @@ int registerInterface(const QQmlPrivate::RegisterInterface &interface) if (interface.version > 0) qFatal("qmlRegisterType(): Cannot mix incompatible QML versions."); - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); int index = data->types.count(); @@ -1163,7 +1163,7 @@ QString registrationTypeString(QQmlType::RegistrationType typeType) return typeStr; } -// NOTE: caller must hold a QWriteLocker on "data" +// NOTE: caller must hold a QMutexLocker on "data" bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, const char *uri, const QString &typeName, int majorVersion = -1) { if (!typeName.isEmpty()) { @@ -1214,7 +1214,7 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da return true; } -// NOTE: caller must hold a QWriteLocker on "data" +// NOTE: caller must hold a QMutexLocker on "data" void addTypeToData(QQmlType* type, QQmlMetaTypeData *data) { if (!type->elementName().isEmpty()) @@ -1253,7 +1253,7 @@ void addTypeToData(QQmlType* type, QQmlMetaTypeData *data) int registerType(const QQmlPrivate::RegisterType &type) { - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QString elementName = QString::fromUtf8(type.elementName); if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor)) @@ -1273,7 +1273,7 @@ int registerType(const QQmlPrivate::RegisterType &type) int registerSingletonType(const QQmlPrivate::RegisterSingletonType &type) { - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QString typeName = QString::fromUtf8(type.typeName); if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor)) @@ -1292,7 +1292,7 @@ int registerSingletonType(const QQmlPrivate::RegisterSingletonType &type) int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type) { // Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type. - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QString typeName = QString::fromUtf8(type.typeName); bool fileImport = false; @@ -1317,7 +1317,7 @@ int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingleton int registerCompositeType(const QQmlPrivate::RegisterCompositeType &type) { // Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type. - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QString typeName = QString::fromUtf8(type.typeName); bool fileImport = false; @@ -1342,7 +1342,7 @@ int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRe { if (hookRegistration.version > 0) qFatal("qmlRegisterType(): Cannot mix incompatible QML versions."); - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); data->lookupCachedQmlUnit << hookRegistration.lookupCachedQmlUnit; return 0; @@ -1375,7 +1375,7 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) //From qqml.h bool qmlProtectModule(const char *uri, int majVersion) { - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlMetaTypeData::VersionedUri versionedUri; @@ -1424,7 +1424,7 @@ QStringList QQmlMetaType::typeRegistrationFailures() return data->typeRegistrationFailures; } -QReadWriteLock *QQmlMetaType::typeRegistrationLock() +QMutex *QQmlMetaType::typeRegistrationLock() { return metaTypeDataLock(); } @@ -1434,7 +1434,7 @@ QReadWriteLock *QQmlMetaType::typeRegistrationLock() */ bool QQmlMetaType::isAnyModule(const QString &uri) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin(); @@ -1451,7 +1451,7 @@ bool QQmlMetaType::isAnyModule(const QString &uri) */ bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlMetaTypeData::VersionedUri versionedUri; @@ -1472,7 +1472,7 @@ bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion) bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor) { Q_ASSERT(versionMajor >= 0 && versionMinor >= 0); - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); @@ -1487,14 +1487,14 @@ bool QQmlMetaType::isModule(const QString &module, int versionMajor, int version QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion)); } QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions() { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return data->parentFunctions; } @@ -1516,7 +1516,7 @@ bool QQmlMetaType::isQObject(int userType) if (userType == QMetaType::QObjectStar) return true; - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType); } @@ -1526,7 +1526,7 @@ bool QQmlMetaType::isQObject(int userType) */ int QQmlMetaType::listType(int id) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlType *type = data->idToType.value(id); if (type && type->qListTypeId() == id) @@ -1537,7 +1537,7 @@ int QQmlMetaType::listType(int id) int QQmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlType *type = data->metaObjectToType.value(mo); @@ -1551,7 +1551,7 @@ QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(int id) { if (id < 0) return 0; - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return data->types.at(id)->attachedPropertiesFunction(); } @@ -1615,7 +1615,7 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType) if (userType == QMetaType::QObjectStar) return Object; - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); if (userType < data->objects.size() && data->objects.testBit(userType)) return Object; @@ -1627,14 +1627,14 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType) bool QQmlMetaType::isInterface(int userType) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType); } const char *QQmlMetaType::interfaceIId(int userType) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlType *type = data->idToType.value(userType); lock.unlock(); @@ -1646,7 +1646,7 @@ const char *QQmlMetaType::interfaceIId(int userType) bool QQmlMetaType::isList(int userType) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType); } @@ -1668,7 +1668,7 @@ bool QQmlMetaType::isList(int userType) */ void QQmlMetaType::registerCustomStringConverter(int type, StringConverter converter) { - QWriteLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); if (data->stringConverters.contains(type)) @@ -1682,7 +1682,7 @@ void QQmlMetaType::registerCustomStringConverter(int type, StringConverter conve */ QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return data->stringConverters.value(type); @@ -1711,7 +1711,7 @@ QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor) { Q_ASSERT(version_major >= 0 && version_minor >= 0); - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name); @@ -1731,7 +1731,7 @@ QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStrin */ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return data->metaObjectToType.value(metaObject); @@ -1745,7 +1745,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject) QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor) { Q_ASSERT(version_major >= 0 && version_minor >= 0); - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject); @@ -1765,7 +1765,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStri */ QQmlType *QQmlMetaType::qmlType(int userType) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlType *type = data->idToType.value(userType); @@ -1783,7 +1783,7 @@ QQmlType *QQmlMetaType::qmlType(int userType) */ QQmlType *QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* = false */) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlType *type = data->urlToType.value(url); @@ -1803,7 +1803,7 @@ QQmlType *QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* = */ QQmlType *QQmlMetaType::qmlTypeFromIndex(int idx) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); if (idx < 0 || idx >= data->types.count()) @@ -1816,7 +1816,7 @@ QQmlType *QQmlMetaType::qmlTypeFromIndex(int idx) */ QList<QString> QQmlMetaType::qmlTypeNames() { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QList<QString> names; @@ -1834,7 +1834,7 @@ QList<QString> QQmlMetaType::qmlTypeNames() */ QList<QQmlType*> QQmlMetaType::qmlTypes() { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return data->nameToType.values(); @@ -1845,7 +1845,7 @@ QList<QQmlType*> QQmlMetaType::qmlTypes() */ QList<QQmlType*> QQmlMetaType::qmlAllTypes() { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); return data->types; @@ -1856,7 +1856,7 @@ QList<QQmlType*> QQmlMetaType::qmlAllTypes() */ QList<QQmlType*> QQmlMetaType::qmlSingletonTypes() { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QList<QQmlType*> alltypes = data->nameToType.values(); @@ -1872,7 +1872,7 @@ QList<QQmlType*> QQmlMetaType::qmlSingletonTypes() const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(const QUrl &uri) { - QReadLocker lock(metaTypeDataLock()); + QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); for (QVector<QQmlPrivate::QmlUnitCacheLookupFunction>::ConstIterator it = data->lookupCachedQmlUnit.constBegin(), end = data->lookupCachedQmlUnit.constEnd(); it != end; ++it) { diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 63e6e3bec8..e5ac20d314 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -62,7 +62,7 @@ class QQmlTypePrivate; class QQmlTypeModule; class QHashedString; class QHashedStringRef; -class QReadWriteLock; +class QMutex; namespace QV4 { struct String; } @@ -121,7 +121,7 @@ public: static void setTypeRegistrationNamespace(const QString &); static QStringList typeRegistrationFailures(); - static QReadWriteLock *typeRegistrationLock(); + static QMutex *typeRegistrationLock(); }; struct QQmlMetaTypeData; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 9abd1859b7..3c2f3690b9 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -113,6 +113,7 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext) { parentContext = providedParentContext; engine = parentContext->engine; + v4 = QV8Engine::getV4(engine); if (!compiledData->isInitialized()) compiledData->initialize(engine); @@ -123,10 +124,11 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext) _scopeObject = 0; _valueTypeProperty = 0; _compiledObject = 0; + _compiledObjectIndex = -1; _ddata = 0; _propertyCache = 0; _vmeMetaObject = 0; - _qmlContext = 0; + _qmlBindingWrapper = 0; } QQmlObjectCreator::~QQmlObjectCreator() @@ -174,8 +176,6 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI context = new QQmlContextData; context->isInternal = true; - context->url = compiledData->url(); - context->urlString = compiledData->fileName(); context->imports = compiledData->importCache; context->imports->addref(); context->typeCompilationUnit = compiledData->compilationUnit; @@ -187,26 +187,15 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI sharedState->rootContext->isRootObjectInCreation = true; } - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QV4::Scope scope(v4); Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator); if (topLevelCreator) sharedState->allJavaScriptObjects = scope.alloc(compiledData->totalObjectCount); - QVector<QQmlContextData::ObjectIdMapping> mapping(objectIndexToId.count()); - for (QHash<int, int>::ConstIterator it = objectIndexToId.constBegin(), end = objectIndexToId.constEnd(); - it != end; ++it) { - const QV4::CompiledData::Object *obj = qmlUnit->objectAt(it.key()); + context->setIdPropertyData(objectIndexToId); - QQmlContextData::ObjectIdMapping m; - m.id = it.value(); - m.name = stringAt(obj->idIndex); - mapping[m.id] = m; - } - context->setIdPropertyData(mapping); - - if (subComponentIndex == -1) { + if (subComponentIndex == -1 && compiledData->scripts.count()) { QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count())); context->importedScripts.set(v4, scripts); for (int i = 0; i < compiledData->scripts.count(); ++i) { @@ -245,9 +234,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance) QQmlData *declarativeData = QQmlData::get(instance); context = declarativeData->deferredData->context; sharedState->rootContext = context; - const int objectIndex = declarativeData->deferredData->deferredIdx; - const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex); QObject *bindingTarget = instance; QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache; @@ -256,29 +243,30 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance) QObject *scopeObject = instance; qSwap(_scopeObject, scopeObject); - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QV4::Scope valueScope(v4); Q_ASSERT(topLevelCreator); Q_ASSERT(!sharedState->allJavaScriptObjects); sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->totalObjectCount); - QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject)); - QV4::ScopedContext global(valueScope, valueScope.engine->rootContext()); - QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope)); - // ### GC - QV4::ExecutionContext *qmlContext = QV4::ScopedContext(valueScope, qmlBindingWrapper->context()); + QV4::Value *qmlBindingWrapper = valueScope.alloc(1); - qSwap(_qmlContext, qmlContext); + qSwap(_qmlBindingWrapper, qmlBindingWrapper); qSwap(_propertyCache, cache); qSwap(_qobject, instance); + + int objectIndex = declarativeData->deferredData->deferredIdx; + qSwap(_compiledObjectIndex, objectIndex); + + const QV4::CompiledData::Object *obj = qmlUnit->objectAt(_compiledObjectIndex); qSwap(_compiledObject, obj); + qSwap(_ddata, declarativeData); qSwap(_bindingTarget, bindingTarget); qSwap(_vmeMetaObject, vmeMetaObject); - QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(objectIndex); + QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(_compiledObjectIndex); for (int i = 0; i < bindingSkipList.count(); ++i) bindingSkipList.setBit(i, !bindingSkipList.testBit(i)); @@ -288,10 +276,11 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance) qSwap(_bindingTarget, bindingTarget); qSwap(_ddata, declarativeData); qSwap(_compiledObject, obj); + qSwap(_compiledObjectIndex, objectIndex); qSwap(_qobject, instance); qSwap(_propertyCache, cache); - qSwap(_qmlContext, qmlContext); + qSwap(_qmlBindingWrapper, qmlBindingWrapper); qSwap(_scopeObject, scopeObject); phase = ObjectsCreated; @@ -299,14 +288,13 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance) return errors.isEmpty(); } -void QQmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) +void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) { QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::RemoveBindingOnAliasWrite; int propertyWriteStatus = -1; void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags }; - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QV4::Scope scope(v4); int propertyType = property->propType; @@ -654,13 +642,12 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip) QQmlListProperty<void> savedList; qSwap(_currentList, savedList); - QQmlPropertyData *property = 0; - QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty(); + const QV4::CompiledData::BindingPropertyData &propertyData = compiledData->compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex); - QString id = stringAt(_compiledObject->idIndex); - if (!id.isEmpty()) { - QQmlPropertyData *idProperty = _propertyCache->property(QStringLiteral("id"), _qobject, context); - if (idProperty && idProperty->isWritable() && idProperty->propType == QMetaType::QString) { + if (_compiledObject->idIndex) { + const QQmlPropertyData *idProperty = propertyData.last(); + Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QStringLiteral("id")); + if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType == QMetaType::QString) { QV4::CompiledData::Binding idBinding; idBinding.propertyNameIndex = 0; // Not used idBinding.flags = 0; @@ -686,50 +673,40 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip) if (qmlTypeForObject(_bindingTarget)) { quint32 bindingSkipList = 0; + QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty(); + const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable(); for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) { - property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty; + QQmlPropertyData *property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty; if (property) bindingSkipList |= (1 << property->coreIndex); } - property = 0; proxy->removeBindings(bindingSkipList); } } } + int currentListPropertyIndex = -1; + const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable(); for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) { + if (static_cast<int>(i) < bindingsToSkip.size() && bindingsToSkip.testBit(i)) + continue; - QString name = stringAt(binding->propertyNameIndex); - if (name.isEmpty()) - property = 0; - - if (!property - || (i > 0 && ((binding - 1)->propertyNameIndex != binding->propertyNameIndex - || (binding - 1)->flags != binding->flags)) - ) { - if (!name.isEmpty()) { - if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression - || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) - property = QmlIR::PropertyResolver(_propertyCache).signal(name, /*notInRevision*/0, _qobject, context); - else - property = _propertyCache->property(name, _qobject, context); - } else - property = defaultProperty; - - if (property && property->isQList()) { + const QQmlPropertyData *property = propertyData.at(i); + + if (property && property->isQList()) { + if (property->coreIndex != currentListPropertyIndex) { void *argv[1] = { (void*)&_currentList }; QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv); - } else if (_currentList.object) - _currentList = QQmlListProperty<void>(); - + currentListPropertyIndex = property->coreIndex; + } + } else if (_currentList.object) { + _currentList = QQmlListProperty<void>(); + currentListPropertyIndex = -1; } - if (static_cast<int>(i) < bindingsToSkip.size() && bindingsToSkip.testBit(i)) - continue; - if (!setPropertyBinding(property, binding)) return; } @@ -737,7 +714,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip) qSwap(_currentList, savedList); } -bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) +bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) { if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty()); @@ -785,7 +762,7 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4 QObject *groupObject = 0; QQmlValueType *valueType = 0; - QQmlPropertyData *valueTypeProperty = 0; + const QQmlPropertyData *valueTypeProperty = 0; QObject *bindingTarget = _bindingTarget; if (QQmlValueTypeFactory::isValueType(property->propType)) { @@ -828,8 +805,9 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4 if (binding->type == QV4::CompiledData::Binding::Type_Script) { QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]; - QV4::Scope scope(_qmlContext); - QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(_qmlContext, runtimeFunction, /*createProto*/ false)); + QV4::Scope scope(v4); + QV4::ScopedContext qmlContext(scope, currentQmlContext()); + QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction, /*createProto*/ false)); if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) { int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex); @@ -948,7 +926,6 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4 } } else if (property->propType == QMetaType::QVariant) { if (property->isVarProperty()) { - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QV4::Scope scope(v4); QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(QV8Engine::getV4(engine), createdSubObject)); _vmeMetaObject->setVMEProperty(property->coreIndex, wrappedObject); @@ -995,8 +972,9 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4 void QQmlObjectCreator::setupFunctions() { - QV4::Scope scope(_qmlContext); + QV4::Scope scope(v4); QV4::ScopedValue function(scope); + QV4::ScopedContext qmlContext(scope, currentQmlContext()); const quint32 *functionIdx = _compiledObject->functionOffsetTable(); for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) { @@ -1007,7 +985,7 @@ void QQmlObjectCreator::setupFunctions() if (!property->isVMEFunction()) continue; - function = QV4::FunctionObject::createScriptFunction(_qmlContext, runtimeFunction); + function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction); _vmeMetaObject->setVmeMethod(property->coreIndex, function); } } @@ -1029,6 +1007,17 @@ void QQmlObjectCreator::registerObjectWithContextById(int objectIndex, QObject * context->setIdProperty(idEntry.value(), instance); } +QV4::Heap::ExecutionContext *QQmlObjectCreator::currentQmlContext() +{ + if (!_qmlBindingWrapper->objectValue()) { + QV4::Scope valueScope(v4); + QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject)); + QV4::ScopedContext global(valueScope, v4->rootContext()); + *_qmlBindingWrapper = v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope); + } + return static_cast<QV4::QmlBindingWrapper*>(_qmlBindingWrapper->objectValue())->context(); +} + QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject) { QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler); @@ -1046,7 +1035,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo isComponent = true; QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent); Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(QStringLiteral("<component>"), - context->url, obj->location.line, obj->location.column)); + context->url(), obj->location.line, obj->location.column)); QQmlComponentPrivate::get(component)->creationContext = context; instance = component; ddata = QQmlData::get(instance, /*create*/true); @@ -1057,7 +1046,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo QQmlType *type = typeRef->type; if (type) { Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(type->qmlTypeName(), - context->url, obj->location.line, obj->location.column)); + context->url(), obj->location.line, obj->location.column)); instance = type->create(); if (!instance) { recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex))); @@ -1080,7 +1069,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo } else { Q_ASSERT(typeRef->component); Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(typeRef->component->fileName(), - context->url, obj->location.line, obj->location.column)); + context->url(), obj->location.line, obj->location.column)); if (typeRef->component->compilationUnit->data->isSingleton()) { recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex))); @@ -1168,24 +1157,18 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo QObject *scopeObject = instance; qSwap(_scopeObject, scopeObject); - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); - Q_ASSERT(sharedState->allJavaScriptObjects); *sharedState->allJavaScriptObjects = QV4::QObjectWrapper::wrap(v4, instance); ++sharedState->allJavaScriptObjects; QV4::Scope valueScope(v4); - QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject)); - QV4::ScopedContext global(valueScope, valueScope.engine->rootContext()); - QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope)); - // ### GC - QV4::ExecutionContext *qmlContext = QV4::ScopedContext(valueScope, qmlBindingWrapper->context()); + QV4::Value *qmlBindingWrapper = valueScope.alloc(1); - qSwap(_qmlContext, qmlContext); + qSwap(_qmlBindingWrapper, qmlBindingWrapper); bool result = populateInstance(index, instance, /*binding target*/instance, /*value type property*/0, bindingsToSkip); - qSwap(_qmlContext, qmlContext); + qSwap(_qmlBindingWrapper, qmlBindingWrapper); qSwap(_scopeObject, scopeObject); return result ? instance : 0; @@ -1277,26 +1260,25 @@ void QQmlObjectCreator::clear() phase = Done; } -bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip) +bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip) { - const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index); - QQmlData *declarativeData = QQmlData::get(instance, /*create*/true); qSwap(_qobject, instance); qSwap(_valueTypeProperty, valueTypeProperty); + qSwap(_compiledObjectIndex, index); + const QV4::CompiledData::Object *obj = qmlUnit->objectAt(_compiledObjectIndex); qSwap(_compiledObject, obj); qSwap(_ddata, declarativeData); qSwap(_bindingTarget, bindingTarget); - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QV4::Scope valueScope(v4); QV4::ScopedValue scopeObjectProtector(valueScope); - QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(index); + QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(_compiledObjectIndex); QQmlVMEMetaObject *vmeMetaObject = 0; - const QByteArray data = vmeMetaObjectData.value(index); + const QByteArray data = vmeMetaObjectData.value(_compiledObjectIndex); if (!data.isEmpty()) { Q_ASSERT(!cache.isNull()); // install on _object @@ -1310,14 +1292,14 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * vmeMetaObject = QQmlVMEMetaObject::get(_qobject); } - registerObjectWithContextById(index, _qobject); + registerObjectWithContextById(_compiledObjectIndex, _qobject); qSwap(_propertyCache, cache); qSwap(_vmeMetaObject, vmeMetaObject); QBitArray bindingSkipList = bindingsToSkip; { - QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(index); + QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(_compiledObjectIndex); if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) { if (bindingSkipList.isEmpty()) bindingSkipList.resize(deferredBindings->count()); @@ -1326,7 +1308,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * if (deferredBindings->testBit(i)) bindingSkipList.setBit(i); QQmlData::DeferredData *deferData = new QQmlData::DeferredData; - deferData->deferredIdx = index; + deferData->deferredIdx = _compiledObjectIndex; deferData->compiledData = compiledData; deferData->compiledData->addref(); deferData->context = context; @@ -1334,13 +1316,15 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * } } - setupFunctions(); + if (_compiledObject->nFunctions > 0) + setupFunctions(); setupBindings(bindingSkipList); qSwap(_vmeMetaObject, vmeMetaObject); qSwap(_bindingTarget, bindingTarget); qSwap(_ddata, declarativeData); qSwap(_compiledObject, obj); + qSwap(_compiledObjectIndex, index); qSwap(_valueTypeProperty, valueTypeProperty); qSwap(_qobject, instance); qSwap(_propertyCache, cache); diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 3886155786..60fefe494f 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -94,12 +94,12 @@ private: QObject *createInstance(int index, QObject *parent = 0, bool isContextObject = false); bool populateInstance(int index, QObject *instance, - QObject *bindingTarget, QQmlPropertyData *valueTypeProperty, + QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip = QBitArray()); void setupBindings(const QBitArray &bindingsToSkip); - bool setPropertyBinding(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding); - void setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding); + bool setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding); + void setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding); void setupFunctions(); QString stringAt(int idx) const { return qmlUnit->stringAt(idx); } @@ -107,6 +107,8 @@ private: void registerObjectWithContextById(int objectIndex, QObject *instance) const; + QV4::Heap::ExecutionContext *currentQmlContext(); + enum Phase { Startup, CreatingObjects, @@ -117,6 +119,7 @@ private: } phase; QQmlEngine *engine; + QV4::ExecutionEngine *v4; QQmlCompiledData *compiledData; const QV4::CompiledData::Unit *qmlUnit; QQmlGuardedContextData parentContext; @@ -133,13 +136,14 @@ private: QObject *_scopeObject; QObject *_bindingTarget; - QQmlPropertyData *_valueTypeProperty; // belongs to _qobjectForBindings's property cache + const QQmlPropertyData *_valueTypeProperty; // belongs to _qobjectForBindings's property cache + int _compiledObjectIndex; const QV4::CompiledData::Object *_compiledObject; QQmlData *_ddata; QQmlRefPointer<QQmlPropertyCache> _propertyCache; QQmlVMEMetaObject *_vmeMetaObject; QQmlListProperty<void> _currentList; - QV4::ExecutionContext *_qmlContext; + QV4::Value *_qmlBindingWrapper; friend struct QQmlObjectCreatorRecursionWatcher; }; diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index aef2bf0420..1036d68713 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -53,6 +53,7 @@ #include <QStringList> #include <private/qmetaobject_p.h> +#include <private/qqmlvaluetypewrapper_p.h> #include <QtCore/qdebug.h> Q_DECLARE_METATYPE(QList<int>) @@ -1519,6 +1520,11 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, QUICK_STORE(QString, result.toQStringNoThrow()) break; default: + if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) { + if (vtw->d()->valueType->typeId == core.propType) { + return vtw->write(object, core.coreIndex); + } + } break; } } diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 0bf8043cdb..d713e9ee03 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2478,8 +2478,8 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare ctxt->isPragmaLibraryContext = true; else ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext; - ctxt->url = url; - ctxt->urlString = urlString; + ctxt->baseUrl = url; + ctxt->baseUrlString = urlString; // For backward compatibility, if there are no imports, we need to use the // imports from the parent context. See QTBUG-17518. diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 3b8a17960e..3d22b0b38f 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -51,6 +51,9 @@ DEFINE_OBJECT_VTABLE(QmlTypeWrapper); Heap::QmlTypeWrapper::QmlTypeWrapper(ExecutionEngine *engine) : Heap::Object(engine) , mode(IncludeEnums) + , type(Q_NULLPTR) + , typeNamespace(Q_NULLPTR) + , importNamespace(Q_NULLPTR) { } diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 490ac66f1f..341ddf802d 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -38,6 +38,7 @@ #include <QtCore/qdebug.h> #include <private/qmetaobjectbuilder_p.h> #include <private/qqmlmodelindexvaluetype_p.h> +#include <private/qmetatype_p.h> QT_BEGIN_NAMESPACE @@ -182,8 +183,9 @@ void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, } QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) - : typeId(typeId) - , gadgetPtr(QMetaType::create(typeId)) + : gadgetPtr(QMetaType::create(typeId)) + , typeId(typeId) + , metaType(typeId) { QObjectPrivate *op = QObjectPrivate::get(this); Q_ASSERT(!op->metaObject); @@ -201,7 +203,7 @@ QQmlValueType::~QQmlValueType() Q_ASSERT(op->metaObject == this); op->metaObject = 0; ::free((void*)_metaObject); - QMetaType::destroy(typeId, gadgetPtr); + metaType.destroy(gadgetPtr); } void QQmlValueType::read(QObject *obj, int idx) @@ -227,8 +229,8 @@ QVariant QQmlValueType::value() void QQmlValueType::setValue(const QVariant &value) { Q_ASSERT(typeId == value.userType()); - QMetaType::destruct(typeId, gadgetPtr); - QMetaType::construct(typeId, gadgetPtr, value.constData()); + metaType.destruct(gadgetPtr); + metaType.construct(gadgetPtr, value.constData()); } QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *) diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index f534fedf5d..be453ae35a 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -75,8 +75,11 @@ public: private: const QMetaObject *_metaObject; - int typeId; void *gadgetPtr; + +public: + int typeId; + QMetaType metaType; }; class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 0f48c91737..77d76e89c8 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -79,27 +79,31 @@ using namespace QV4; Heap::QQmlValueTypeWrapper::QQmlValueTypeWrapper(ExecutionEngine *engine) : Heap::Object(engine) - , gadgetPtr(0) { } Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper() { - if (gadgetPtr) - QMetaType::destroy(metaType, gadgetPtr); + if (gadgetPtr) { + valueType->metaType.destruct(gadgetPtr); + ::operator delete(gadgetPtr); + } } void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const { - Q_ASSERT(metaType == value.userType()); - QMetaType::destruct(metaType, gadgetPtr); - QMetaType::construct(metaType, gadgetPtr, value.constData()); + Q_ASSERT(valueType->typeId == value.userType()); + if (gadgetPtr) + valueType->metaType.destruct(gadgetPtr); + if (!gadgetPtr) + gadgetPtr = ::operator new(valueType->metaType.sizeOf()); + valueType->metaType.construct(gadgetPtr, value.constData()); } QVariant Heap::QQmlValueTypeWrapper::toVariant() const { Q_ASSERT(gadgetPtr); - return QVariant(metaType, gadgetPtr); + return QVariant(valueType->typeId, gadgetPtr); } @@ -123,7 +127,7 @@ bool QQmlValueTypeReference::readReferenceValue() const QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, a); int variantReferenceType = variantReferenceValue.userType(); - if (variantReferenceType != d()->metaType) { + if (variantReferenceType != typeId()) { // This is a stale VariantReference. That is, the variant has been // overwritten with a different type in the meantime. // We need to modify this reference to the updated value type, if @@ -132,24 +136,27 @@ bool QQmlValueTypeReference::readReferenceValue() const QQmlPropertyCache *cache = 0; if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType)) cache = QJSEnginePrivate::get(engine())->cache(mo); - if (d()->gadgetPtr) - QMetaType::destroy(d()->metaType, d()->gadgetPtr); - d()->gadgetPtr = 0; + if (d()->gadgetPtr) { + d()->valueType->metaType.destruct(d()->gadgetPtr); + ::operator delete(d()->gadgetPtr); + } + d()->gadgetPtr =0; d()->propertyCache = cache; - d()->metaType = variantReferenceType; - if (cache) { - d()->gadgetPtr = QMetaType::create(d()->metaType); - } else { + d()->valueType = QQmlValueTypeFactory::valueType(variantReferenceType); + if (!cache) return false; - } } else { return false; } } d()->setValue(variantReferenceValue); } else { + if (!d()->gadgetPtr) { + d()->gadgetPtr = ::operator new(d()->valueType->metaType.sizeOf()); + d()->valueType->metaType.construct(d()->gadgetPtr, 0); + } // value-type reference - void *args[] = { d()->gadget(), 0 }; + void *args[] = { d()->gadgetPtr, 0 }; QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, args); } return true; @@ -176,8 +183,8 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj r->setPrototype(proto); r->d()->object = object; r->d()->property = property; r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject); - r->d()->metaType = typeId; - r->d()->gadgetPtr = QMetaType::create(r->d()->metaType); + r->d()->valueType = QQmlValueTypeFactory::valueType(typeId); + r->d()->gadgetPtr = 0; return r->asReturnedValue(); } @@ -190,8 +197,8 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype); r->setPrototype(proto); r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject); - r->d()->metaType = typeId; - r->d()->gadgetPtr = QMetaType::create(r->d()->metaType); + r->d()->valueType = QQmlValueTypeFactory::valueType(typeId); + r->d()->gadgetPtr = 0; r->d()->setValue(value); return r->asReturnedValue(); } @@ -204,11 +211,15 @@ QVariant QQmlValueTypeWrapper::toVariant() const return d()->toVariant(); } -void QQmlValueTypeWrapper::toGadget(void *data) const +bool QQmlValueTypeWrapper::toGadget(void *data) const { - int typeId = d()->metaType; + if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>()) + if (!ref->readReferenceValue()) + return false; + const int typeId = d()->valueType->typeId; QMetaType::destruct(typeId, data); - QMetaType::construct(typeId, data, d()->gadget()); + QMetaType::construct(typeId, data, d()->gadgetPtr); + return true; } void QQmlValueTypeWrapper::destroy(Heap::Base *that) @@ -248,6 +259,36 @@ bool QQmlValueTypeWrapper::isEqual(const QVariant& value) return (value == d()->toVariant()); } +int QQmlValueTypeWrapper::typeId() const +{ + return d()->valueType->typeId; +} + +bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const +{ + bool destructGadgetOnExit = false; + if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>()) { + if (!d()->gadgetPtr) { + d()->gadgetPtr = alloca(d()->valueType->metaType.sizeOf()); + d()->valueType->metaType.construct(d()->gadgetPtr, 0); + destructGadgetOnExit = true; + } + if (!ref->readReferenceValue()) + return false; + } + + int flags = 0; + int status = -1; + void *a[] = { d()->gadgetPtr, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, propertyIndex, a); + + if (destructGadgetOnExit) { + d()->valueType->metaType.destruct(d()->gadgetPtr); + d()->gadgetPtr = 0; + } + return true; +} + ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx) { Object *o = ctx->thisObject().as<Object>(); @@ -265,15 +306,15 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx) // Prepare a buffer to pass to QMetaType::convert() QString convertResult; convertResult.~QString(); - if (QMetaType::convert(w->d()->gadgetPtr, w->d()->metaType, &convertResult, QMetaType::QString)) { + if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->typeId, &convertResult, QMetaType::QString)) { result = convertResult; } else { - result = QString::fromUtf8(QMetaType::typeName(w->d()->metaType)); + result = QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId)); result += QLatin1Char('('); const QMetaObject *mo = w->d()->propertyCache->metaObject(); const int propCount = mo->propertyCount(); for (int i = 0; i < propCount; ++i) { - QVariant value = mo->property(i).readOnGadget(w->d()->gadget()); + QVariant value = mo->property(i).readOnGadget(w->d()->gadgetPtr); result += value.toString(); if (i < propCount - 1) result += QStringLiteral(", "); @@ -322,7 +363,7 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha int index = result->coreIndex; QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index); - void *gadget = r->d()->gadget(); + void *gadget = r->d()->gadgetPtr; // These four types are the most common used by the value type wrappers VALUE_TYPE_LOAD(QMetaType::QReal, qreal, qreal); @@ -411,7 +452,7 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) if (property.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) v = v.toInt(); - void *gadget = r->d()->gadget(); + void *gadget = r->d()->gadgetPtr; property.writeOnGadget(gadget, v); @@ -427,7 +468,7 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) } else { int flags = 0; int status = -1; - void *a[] = { r->d()->gadget(), 0, &status, &flags }; + void *a[] = { r->d()->gadgetPtr, 0, &status, &flags }; QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a); } } diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h index 08b3ec76e9..efc4a78835 100644 --- a/src/qml/qml/qqmlvaluetypewrapper_p.h +++ b/src/qml/qml/qqmlvaluetypewrapper_p.h @@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE class QV8Engine; +class QQmlValueType; namespace QV4 { @@ -62,13 +63,12 @@ namespace Heap { struct QQmlValueTypeWrapper : Object { QQmlValueTypeWrapper(ExecutionEngine *engine); ~QQmlValueTypeWrapper(); - mutable QQmlRefPointer<QQmlPropertyCache> propertyCache; + QQmlRefPointer<QQmlPropertyCache> propertyCache; mutable void *gadgetPtr; - mutable int metaType; + QQmlValueType *valueType; void setValue(const QVariant &value) const; QVariant toVariant() const; - void *gadget() const { return gadgetPtr; } }; } @@ -84,8 +84,10 @@ public: static ReturnedValue create(ExecutionEngine *engine, const QVariant &, const QMetaObject *metaObject, int typeId); QVariant toVariant() const; - void toGadget(void *data) const; + bool toGadget(void *data) const; bool isEqual(const QVariant& value); + int typeId() const; + bool write(QObject *target, int propertyIndex) const; static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); static void put(Managed *m, String *name, const Value &value); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 39196e0e65..33c687dcd0 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -815,8 +815,15 @@ ReturnedValue QtObject::method_formatDateTime(QV4::CallContext *ctx) } /*! -\qmlmethod bool Qt::openUrlExternally(url target) -Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise. + \qmlmethod bool Qt::openUrlExternally(url target) + + Attempts to open the specified \c target url in an external application, based on the user's + desktop preferences. Returns true if it succeeds, and false otherwise. + + \warning A return value of \c true indicates that the application has successfully requested + the operating system to open the URL in an external application. The external application may + still fail to launch or fail to open the requested URL. This result will not be reported back + to the application. */ ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx) { @@ -1723,7 +1730,7 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx) QV8Engine *v8engine = ctx->d()->engine->v8Engine; QString context; if (QQmlContextData *ctxt = v8engine->callingContext()) { - QString path = ctxt->url.toString(); + QString path = ctxt->urlString(); int lastSlash = path.lastIndexOf(QLatin1Char('/')); int lastDot = path.lastIndexOf(QLatin1Char('.')); int length = lastDot - (lastSlash + 1); |