diff options
Diffstat (limited to 'src/qml')
29 files changed, 311 insertions, 230 deletions
diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp index f3ba20538d..b37a7335a0 100644 --- a/src/qml/debugger/qqmldebugservice.cpp +++ b/src/qml/debugger/qqmldebugservice.cpp @@ -215,7 +215,7 @@ QList<QObject*> QQmlDebugService::objectForLocationInfo(const QString &filename, } else { QQmlData *ddata = QQmlData::get(iter.value()); if (ddata && ddata->outerContext) { - if (QFileInfo(ddata->outerContext->urlString).fileName() == filename && + if (QFileInfo(ddata->outerContext->urlString()).fileName() == filename && ddata->lineNumber == lineNumber && ddata->columnNumber >= columnNumber) { objects << *iter; diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index b0c0995a44..da01d00f17 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -391,7 +391,7 @@ QQmlEngineDebugService::objectData(QObject *object) QQmlData *ddata = QQmlData::get(object); QQmlObjectData rv; if (ddata && ddata->outerContext) { - rv.url = ddata->outerContext->url; + rv.url = ddata->outerContext->url(); rv.lineNumber = ddata->lineNumber; rv.columnNumber = ddata->columnNumber; } else { @@ -762,7 +762,7 @@ bool QQmlEngineDebugService::setMethodBody(int objectId, const QString &method, int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex); QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine(object)->handle()); QV4::Scope scope(v4); - QV4::ScopedValue v(scope, QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->url.toString(), lineNumber)); + QV4::ScopedValue v(scope, QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber)); vmeMetaObject->setVmeMethod(prop->coreIndex, v); return true; } diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index ba85a76277..5c994b112f 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -112,11 +112,11 @@ Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE); class QQmlProfiler : public QObject, public QQmlProfilerDefinitions { Q_OBJECT public: - void startBinding(const QString &fileName, int line, int column) + void startBinding(const QQmlSourceLocation &location) { m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeLocation), 1 << Binding, - fileName, line, column)); + location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column))); } // Have toByteArrays() construct another RangeData event from the same QString later. @@ -201,11 +201,11 @@ struct QQmlProfilerHelper : public QQmlProfilerDefinitions { }; struct QQmlBindingProfiler : public QQmlProfilerHelper { - QQmlBindingProfiler(QQmlProfiler *profiler, const QString &url, int line, int column) : + QQmlBindingProfiler(QQmlProfiler *profiler, const QV4::FunctionObject *function) : QQmlProfilerHelper(profiler) { Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler, - startBinding(url, line, column)); + startBinding(function->sourceLocation())); } ~QQmlBindingProfiler() diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 09d7393da9..9330f10780 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -166,7 +166,7 @@ Heap::CallContext::CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::F callData->argc = 0; callData->thisObject = Primitive::undefinedValue(); - strictMode = true; + strictMode = false; outer = function->scope(); activation = qml->d(); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 8c0df3ef04..cbfac86e9f 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -308,6 +308,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.asObject()); functionClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_Prototype); + simpleScriptFunctionClass = functionClass->addMember(id_name, Attr_ReadOnly, &index); + Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Name); + simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length, Attr_ReadOnly, &index); + Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Length); protoClass = emptyClass->addMember(id_constructor, Attr_NotEnumerable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor); @@ -1738,9 +1742,8 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da { QV4::Scoped<QV4::QQmlValueTypeWrapper> vtw(scope, value); - if (vtw && vtw->d()->metaType == type) { - vtw->toGadget(data); - return true; + if (vtw && vtw->typeId() == type) { + return vtw->toGadget(data); } } diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index bcb74ab694..f01579be71 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -169,6 +169,7 @@ public: InternalClass *arrayClass; InternalClass *functionClass; + InternalClass *simpleScriptFunctionClass; InternalClass *protoClass; InternalClass *regExpExecArrayClass; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 5be638e909..7006a8892d 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -210,6 +210,18 @@ bool FunctionObject::isBoundFunction() const return d()->vtable == BoundFunction::staticVTable(); } +QQmlSourceLocation FunctionObject::sourceLocation() const +{ + if (isBinding()) { + Q_ASSERT(as<const QV4::QQmlBindingFunction>()); + return static_cast<QV4::Heap::QQmlBindingFunction *>(d())->bindingLocation; + } + QV4::Function *function = d()->function; + Q_ASSERT(function); + + return QQmlSourceLocation(function->sourceFile(), function->compiledFunction->location.line, function->compiledFunction->location.column); +} + DEFINE_OBJECT_VTABLE(FunctionCtor); Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope) @@ -447,21 +459,27 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData) DEFINE_OBJECT_VTABLE(SimpleScriptFunction); Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto) - : Heap::FunctionObject(scope, function, createProto) + : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype.asObject()) { + this->scope = scope->d(); + this->function = function; function->compilationUnit->addref(); Q_ASSERT(function); Q_ASSERT(function->code); - // global function - if (!scope) - return; - Scope s(scope); ScopedFunctionObject f(s, this); - f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount())); + if (createProto) { + ScopedString name(s, function->name()); + f->init(name, createProto); + f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount())); + } else { + f->ensureMemberIndex(s.engine, Index_Length); + memberData->data[Index_Name] = function->name(); + memberData->data[Index_Length] = Primitive::fromInt32(f->formalParameterCount()); + } if (scope->d()->strictMode) { ScopedProperty pd(s); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 3433e7b8ca..252ff40a1a 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -40,6 +40,8 @@ QT_BEGIN_NAMESPACE +struct QQmlSourceLocation; + namespace QV4 { namespace Heap { @@ -87,6 +89,10 @@ struct IndexedBuiltinFunction : FunctionObject { }; struct SimpleScriptFunction : FunctionObject { + enum { + Index_Name = FunctionObject::Index_Prototype + 1, + Index_Length + }; SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto); }; @@ -140,6 +146,8 @@ struct Q_QML_EXPORT FunctionObject: Object { bool isBinding() const; bool isBoundFunction() const; + QQmlSourceLocation sourceLocation() const; + static void markObjects(Heap::Base *that, ExecutionEngine *e); }; diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 7a5890f8c4..50efff001d 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1835,7 +1835,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) if (!wrapper) return Encode::undefined(); - object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadget()); + object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadgetPtr); } QQmlPropertyData method; diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index ff794f5f09..f223d099e4 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->asFunctionObject()->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 2498e5acc9..b2d03bc188 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -82,7 +82,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 +200,9 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty 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 +310,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/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 3ac0f23e4d..02bd1c4b83 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..cbbd88f1fc 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +class 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 a32dc9e0a9..4c86e6a307 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); @@ -126,7 +127,7 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext) _ddata = 0; _propertyCache = 0; _vmeMetaObject = 0; - _qmlContext = 0; + _qmlBindingWrapper = 0; } QQmlObjectCreator::~QQmlObjectCreator() @@ -174,8 +175,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 +186,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) { @@ -256,20 +244,15 @@ 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); @@ -291,7 +274,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance) qSwap(_qobject, instance); qSwap(_propertyCache, cache); - qSwap(_qmlContext, qmlContext); + qSwap(_qmlBindingWrapper, qmlBindingWrapper); qSwap(_scopeObject, scopeObject); phase = ObjectsCreated; @@ -306,7 +289,6 @@ void QQmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4:: int propertyWriteStatus = -1; void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags }; - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QV4::Scope scope(v4); int propertyType = property->propType; @@ -826,8 +808,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); @@ -946,7 +929,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); @@ -993,8 +975,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) { @@ -1005,7 +988,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); } } @@ -1027,6 +1010,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); @@ -1044,7 +1038,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); @@ -1055,7 +1049,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))); @@ -1078,7 +1072,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))); @@ -1166,24 +1160,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; @@ -1287,7 +1275,6 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * qSwap(_ddata, declarativeData); qSwap(_bindingTarget, bindingTarget); - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QV4::Scope valueScope(v4); QV4::ScopedValue scopeObjectProtector(valueScope); @@ -1332,7 +1319,8 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * } } - setupFunctions(); + if (_compiledObject->nFunctions > 0) + setupFunctions(); setupBindings(bindingSkipList); qSwap(_vmeMetaObject, vmeMetaObject); diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 3886155786..fcf247be5a 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -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; @@ -139,7 +142,7 @@ private: 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 931adb9a13..ae452b727e 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/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 d3a80f0ee2..397068f5d9 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().asObject(); @@ -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(Managed *m, String *name, bool *hasPrope 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 0b8c30d0d5..cad48e661c 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(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 09a113dcc9..f53b9a0c7d 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1729,7 +1729,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); |